Learn how to set up identity verification on the Glassix chat widget
Identity verification lets you identify end users in the Glassix chat widget without requiring them to re-authenticate. Instead of relying on browser cookies, you can pass user credentials directly to the widget, creating a personalized and secure chat experience.
Overview
By default, the Glassix chat widget uses browser cookies to identify returning users. Chat widget identity verification replaces this cookie-based approach with JSON Web Tokens (JWT), allowing you to:
- Automatically identify logged-in users without additional authentication steps.
- Pre-populate user information, such as email, and additional details in the chat widget.
- Maintain conversation history across devices and sessions.
- Protect sensitive user data by ensuring only authenticated users can access their chat history.
- For example, in an Insurance Portal, when a customer logs in to their insurance account, the chat widget automatically recognizes them. It can access their policy information, claims history, and personal details without requiring another login.
How It Works
The chat widget Identity verification in Glassix uses three key components passed to the widget:
- Unique Identifier: A UUID/GUID that you maintain for each user
- Identity Token: A JWT containing the unique identifier and signed with your department's API secret
When these values are provided to the widget, Glassix:
- Scopes all conversations to that specific user
- Loads the user's profile and conversation history
- Pre-fills ticket fields with user information
You are responsible for managing user identification, storing credentials, and generating JWTs on demand. Glassix only validates and processes the tokens you provide.
Implementation Guide
Step 1: Set Up Your User Database
Create a system to manage unique identifiers for your users. This could be:
- A database table mapping user accounts to UUIDs
- Integration with your existing authentication system
- A third-party identity management service
Requirements:
- Unique identifiers must be valid UUIDs/GUIDs
- Format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
- Must remain consistent for each user across sessions
- Cannot use usernames, email addresses, or other formats
Step 2: Retrieve the User Identifier on Login
When a user logs into your application, retrieve their unique identifier from your database or authentication system.
Step 3: Create the JWT
Generate a JSON Web Token with the required claims. The JWT must be created on demand (not pre-generated) because it includes an expiration timestamp.
Required Claims:
| Name | Description |
|---|---|
| Issuer | UUID. The API key (lowercase) |
| Audience | UUID. The unique identifier of the customer (lowercase) |
| Expiration | Token expiration datetime in UTC. We recommend at least 5 hours from the time of creation. |
The aud (audience) claim in your JWT must match the uniqueIdentifier value you pass to the widget options. This unique identifier must be in a valid UUID format.
You are responsible for generating and storing these UUIDs on your server. The critical requirement is consistency: each user must always receive the same UUID across all login sessions.
Example:
User: [[email protected]]
UUID: db79e775-81fd-4f2e-8741-9266e920cc32
Every time [email protected] logs in, you must provide the UUID db79e775-81fd-4f2e-8741-9266e920cc32. If you generate a different UUID for the same user, they will lose access to their previous conversation history.
The JWT is signed using your department's API secret, not the API key. The API key is used as the
iss(issuer) claim inside the token payload, but the signing secret is a separate credential. Keep your API secret secure and never expose it in client-side code.
Optional Claims
| Name | Description |
|---|---|
| field1 | If a ticket is opened, this value will be set for field1. |
| field2 | If a ticket is opened, this value will be set for field2. |
| field3 | If a ticket is opened, this value will be set for field3. |
| And so on... |
You can also add your own custom claims to the token. These values will be present in the identityTokenClaims object in the ticket details (The max length of the serialized identityTokenClaims to JSON is 500).
Example:
{
"iss": "7cab072d-43d0-4e9d-bb25-2a947696fe8f",
"iat": 1539766700,
"exp": 1571386631,
"aud": "db79e775-84f2e-8741-9266e920cc32",
"sub": "",
"field1" : "John"
}JWT Generation Example:
JWT Generation Example Using Node.js
// Install a JWT library
// npm install jsonwebtoken
const jwt = require('jsonwebtoken');
function generateIdentityToken(uniqueIdentifier, apiKey, apiSecret) {
const payload = {
aud: uniqueIdentifier, // User's UUID
exp: Math.floor(Date.now() / 1000) + (60 * 60), // Expires in 1 hour
};
// Sign with the API SECRET (not the API key)
const token = jwt.sign(payload, apiSecret, {
algorithm: 'HS256',
issuer: apiKey
});
return token;
}
// Usage
const userUuid = 'a1b2c3d4-e5f6-7890-abcd-ef1234567890';
const departmentApiKey = 'your-department-api-key';
const departmentApiSecret = 'your-department-api-secret';
const identityToken = generateIdentityToken(userUuid, departmentApiKey, departmentApiSecret);Alternative: Online JWT Builder
For testing, you can use this Online JWT Builder or another JWT builder:
- Set Algorithm to HS256
- Add payload:
{ "aud": "your-user-uuid", "exp": 1735689600} - Set the issuer to your API key
- Use your API secret as the signing secret
After creating the token, pass it, together with the customer's "uniqueidentifier", like this:
<!-- Start of Glassix Chat Widget -->
<script>
var widgetOptions = {
apiKey: "7cab072d-43d0-4e9d-bb25-2a947696fe8f",
snippetId: "dr548fbb5d61ec51869a",
uniqueIdentifier: "db79e775-81fd-4f2e-8741-9266e920cc32",
identityToken: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJ..."
};
(function(n){var u=function(){GlassixWidgetClient&&typeof GlassixWidgetClient=="function"?(window.widgetClient=new GlassixWidgetClient(n),widgetClient.attach(),window.glassixWidgetScriptLoaded&&window.glassixWidgetScriptLoaded()):f()},f=function(){r.src="https://cdn.glassix.net/clients/widget.1.2.min.js";r.onload=u;document.body.removeChild(t);i.parentNode.insertBefore(r,i)},i=document.getElementsByTagName("script")[0],t=document.createElement("script"),r;(t.async=!0,t.type="text/javascript",t.crossorigin="anonymous",t.id="glassix-widget-script",r=t.cloneNode(),t.onload=u,t.src="https://cdn.glassix.com/clients/widget.1.2.min.js",!document.getElementById(t.id)&&document.body)&&(i.parentNode.insertBefore(t,i),t.onerror=f)})(widgetOptions)
</script>
<!-- End of Glassix Chat Widget -->Step 4: Pass Credentials to the Widget
Provide the unique identifier and identity token to the widget before it launches, or destroy and reattach the widget if it's already loaded.
Step 5: Test the Implementation
Before enabling the "Require Identity Verification" setting, thoroughly test your implementation:
- Verify User Recognition: Log in as different users and confirm the widget loads their correct conversation history
- Check Field Pre-population: Ensure user details are automatically filled in ticket fields
- Test Token Expiration: Confirm the widget handles expired tokens gracefully
Testing Checklist:
- Widget loads with the correct user identity
- Conversation history persists across sessions
- User fields pre-populate correctly
- Widget works without requiring additional authentication
- Token refresh logic works before expiration
- Destroy and reattach functionality works on login/logout
Step 6: Enable "Require Identity Verification" (Optional)
Do NOT enable "Require Identity Verification" until you have:
- Fully implemented JWT generation on all pages with the widget
- Tested the implementation thoroughly
- Prepared to allow it across ALL departments in your workspace
Once enabled, the widget will NOT work without a valid identity token. The browser cookie fallback is completely disabled organization-wide.

