Enforce identity verification on all platforms to prevent third parties from impersonating logged-in users. Once enabled, Gleap will require you to pass the correct user hash in order to identify users.
For private conversation attachments, also follow Authenticated conversation files. That guide covers the compatible SDK, customer application URL and preserving attachment links through login. Identity verification alone does not enable protected file storage.
User hash generation
To set up identity verification, you'll need to generate an HMAC on your server for each logged-in user and send it to Gleap.
Please choose your server stack to show an example code for the user hash generation.
const crypto = require('crypto');
const hmac = crypto.createHmac('sha256', 'YOUR-SECRET'); // secret key (keep it safe!)
const userIdAsString = String(user.id); // convert user's id to string
const userHash = hmac.update(userIdAsString).digest('hex'); // generate hashOpenSSL::HMAC.hexdigest(
'sha256', # hash function
'YOUR-SECRET', # secret key (keep safe!)
current_user.id.to_s # user's id
)import hmac
import hashlib
hmac.new(
b'YOUR-SECRET', # secret key (keep it safe!)
bytes(request.user.id, encoding='utf-8'), # user's id
digestmod=hashlib.sha256 # hash function
).hexdigest()$userHash = hash_hmac(
'sha256', // hash function
$user->id, // user ID
'YOUR-SECRET' // secret key (keep it safe!)
);Signed identity token (proves the email too)
The user hash above proves the user ID only. If you also sign the user's email, Gleap knows the email really belongs to this user. That is what lets Gleap bring the person's earlier conversations together (see Merge contacts).
Instead of the user hash, create a JSON Web Token (HS256) with the same secret key and pass it in the same place. Every SDK accepts it as the user hash, so no SDK update is needed, and existing app versions keep working.
Claim | |
|---|---|
| Required. The user ID you pass to identify, as a string. |
| Optional. Only put an email in the token that your system has confirmed (sign-up confirmation, SSO). Signing it means you vouch for it. |
| Optional. Once the token has expired it still identifies the user, but no longer proves the email. |
const jwt = require('jsonwebtoken');
const userHash = jwt.sign(
{ user_id: String(user.id), email: user.email },
'YOUR-SECRET', // secret key (keep it safe!)
{ algorithm: 'HS256' }
);use Firebase\JWT\JWT; // composer require firebase/php-jwt
$userHash = JWT::encode(
['user_id' => (string) $user->id, 'email' => $user->email],
'YOUR-SECRET', // secret key (keep it safe!)
'HS256'
);import jwt # pip install PyJWT
user_hash = jwt.encode(
{"user_id": str(user.id), "email": user.email},
"YOUR-SECRET", # secret key (keep it safe!)
algorithm="HS256",
)# gem 'jwt'
JWT.encode(
{ user_id: current_user.id.to_s, email: current_user.email },
'YOUR-SECRET', # secret key (keep safe!)
'HS256'
)// dotnet add package System.IdentityModel.Tokens.Jwt
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("YOUR-SECRET"));
var token = new JwtSecurityToken(
claims: new[] { new Claim("user_id", user.Id.ToString()), new Claim("email", user.Email) },
signingCredentials: new SigningCredentials(key, SecurityAlgorithms.HmacSha256));
var userHash = new JwtSecurityTokenHandler().WriteToken(token);Then pass the token as the user hash, with the same email in the user data:
Gleap.identify("user_19283", { name: "Franz", email: "[email protected]" }, "SIGNED_IDENTITY_TOKEN");The token works everywhere the user hash works, including enforced identity verification and authenticated conversation files.
A token whose email differs from the email you send identifies the user, but proves no email.
An email sent without a token is saved as before, but never counts as proven.
Merge contacts
The same person can end up as several contacts: an email to your support address creates one, a website chat without login another, your app login a third. Gleap brings them together in these cases. Contacts with their own user ID are never merged into each other.
Case | How |
|---|---|
Same device: a visitor chats, then logs in | Automatic, always on. |
Your server creates the user |
|
The user logs in with a signed email | Turn on Settings → User identity → Merge contacts by email. Every contact without a user ID that has this email joins the user, once per user and email. Off by default. |
Your server decides |
|
A website visitor confirms the email with a code | The "Verify email" workflow step. If a user with this email exists and your server or a signed token proved that email, the chat moves to the user. |
Conversations, messages and survey answers move to the user. Details the user doesn't have yet, such as the company, only come from contacts your server or an inbound email created.
Identify user with user hash
After generating the user hash you need to send it to your client and pass it to the Gleap SDK.
Gleap.identify("user_19283", {
name: "Franz",
email: "[email protected]",
}, "GENERATED_USER_HASH");let userProperty = GleapUserProperty()
userProperty.name = "Franz"
userProperty.email = "[email protected]"
Gleap.identifyUser(with: "user_1234", andData: userProperty andUserHash: "GENERATED_USER_HASH")GleapUserProperties userProperties = new GleapUserProperties();
userProperties.setEmail("[email protected]");
userProperties.setName("Franzi");
userProperties.setPhone("+1 (902) 123123");
userProperties.setValue(199.95);
userProperties.setHash("GENERATED_USER_HASH");
Gleap.getInstance().identifyUser("12334", userProperties);Gleap.identifyWithUserHash('12334', {
name: 'Franz',
email: '[email protected]',
}, 'GENERATED_USER_HASH');Gleap.identifyWithUserHash(
userId: '12345',
userProperties: GleapUserProperty(name: 'Franz', email: '[email protected]'),
'GENERATED_USER_HASH',
);
