Webhooks
Introduction to Webhooks in ConSol CM
Webhooks allow easy integration of ConSol CM with external applications, as shopping applications, social media platforms, chat tools, or customer-built applications. The applications can send data to ConSol CM using HTTP POST requests. ConSol CM processes the received data and returns a response to the requesting application.
Concepts, terms and definitions
Concept |
Other terms |
Definition |
---|---|---|
webhook |
Mechanism to allow communication between ConSol CM and external applications | |
security provider | Mechanism to check if the data received by the webhook comes from an authorized application | |
content type | Format of the data sent using HTTP POST requests |
Purpose and usage
Webhooks enable ConSol CM to communicate with external applications using HTTP POST requests. The ConSol CM webhook module provides services for these integrations. You can integrate several applications at the same time. In addition, webhooks are used for web forms
The basic steps of the information transfer using webhooks are:
- The external application sends a HTTP request to the webhook service in ConSol CM.
- The request is processed by the webhook. The functionalities of the service are implemented in a script.
- The response is sent back to the requesting application which processes the response.
The following figure illustrates the interaction between the external application and ConSol CM:
Figure 438: Webhooks in ConSol CM
Usage examples:
- Update data in ConSol CM based on master data managed in an ERP system.
- Integrate a social media platform to import customer data into ConSol CM.
- Use web forms for creating cases and adding content.
Available settings for webhooks
Supported content types
The HTTP POST requests which are sent by the requesting application can have the following content types:
- application/json
- application/x-www-form-urlencoded
- multipart/form-data
The response which is returned to the requesting application always has the content type application/json. It can contain custom-defined objects of the following types:
- httpStatusCode
- httpHeaders
- body
Security providers
The following settings exist for webhooks:
- Enabled: Select this checkbox to enable the webhook.
- IP-based filtering
- Select the checkbox Enabled to enable IP-based filtering as a security provider.
- Enter the IP addresses in CIDR notation in the field below, see Valid range of IP addresses.
- Secret tokens
- Select the checkbox Enabled to enable secret tokens as a security provider.
- Select the checkbox HMAC to use a secure hash for message authentication. Only supported for the content types application/json and application/x-www-form-urlencoded.
- Enter the name of the HTML header for the shared secret. The default value is “SECRET_TOKEN”.
- Enter the secret tokens in the field below. You can enter one token per line, see Secret tokens.
If both security providers are configured, they are checked in the following order:
- First the IP address is checked. If it is in the permitted range, the request can proceed.
- If the IP address is not in the required range, the secret token is checked subsequently. If it is correct, the request can proceed as well.
- If neither of the two criteria is met, the request is rejected with an authorization failed message.
There is no other mandatory access validation beyond the security providers, specifically no login-based authentication, as for users, which imposes additional access restrictions. The interface has full system access, so securing it additionally with a proxy is mandatory for real-life usage.
It is highly recommended to use HTTPS as a communication protocol for transferring data using a ConSol CM webhook.
Valid range of IP addresses
The IP-based filter uses a list of IP address ranges defined in the CIDR notation (Classless Inter-Domain Routing). A valid entry in this notation is an IP address followed by a slash separating it from a number of bits defining the subnet mask. The example 10.20.30.40/24 stands for the IP address 10.20.30.40 and its subnet mask 255.255.255.0. The address list for service configuration allows multiple IP ranges in this notation with each range entry on a separate line.
Secret tokens
The checkbox HMAC activates the validation of the request by a mandatory hash based on the token. The HMAC (Hash-based Message Authentication Code) value is derived from the unencrypted payload and the secret token. This code is transferred in the header of the request and decrypted by the server using the secret token. The only hashing algorithm supported by ConSol CM in this case is SHA-1. MD5 is not supported.
A corresponding hashing of the response is currently not supported.
The input field Header allows to define the HTTP header field name which shall be used to transfer the shared secret token. The value defaults to SECRET_TOKEN, but it is recommended to change this value. A non-standard name can mean a security improvement.
The script can access the used token in the headers map of the HTTP request, which contains a field named as defined in the webhook configuration under Headers.
The service behavior is completely based on the implementation of the corresponding script, i.e., the security based on the provided tokens has to be implemented and is not system-immanent!
Creating a webhook
The following steps are necessary to create a webhook:
-
Write a script of the type Integration to implement the logic of the webhook. This script has to process the data received from the external application and send a response to the application. See Writing the integration script.
-
Define a security provider which checks the requests. This can be a range of valid IP addresses or a secret token, see Configuring the webhook service and Security providers.
The service URL which receives the POST requests is:
https://<CM server address>/intg/<script name>/service
Writing the integration script
You need to create a script of the type Integration to process the data received from the external application and send a response to the application. The name of this script (without the extension .groovy) is the name of the service, which is part of the URL to access the interface.
Example:
- Script name: myWebHook.groovy
- Service URL: https://<CM server address>/intg/myWebHook/service
The script is executed in an administrative context for processing a request, so that it has full system access.
The integration script consists of two parts:
- Process the request, see Processing the received data.
- Generate the response, see Creating the response
Processing the received data
The first step for processing the received data is determining the content type of the payload. Either you already know which content type is used by the requesting application or you check the content type within the script:
- application/json
The payload is a String object in JSON format. - application/x-www-form-urlencoded
The payload is a MultiValueMap object. - multipart/form-data
The payload is a MultipartData object.
Once the content type has been determined, you can process the data to create or update objects in ConSol CM.
Creating the response
Scripts of type Integration must return an object of the class IntgServiceResponse, which can include the following information:
- httpStatusCode
Optional. Defines the HTTP status code. If not provided, the following supported default status codes are used:- 200 (OK)
- 401 (Unauthorized)
One or more security provider is enabled, but the data provided by the client did not match the expected data (e.g., wrong token or IP address) - 404 (Not Found)
A script for a webhook with the given name could not be found / webhook is disabled / no security provider is enabled for the webhook - 405 (Method Not Allowed)
Any HTTP method other than POST - 500 (Internal Server Error)
Any problems / exceptions on the server side (ConSol CM)
- httpHeaders
Optional. Defines the response header. Only required if you want to define a specific httpHeader, i.e., one which is not part of the supported standard headers. - body
Optional. Defines the content of the response. If not provided, the response is empty. This is the object which can contain a JSON statement, see Coding Example.
Permissions
The webhook script is executed with administrator privileges. This means that all operations performed in the script are executed with these permissions. If this is not desired, the script can include the credentials of another user and some code to downgrade the session to the user’s privileges. The method executeWithUserPermissions of the class SecurityTemplate is used for this purpose.
The following code example shows the usage of this method in a script. The session is downgraded to the permissions of the user identified by the login and password included in the JSON payload. Then, a customer search for the customer with the ID “12345” is performed with these permissions.
import com.consol.cmas.common.security.template.SecurityCallbackWithoutResult;
import com.consol.cmas.common.security.template.SecurityTemplate;
import groovy.json.JsonSlurper
def jsonSlurper = new JsonSlurper()
def message = jsonSlurper.parseText(payload);
SecurityTemplate.executeWithUserPermissions(message.login, message.password, new SecurityCallbackWithoutResult() {
@Override
public void doInSecurityContextWithoutResult() {
unitService.getById(12345)
}
});
Code example 90: Example of downgrading the session to a user’s privileges
Configuring the webhook service
The configuration page is available at the following URL:
https://<CM server address>/intg/<script name>/config
You need to log in with an administrator account. The configuration page allows to enable the webhook and define the security providers. Both steps are mandatory to use the webhook. See Security providers for details.
Testing the service
A simple way of testing your service is using a REST plugin in your browser:
- Set the required content type in the header, e.g. application/json.
- Enter the request content in the body using the syntax required by the content type, e.g. {"ticket": "100200"} to retrieve a case
- using JSON.
- Send a POST request to the service URL: https://<CM server address>/intg/<script name>/service
The response is returned as JSON. If the case is found, the response contains the case information defined in the script. Otherwise, the defined error message is returned.
Alternatively, you can also use CURL to test the service:
# Linux:
curl -X POST https://myserver.consol.de:8080/intg/myWebHook/service //
-H 'content-type: application/json' //
-d '{"ticket": "100200"}'
# Windows (note the different quoting/escaping for the -d option):
curl -X POST https://myserver.consol.de:8080/intg/myWebHook/service //
-H "content-type: application/json" //
-d "{\"ticket\": \"100200\"}"
The request payload in this example is the value of the -d option.
The following example shows the response generated by the script and returned to the requesting application:
{
"status" : "OK" ,
"ticket" : "100200" ,
"subject" : "New Ticket for Resource 3" ,
"engineer" : "Susan ServiceDesk"
}
Coding Example
The following example shows the implementation of a service named myWebHook. The script is called myWebHook.groovy and is stored in the script section of the Web Admin Suite / Admin Tool. It returns a JSON object with case number, subject, and assigned user as a response on a request with the case number.
import com.consol.cmas.intg.service.IntgServiceResponse
import groovy.json.JsonSlurper
import groovy.json.JsonOutput
import com.consol.cmas.common.service.TicketService
def jsonSlurper = new JsonSlurper()
def message = jsonSlurper.parseText(payload)
def ticketname
def ticketsubject
def engineername
def OK = false
if (message.ticket) {
ticket = ticketService.getByName(message.ticket)
if (ticket) {
ticketname = message.ticket
ticketsubject = ticket?.getSubject()
if (ticket.engineer) {
engineername = ticket.engineer.getFirstname() + " " + ticket.engineer.getLastname()
}
OK = true
}
}
def response = new IntgServiceResponse()
if (OK) {
response.httpStatusCode = 200
response.body = JsonOutput.toJson([ticket: ticketname, subject: ticketsubject, engineer: engineername]) // optional
} else {
response.httpStatusCode = 404
response.httpHeaders = ['Content-Language':'en', 'Warning':'Required oject not found']
}
return response
Code example 91: Example script which implements a webhook service