What This Setting Does:
- Disables cookie-based user identification completely
- Forces all widgets to require a valid JWT
- Applies to ALL widgets in your workspace, not just one department
- Widget will endlessly load/spin if no identity token is provided
When to Enable:
- You want to enforce security and prevent anonymous widget usage
- All your integration points are ready and tested
- You want to ensure that users must be authenticated to access chat
When NOT to Enable:
- You're still testing the implementation
- You only wish to identity verification on some pages
- You want the widget to work for both authenticated and anonymous users
- You can use identity verification without enabling this checkbox. The widget will use the identity token when provided and fall back to cookies when not.
Complete Implementation Example
The following example shows a complete integration of a Node.js backend and a frontend. It includes a dummy user database lookup, JWT generation signed with the API secret, and the complete widget embed code.
Server-Side: User Lookup and JWT Generation
// server.js
// npm install express jsonwebtoken
const express = require('express');
const jwt = require('jsonwebtoken');
const app = express();
app.use(express.json());
// ---------------------------------------------------------------------------
// Dummy user database
// In production, replace this with a real database query.
// Each user has a stable UUID that must never change across sessions.
// ---------------------------------------------------------------------------
const userDatabase = {
'[email protected]': {
uuid: 'db79e775-81fd-4f2e-8741-9266e920cc32',
firstName: 'John',
lastName: 'Wick',
plan: 'premium',
},
'[email protected]': {
uuid: 'a3f1c820-94b2-4d67-b3e5-7f8a2d1c0e9b',
firstName: 'Jane',
lastName: 'Doe',
plan: 'standard',
},
};
// ---------------------------------------------------------------------------
// Your Glassix credentials (store securely — never expose these client-side)
// ---------------------------------------------------------------------------
const GLASSIX_API_KEY = '7cab072d-43d0-4e9d-bb25-2a947696fe8f'; // Used as JWT issuer claim
const GLASSIX_API_SECRET = 'your-department-api-secret'; // Used to SIGN the JWT
// ---------------------------------------------------------------------------
// Helper: look up a user in the database
// ---------------------------------------------------------------------------
function getUserFromDatabase(email) {
// Simulate a database query
const user = userDatabase[email];
if (!user) return null;
return user;
}
// ---------------------------------------------------------------------------
// Helper: generate a signed identity token for a given user UUID
// ---------------------------------------------------------------------------
function generateIdentityToken(userUuid, additionalClaims = {}) {
const payload = {
aud: userUuid, // Must match uniqueIdentifier in widget
exp: Math.floor(Date.now() / 1000) + (60 * 60 * 5), // Expires in 5 hours
...additionalClaims,
};
// Sign with the API SECRET (not the API key)
const token = jwt.sign(payload, GLASSIX_API_SECRET, {
algorithm: 'HS256',
issuer: GLASSIX_API_KEY, // API key goes in the 'iss' claim
});
return token;
}
// ---------------------------------------------------------------------------
// API endpoint: called by your frontend after the user logs in.
// Returns the uniqueIdentifier + identityToken needed by the widget.
// ---------------------------------------------------------------------------
app.post('/api/glassix-identity', (req, res) => {
const { email } = req.body;
if (!email) {
return res.status(400).json({ error: 'Email is required' });
}
// Step 1: Retrieve the user's stable UUID from your database
const user = getUserFromDatabase(email);
if (!user) {
return res.status(404).json({ error: 'User not found' });
}
// Step 2: Generate a JWT signed with the API secret.
// Pass optional field claims to pre-populate ticket fields.
const identityToken = generateIdentityToken(user.uuid, {
field1: user.firstName,
field2: user.lastName,
field3: user.plan,
});
// Step 3: Return both values to the frontend
res.json({
uniqueIdentifier: user.uuid,
identityToken: identityToken,
});
});
app.listen(3000, () => console.log('Server running on port 3000'));Client-Side: Fetch Credentials and Initialize the Widget
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>My App</title>
</head>
<body>
<!-- Simulate a logged-in user session. In production this would come
from your auth system (e.g. a session cookie or auth token). -->
<script>
const loggedInUserEmail = '[email protected]';
</script>
<!-- Start of Glassix Chat Widget -->
<script>
async function initGlassixWidget() {
let uniqueIdentifier, identityToken;
try {
// Step 1: Fetch the uniqueIdentifier + identityToken from your backend.
// This call happens AFTER the user has authenticated.
const response = await fetch('/api/glassix-identity', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email: loggedInUserEmail }),
});
if (!response.ok) {
throw new Error('Failed to fetch Glassix identity token');
}
const data = await response.json();
uniqueIdentifier = data.uniqueIdentifier;
identityToken = data.identityToken;
} catch (err) {
console.error('Glassix identity error:', err);
// Widget will fall back to cookie-based identification
// if identity verification is not enforced workspace-wide.
return;
}
// Step 2: Pass the credentials to the widget and attach it.
var widgetOptions = {
apiKey: '7cab072d-43d0-4e9d-bb25-2a947696fe8f',
snippetId: 'dr548fbb5d61ec51869a',
uniqueIdentifier: uniqueIdentifier, // User's stable UUID from your DB
identityToken: identityToken, // JWT signed with your API secret
};
(function(n){var u=function(){GlassixWidgetClient&&typeof GlassixWidgetClient=="function"?(window.widgetClient=new GlassixWidgetClient(n),widgetClient.attach(),window.glassixWidgetScriptLoaded&&window.glassixWidgetScriptLoaded()):f()},f=function(){r.src="https://cdn.glassix.net/clients/widget.1.2.min.js";r.onload=u;document.body.removeChild(t);i.parentNode.insertBefore(r,i)},i=document.getElementsByTagName("script")[0],t=document.createElement("script"),r;(t.async=!0,t.type="text/javascript",t.crossorigin="anonymous",t.id="glassix-widget-script",r=t.cloneNode(),t.onload=u,t.src="https://cdn.glassix.com/clients/widget.1.2.min.js",!document.getElementById(t.id)&&document.body)&&(i.parentNode.insertBefore(t,i),t.onerror=f)})(widgetOptions)
}
document.addEventListener('DOMContentLoaded', initGlassixWidget);
</script>
<!-- End of Glassix Chat Widget -->
</body>
</html>Summary
Identity verification transforms the chat widget from a cookie-based system to a seamless, authenticated experience. By following this implementation guide, you can:
- Set up a UUID database for your users
- Generate JWTs dynamically upon user login, signed with your API secret
- Pass credentials to the widget securely via a backend endpoint
- Optionally enforce identity verification workspace-wide
Remember to test thoroughly before enabling "Require Identity Verification," as it turns off cookie fallback across your entire workspace.