Calabrio Call Recording
The call recording function of b+s Connects for Dynamics has the following features:
- Buttons in the agent UI to pause/resume recording and to save/delete the current recording segment.
- Saving the recording URL in the phone call record.
- Saving the ID of the phone call record into the metadata of the recording.
- Optionally assigning hoteling user to the current device.
The Calabrio Call Recording feature needs to be activated and configured in the Service Layout settings.
Prerequisites
- Configured Calabrio Cloud or On-Prem 11.5.
- Knowledge of any proxy product in this documentation. An example configuration is outlined for the Azure API management service.
- Knowledge of Cross-Origin Resource Sharing (CORS). More information: Cross-Origin Resource Sharing (CORS) on MDN.
- Knowledge of Cookie handling in Browsers, especially the SameSite attribute. More information: Set-Cookie Attributes on MDN.
- Understanding of Cross-Site Request Forgery attacks. More information: CSRF Prevention.
Configuration
Create an API user
This integration requires Calabrio ONE Authentication to be enabled and an API User configured properly. An API user is configured the same as a system administrator, but the purpose of this user is to enable third-party applications to authenticate with Calabrio ONE.
You will also have to specify the username and password of this API User in Service Layout settings as Server Login Username
and Server Login Password
.
Write phone call record ID to Calabrio
b+s Connects for Microsoft Dynamics allows you to save the phone call record ID into the metadata of the corresponding Calabrio recording.
In order to do that, a metadata field of type Text
has to be configured in the Calabrio Metadata Manager.
You will also have to specify this field key in Service Layout settings as Metadata Key
.
Write Calabrio recording URL to phone call record
b+s Connects for Microsoft Dynamics allows you to save the Calabrio call recording URL to the corresponding phone call record.
For information about the configuration please refer to Service Layout settings.
Configure Calabrio users and devices
Calabrio users can be set up in two modes:
- Fix Device assignment
- Hoteling User (shared desk)
Fix device assignment
The devices can be assigned in Calabrio Device Associations directly to CCE/CCX users.
Hoteling user (shared desk)
If the same device is used by multiple agents, you can configure the devices in Calabrio for hoteling users. The device is assigned in Calabrio Device Associations to a default hoteling user and can then be temporarily re-assigned to the specific hoteling users of the agents. When the agent logs in to Finesse with a specific extension, this extension will be re-assigned by performing an additional login with the hoteling user to Calabrio.
b+s Connects for Microsoft Dynamics therefore needs to know the user name of the agents hoteling user in order to automatically process the login. These hoteling user names have the format of an email address and are stored in the Connects Agent record.
Configure CORS and SameSite
In order to use Calabrio ONE from the *.dynamics.com
domain, CORS headers must be set and Cookie attributes (SameSite) must be manipulated. The required configuration for Cloud and On-Prem differ, please consult the respective chapter for your deployment type.
On-Prem
For on-prem configuration please see Annex I CORS and Annex II SameSite.
Cloud
This is a possible solution for Calabrio Cloud by utilizing the Azure API Management service; although any proxy on-premise or Cloud, which is capable of setting CORS headers and manipulating HTTP Headers, can be utilized.
Step 1: Create an API Management service.
For production purposes a suitable pricing tier should be selected.
Step 2: Define a new HTTP API.
Step 3: Create an HTTP API.
Set Web service URL to https://partners.calabriocloud.com
, provide any value for the remaining required fields and click on "Create".
Step 4: Add an operation, provide the following properties and save your change.
Field | Description |
---|---|
Display name | authorize |
Name | authorize |
URL | POST, /api/rest/authorize |
Step 5: Add an operation, provide the following properties and save your change.
Field | Description |
---|---|
Display name | contactBasicSearch |
Name | contactBasicSearch |
URL | GET, /api/rest/recording/contactBasicSearch |
Step 6: Add an operation, provide the following properties and save your change.
Field | Description |
---|---|
Display name | recordingcontrols |
Name | recordingcontrols |
URL | POST, /api/rest/recordingcontrols/* |
Step 7: Add the following CORS and Set-Header statements to the inbound
section for All operations
, adjust the origin(s) to reflect your Dynamics 365 URL(s).
<policies>
<inbound>
<base />
<cors allow-credentials="true">
<allowed-origins>
<origin>https://<yourorg>.crm<num>.dynamics.com</origin>
</allowed-origins>
<allowed-methods>
<method>*</method>
</allowed-methods>
<allowed-headers>
<header>*</header>
</allowed-headers>
<expose-headers>
<header>*</header>
</expose-headers>
</cors>
<set-header name="Origin" exists-action="delete" />
<set-header name="Ocp-Apim-Subscription-Key" exists-action="delete" />
<set-header name="Referer" exists-action="delete" />
</inbound>
...
</policies>
Step 8: Add the following Set-Header node to the outbound
section for the authorize
operation.
<policies>
...
<outbound>
<set-header name="Set-Cookie" exists-action="override">
<value>@{
var s = context.Response.Headers.GetValueOrDefault("Set-Cookie","");
return s.Substring(s.IndexOf("AWSALB="), s.IndexOf("AWSALBCORS=")-1);
}</value>
<value>@{
var s = context.Response.Headers.GetValueOrDefault("Set-Cookie","");
return s.Substring(s.IndexOf("AWSALBCORS="), s.IndexOf("JSESSIONID=")-s.IndexOf("AWSALBCORS=")-1);
}</value>
<value>@{
var s = context.Response.Headers.GetValueOrDefault("Set-Cookie","");
return s.Substring(s.IndexOf("JSESSIONID="), s.IndexOf("hazelcast.sessionId=")-s.IndexOf("JSESSIONID=")-1);
}</value>
<value>@{
var s = context.Response.Headers.GetValueOrDefault("Set-Cookie","");
return s.Substring(s.IndexOf("hazelcast.sessionId="), s.Length-s.IndexOf("hazelcast.sessionId=")) + "; SameSite=None";
}</value>
</set-header>
<base />
</outbound>
...
</policies>
Annex I - CORS (Cross Origin Resource Sharing)
Guides
The following documents can be consulted to help define the terms CORS and CSRF used in this documentation.
Abbreviation | Name | Link |
---|---|---|
CORS | Cross-Origin Resource Sharing | https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS |
CSRF | Cross-Site Request Forgery | https://infosec.mozilla.org/guidelines/web_security#csrf-prevention |
Allowing HTTP requests from Cross Site resources in Calabrio
Making the changes suggested in this guide will allow external resources to access Calabrio. Therefore, it is recommended to read the documents listed above beforehand. In addition, it is recommended that before making any changes, all configuration files are backed up for possible recovery.
The following changes may cause Calabrio Web Services to become unresponsive if not performed properly. Please Note: This solution only applies to on-premise deployments of Calabrio and cannot be performed on application servers hosted in the cloud.
This requires a restart of Calabrio Web Server Services to apply the changes. It is recommended to schedule a downtime window to test and restore changes if necessary.
Allow CORS requests to Calabrio Application Server
In this example, the goal is to allow all CORS requests from the following website:
https://fiddle.jshell.net
In your environment, replace this with the origin that your traffic originates from.
- Back up your httpd.conf file. For a standard Calabrio installation, the file is located here:
C:\Program Files\Common Files\Calabrio ONE\Server\config
Find the XML tag for
<VirtualHost *:443>
in the httpd.conf file.Add the following re-write rules:
RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule ^(.*)$ $1 [R=200,L]
This change will allow Pre-Flight requests to return with a Status of 200 allowing the application to send a follow up request.
- Add CORS rules to allow certain protocols and methods of access to the request.
Note: Modify the following lines in your website's origin. This must include the http/https requirements.
Header always set Access-Control-Allow-Origin "https://fiddle.jshell.net"
Header always set Access-Control-Allow-Credentials "true"
Note: Apache does not support multiple origins in this field or additional entries, consult Apache Documentation for additional options if this method is not applicable.
Header always set Access-Control-Allow-Origin "https://fiddle.jshell.net"
Header always set Access-Control-Allow-Credentials "true"
Header always set Access-Control-Allow-Methods "POST,GET,OPTIONS,DELETE,PUT"
Header always set Access-Control-Max-Age "3600"
Header always set Access-Control-Allow-Headers "X-Requested-With, Content-Type, Origin,
Authorization, Accept, Client-Security-Token, Accept-Encoding"
Full example:
<VirtualHost *:443>
#Protocols h2 http/1.1
ServerName localhost
SSLEngine on
SSLCertificateFile "C:/Program Files/Common Files/Calabrio One/Server/config/localhost.crt"
SSLCertificateKeyFile "C:/Program Files/Common Files/Calabrio One/Server/config/localhost.key"
SSLUseStapling on
RewriteEngine On
#Disable TRACE and TRACK http methods
RewriteCond %{REQUEST_METHOD} ^(TRACE|TRACK)
RewriteRule .* - [F]
RewriteRule ^/$ https://%{HTTP_HOST}/index.html [R=301]
RewriteRule ^/login/index.html$ https://%{HTTP_HOST}/index.html [R=301]
RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule ^(.*)$ $1 [R=200,L]
Header always set Access-Control-Allow-Origin "https://fiddle.jshell.net"
Header always set Access-Control-Allow-Credentials "true"
Header always set Access-Control-Allow-Methods "POST,GET,OPTIONS,DELETE,PUT"
Header always set Access-Control-Max-Age "3600"
Header always set Access-Control-Allow-Headers "X-Requested-With, Content-Type, Origin,
Authorization, Accept, Client-Security-Token, Accept-Encoding"
- Save the file and restart The following Calabrio services:
- Calabrio ONE Application Server
- Calabrio ONE Web Server
Allow CSRF requests to Calabrio Application Server
This step will need to be applied to each Calabrio Application server in your environment.
- Backup the following registry section:
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Apache Software Foundation\Procrun 2.0\ciWFOTomcat\
\Parameters\Java
- Modify the "Options" key to include the following line:
-Dsecondary.public.hosts={HOST MAKING REQUEST}
If you are using https://jsfiddle.net/ to make your request, edit the request as shown below:
-Dsecondary.public.hosts=fiddle.jshell.net
The following print screen shows the changes made in this example:
If there is more than one host, the values can be separated with a comma.
- Restart The following Calabrio services:
- Calabrio ONE Application Server
- Calabrio ONE Web Server
Allow CORS requests to the Calabrio Data Server
- Backup the following file:
C:\Program Files\Calabrio ONE\Data Server\Tomcat\conf\web.xml
- Append the following attributes to your web.xml file.
<filter>
<filter-name>CorsFilter</filter-name>
<filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
<init-param>
<param-name>cors.allowed.origins</param-name>
<param-value>*</param-value>
</init-param>
<init-param>
<param-name>cors.allowed.methods</param-name>
<param-value>GET,POST,HEAD,OPTIONS,PUT</param-value>
</init-param>
<init-param>
<param-name>cors.allowed.headers</param-name>
<param-value>Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,
Access-Control-Request-Headers</param-value>
</init-param>
<init-param>
<param-name>cors.exposed.headers</param-name>
<param-value>Access-Control-Allow-Origin,Access-Control-Allow-Credentials</param-value>
</init-param>
<init-param>
<param-name>cors.support.credentials</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>cors.preflight.maxage</param-name>
<param-value>10</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CorsFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
- Restart the following Calabrio service:
- Calabrio ONE Data Server Web Services
Testing
This test can be used to validate that the filter is blocking/allowing traffic from specific origins. In this example CSRF and CORS traffic was allowed from the origin https://jsfiddle.net/
.
- Navigate to
https://jsfiddle.net/
- Paste the following code into the "Javascript" window:
var settings = {
"url": "https://yourCalabrioAddress/api/rest/authorize",
"method": "POST",
"timeout": 0,
"headers": {
"Content-Type": "application/json"
},
"data": JSON.stringify({"userId":"yourUser@email.com","password":"YourPassword","locale":"en"}),
};
$.ajax(settings).done(function (response) {
console.log(response);
});
- Modify the script to point to your Calabrio deployment with a valid username/password.
- Modify the JSFiddle settings to point to the proper JavaScript frameworks to support this code snippet. Select the drop down for a menu. Note: This setting is in the pane for "Javascript" on the site. (You can see this same option in Step 3's screenshot in the top left corner).
- Open your browser's Developer console -- and press the "Run" button for Jsfiddle.
If your test was successful you should see Status "200" back on your authentication (Network tab) and session details logged to the console.
You will see two authorize events since one is the "Pre-Flight" request to validate what the server allows and the other is the actual payload with our javascript request.
Your developer console will show:
How to determine your "Origin"
To capture your "Request-Origin" you will need to inspect the payload you are sending -- All HTTP Requests will have "Request Headers" set -- The browser will automatically set this particular header for us.
Inspecting the request in Developers tools will show us a "Request Headers" Section under the "Headers" pane. The "Origin" is the element of interest.
Annex II - SameSite
SameSite is a cookie attribute. The Recording Toolbar sends an authorize request to the Calabrio application server and it responds with a token that is stored into a cookie (set-cookie response header). Whenever a request is sent to the Calabrio domain, the cookie is attached to the request and the Calabrio server can validate the token. With the latest browser versions, all cookies without a SameSite=None attribute are defaulted to 'lax' which prevents the browser from sending the cookie in a cross-domain request.
The solution is to inject SameSite=None to the cookie attributes from the On Prem Calabrio Application server.
Open the previously modified httpd.conf
file located in the standard Calabrio installation folder
C:\Program Files\Common Files\Calabrio ONE\Server\config
from the Calabrio Application server and check that
LoadModule headers_module modules/mod_headers.so
is added to the LoadModule list.
Check that it does not have a #
at the beginning of the line.
Add the following chunk of code after the LoadModule list:
<ifmodule mod_headers.c>
Header always edit Set-Cookie (.*) "$1; SameSite=None"
Header onsuccess edit Set-Cookie (.*) "$1; SameSite=None"
Header edit Set-Cookie ^(.*);\s?SameSite=None;?\s?(.*);\s?SameSite=None;?\s?(.*)$ "$1; $2; $3; SameSite=None"
Header edit Set-Cookie ^(.*);\s?;\s?(.*)$ "$1; $2"
</ifmodule>
Restart the Calabrio One Application Server
and the Calabrio One Web Server
services.