The messenger widget has 3 levels of authentication:
- Anonymous identity
- Claimed identity
- Verified identity
The minimum required level of user identification to start a conversation is determined
by a setting on Dixa's agent interface (by an admin). The default level is set to anonymous
.
Anonymous identity
This is the default state of the messenger. The user is not identified and the messenger will not be able to provide any information about the user to the agent. The user will be able to start a conversation only if the minimum identification level is set to anonymous
.
Claimed identity
This is the state when the user has identified themselves but we haven't verified their claim. If the minimum identification level is set to claimed
in the settings page, then the user can identify themselves upon attempting to start a new conversation. This will open a form where the user can provide their name and email. The user will be able to start a conversation only if the minimum identification level is set to anonymous
or claimed
. At this level, the agent will be able to see the user's name and email.
Verified identity
This is the state in which the user's identity has been verified. This happens by you informing the messenger of the user's identity upon initialization of the widget. In this case, the user will be able to start a conversation if the minimum identification level is set to anonymous
, claimed
or verified
. At this level, the agent will be able to see the user's name and email and will be notified that the user can be trusted to be who they say they are.
Usage
If you have the required information about a user (let's say the user is logged into your platform) you can provide the necessary information to the messenger so that it can be used for identification purposes. By default, messenger assumes a user is anonymous
unless either you identify the user programmatically at the init
phase, or the user identifies themselves in the messenger. To take advantage of this feature you can pass the user info as an attribute on the options object that you pass to the init
method.
Example:
// verified user identity
_dixa_.invoke('init', {
messengerToken: '<YOUR_DIXA_MESSENGER_TOKEN>',
userIdentity: {
type: 'verified',
payload: {
type: 'jwe',
token: 'SomeJWEToken', // this is a JWT token that contains the user info
},
},
});
// Claim the user identity
_dixa_.invoke('init', {
messengerToken: '<YOUR_DIXA_MESSENGER_TOKEN>',
userIdentity: {
type: 'claimed',
name: userProfile.name, // assuming that you have a userProfile object that contains user info
email: userProfile.email,
},
});
It's also possible to update the user identity after the widget has been initialized by calling the setUserIdentity
command.
Example:
// verified user identity
_dixa_.invoke('setUserIdentity', {
type: 'verified',
payload: { type: 'jwe', token: 'SomeJWEToken' },
});
Note that at this point you can only promote the user identity to a higher level, but not demote it. You can't for example go from verified
state to claimed
.
Also note that if you pass an invalid email address, the messenger will not
allow the user to start a conversation. You can listen to the on-backend-error
event to be notified of this.
Generating a JWE token
As shown in the example above, for a verified user, we need to generate a JWE token. The steps to generate it are:
- Generate the JWE using the key (CEK) from the messenger settings (Dixa -> Settings -> Messenger -> Authentication). You can either use an autogenerated key or use your own and encode it. In case you want to generate your own key, it must be represented as the base64url encoding of the value’s big endian representation as an octet sequence of 64 bytes
- Once you have the key from the settings you can use it to generate a JWE with the required payload, in json format. The following claims are recognized:
-
email
: (required) The email of the user -
name
: (required) The name of the user -
iat
: (required) Issued at, identifies the time at which the JWT was issued -
jti
: (required) JWT ID, it provides a unique identifier for the JWT, it should be randomly generated to prevent collisions. -
external_id
: (optional) External identifier for the user. It will be persisted on the dixa user. - The token must be encrypted using direct use of the shared symmetric key, using the encryption algorithm A256CBC-HS512 (AES256 with CBC mode and HMAC-SHA512)
Example for generating a JWE:
Typescript
import * as jose from 'jose';
const key = '...'; // This is the key generated in Dixa settings page
const secret = jose.base64url.decode(key);
// Define the payload data
const payload = {
// A token unique to this object. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.7
jti: '123e4567-e89b-12d3-a456-426614174000',
// the time at which the JWT was issued
iat: 1516239022,
email: 'example@email.com',
name: 'John Doe',
external_id: 'cb3f0475-40b0-46d5-af29-e68a8e2e992d',
};
const generatedJWEPromise = new jose.EncryptJWT(payload)
.setProtectedHeader({ alg: 'dir', enc: 'A256CBC-HS512' })
.encrypt(secret);
// Log the JWE to the console
generatedJWEPromise
.then((JWE) => console.log('Generated JWE:', JWE))
.catch(() => console.log('failed'));
Java (via nimbus-jose-jwt library)
import com.nimbusds.jose.*;
import com.nimbusds.jose.crypto.DirectEncrypter;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
String key = "..."; // This is the key generated in Dixa settings page
byte[] secret = Base64.getUrlDecoder().decode(key);
JWEHeader header = new JWEHeader(JWEAlgorithm.DIR, EncryptionMethod.A256CBC_HS512);
Map<String, Object> claims = new HashMap<>();
claims.put("email", "example@email.com");
claims.put("name","John Doe");
claims.put("iat",1516239022);
claims.put("jti","123e4567-e89b-12d3-a456-426614174000");
Payload payload = new Payload(claims);
JWEObject jwe = new JWEObject(header, payload);
jwe.encrypt(new DirectEncrypter(secret));
String output = jwe.serialize();
System.out.println("Generated JWE:" + output);