If you are using the integrated Web Widget with your Chat account, you can configure your widget to authenticate visitors on every page load using the Javascript API and JWT token.
This article applies to customers using the following versions of Chat:
- Zendesk Chat Phase 4 (Chat-only or with Support)
- Zendesk Chat Phase 3 (with the integrated Chat experience in the Web Widget)
If you are using Zendesk Chat Phase 3 (Chat-only), see Enabling authenticated visitors in the Chat widget .
For help identifying which version of Chat you're using, see Determining your Zendesk Chat account version.
This article includes the following topics:
Overview
You can configure your widget to authenticate visitors on every page load using a new Javascript API and JWT token.
When you configure the Web Widget to use authenticated visitors, you get the following benefits:
- Ability to have higher confidence and security that the visitor/customer you or your agents are talking to is the real deal
- Support for cross domain traffic. If you are embedding the widget on multiple domains or link to externally hosted services (ex. Shopify), authenticating the visitor will make it one visitor across the domains to the Chat platform which allows your agent to have more context
- Support for cross device/browser identification. The visitor can be viewed as the same person if or when they choose to use a different device or browser when the custom ID is specified in the authentication call.
- Ability to present past chat conversations to the visitor in the widget
Generating a Chat shared secret
To generate the shared secret required for authenticated visitors, go to the Widget Security settings tab and click the Generate button underneath the Visitor Authentication section:
Because it is a security setting, your shared secret is intended to be generated, copied and pasted into a communication with your engineering team or directly into your codebase in one sitting. It is not to be entered into a browser:
Regenerating a new shared secret will revoke the previous token. If you have concerns the shared secret has been compromised, you should regenerate a new one. If you need to rotate the keys, you should schedule it when Chat is offline because regenerating the secret may cause visitors to be disconnected from the widget for 5 minutes.
Once you have generated the shared secret, use it to create a JWT token (Learn more about JWT) that you'll add to your Web Widget snippet.
Creating a JWT token
To create a JWT token and add the code to the Chat standalone snippet
- Construct a server-side payload of data for the JWT token. This needs to have the
following information:
- name: Customer's name
- email: Customer's email
- external_id: alphanumeric string, unique to identifying the customer. Once set for the customer, this value cannot be changed. We recommend that you use your system's unique user ID for this field. For example, user-123456.
- iat: Integer value of the current timestamp, in seconds. Some functions in specific languages i.e. JavaScript's Date.now() return milliseconds, so please make sure you convert to seconds. Iat for Chat authentication permits up to two minutes clock skew.
- exp: Integer value of the current timestamp, in seconds. This value indicates when this JWT token will expire. The value is permitted to be up to a maximum of 7 minutes from the iat value.
- Use the code samples below to find a template that fits your language needs.
- Use the zESetting Javascript API with the key `webWidget.authentication.chat.jwtFn` to
provide a function which supplies a fresh JWT every time it is invoked. Below is a code example:
window.zESettings = { webWidget: { authenticate: { chat: { jwtFn: function(callback) { fetch('JWT_TOKEN_ENDPOINT').then(function(res) { res.text().then(function(jwt) { callback(jwt); }); }); } } } } };
Note: The jwtFn can be called multiple times throughout a chat session to obtain a new JWT in order to validate the visitor’s identity over the session’s lifetime.
Code samples
Your token needs to be dynamically generated from the server-side on page load. Find the template below that fits your language needs. Customize the sample as needed, making sure to replace the #{details} with your own information.
If none of these samples match your needs, JWT has a more extensive list of JWT libraries to explore.
Ruby
First, install ruby-jwt.
If you're using Rubygems:
gem install jwt
If you're using Bundler, add the following to your gem file:
gem 'jwt'
Next, generate a token using the shared secret:
require 'jwt'
payload = {
:name => "#{customerName}",
:email => "#{customerEmail}",
:iat => timestamp,
:external_id => "#{externalId}"
}
token = JWT.encode payload, "#{yourSecret}"
NodeJS
Install jsonwebtoken:
npm install jsonwebtoken --save-dev
Then, generate a token using the shared secret:
var jwt = require('jsonwebtoken');
var payload = {
name: '#{customerName}',
email: '#{customerEmail}',
iat: #{timestamp},
external_id: '#{externalId}'
};
var token = jwt.sign(payload, '#{yourSecret}');
Python
Install python-jose:
pip install python-jose
Generate a token using the shared secret:
from jose import jwt
var payload = {
'name': '#{customerName}',
'email': '#{customerEmail}',
'iat': #{timestamp},
'external_id': '#{externalId}'
}
token = jwt.encode(payload, '#{yourSecret}'
PHP
Download PHP-JWT:
composer require firebase/php-jwt
Generate a token using the shared secret:
use \Firebase\JWT\JWT;
$payload = {
'name' => '#{customerName}' ,
'email' => '#{customerEmail}',
'iat' => #{timestamp},
'external_id' => '#{externalId}'
};
$token = JWT::encode($payload, '#{yourSecret}');
Elixir
Add `json_web_token_ex` to your `mix.exs` file:
defp deps do
[{:json_web_token, "~> 0.2"}]
end
Generate a token using the shared secret:
data = %{
name: "#{customerName}",
email: "#{customerEmail}",
iat: "#{timestamp}",
external_id: "#{externalId}"
}
options = %{ key: "#{yourSecret}" }
jwt = JsonWebToken.sign data, options
Sign out
If you want to sign out the authenticated visitor, you will need to use the zE.logout Javascript API. To learn more about the API, click here.
About the agent experience with authenticated visitors
A few things are updated in the Chat dashboard when an agent starts chatting with an authenticated visitor.
First, the agent will be able to tell the visitor is authenticated by the green authenticated checkmark overlay on the visitor's avatar:
The agent will also notice that they cannot edit the visitor's name or email, since the source of truth comes from the information that is being sent via the Javascript API.
Finally, banning an authenticated visitor will mean the visitor cannot access the Chat widget across devices and browsers.
About the widget experience for authenticated visitors
Authenticated visitors will also have a slightly different experience in the Chat widget. First, their information is read-only and cannot be modified by them via the widget or through the Javascript APIs.
Second, ongoing chat sessions are synced across devices when the visitor is authenticated. This gives the visitor flexibility to switch computers/browsers and continue their ongoing chat session, which is not possible today.
Third, the ability to have the chat in a popout is removed for authenticated visitors because there is no way to verify their identity via the popout (as the experience is hosted on our domain, zopim.com).
Finally, the authenticated visitor will have the ability to see their past conversations in the widget by scrolling up in the chat log. To learn about conversation history support for authenticated visitors, click here.
70 Comments
Hi, any idea if your using this would you also still want to use zE.identify https://developer.zendesk.com/embeddables/docs/widget/api#ze.identify
or would this cover that now?
also it seems like setPhone would still be set using the zopim livechat api? as this is only doing name and email https://api.zopim.com/files/meshim/widget/controllers/LiveChatAPI-js.html#setPhone
also I submitted a request for the Web Widget Integrated Chat Experience EAP and was wondering if I could get access
Thanks
Hi Josh,
You would still want to use zE.identify for the other channels in the Web Widget, like contact form/help center. If you only care about setting the information for the Chat product, you can just use this.
Currently, authenticated visitors does not require phone number as a authenticated field and you would need to set it using setPhone for now.
For the Web Widget integrated chat experience EAP, the PM (Dan) should get in touch with you shortly.
Thanks,
Ramin
Quick question - what happens if you try to authenticate a visitor who has some kind of credential on your website but doesn't yet exist in your Zendesk?
Hey Zac,
Using chat authentication with the Web Widget won't create a new user until a ticket gets created from the chat/offline message. This behaviour is the same for non-authenticated visitors also.
If you use zE.identify to authenticate the non-Chat related channels in the Web Widget, it will create a new user if there isn't one that matched the email address in your account.
You can learn more about this Web Widget API here:
https://developer.zendesk.com/embeddables/docs/widget/api#ze.identify
-Ramin
Hello, I followed this article's tutorial as stated, but my function jwtFn never gets called or executed. I'm also passing other stuff on settings like colour change just to make sure it is right, and the colors indeed changed on the widget.
Any help?
Hi Jonathan,
Can you email the issue you are experiencing with the code snippet using the Javascript APIs to chat@zendesk.com?
We can have a look and see what could be causing the issue.
Cheers,
Ramin
Hi,
The jwtFn is never executed. Screenshot below:
This is a blocker, any help?
I have zero experience with website coding and java scripts. When will this be an automatic part of chat? When a user logs into the helpcenter and has the chat widget available, they should automatically be logged into the widget. currently, we are having to ask them to log in yet again, even though they just did. seems counter intuitive. The chat widget should just carry over the user's name and email from the helpcents interface.
Thanks,
Steve
Hi Steve,
Today, the name and email information are pre-filled for customers who are logged into help center but they are not authenticated.
Authenticating visitors for now will require additional code and you will need to get assistance or a contractor to help you with that work.
-Ramin
Quick note to hopefully save users time and frustration:
The fetch method defined in this article (see below), does not work with Safari.
When utilized, it returns the following error int he console:
The operation couldn’t be completed. (kCFErrorDomainCFNetwork error 303.)
Our endpoint was returning http code 200 with the JWT as plain text and worked fine with Chrome, Firefox and IE.
We were able to resolve by replacing the fetch statement with getJSON and updating our endpoint to output JSON with an array (in our case sucess (boolen) and jwt (string). This resolved the issue on Safari and works with every other browser we've tested as well.
Here's the updated code:
Hi Ramin and Brain,
We still have a problem. "fetch" will be executed only when jwtFn is executed. In our case even jwtFn is not being executed.
Hi Brian and Aman,
Brian:
I am not sure why you are having issues with Safari specifically, but it looks like the JWT_TOKEN_ENDPOINT in your code is expected to return a JSON payload.
In that case, you can still use fetch by replacing res.text() with res.json() in the example code above.
Aman: I have replied to you separately in an email.
Thank you,
Jun Yi
Jun Yi,
Thanks for the heads-up regarding the res.json() option to set the handler for a JSON payload. Unfortunately, Safari failed with the res.text() option when the endpoint was returning plain-text. Only the move to AJAX utilizing getJson() resolved the issue on Safari. For reference the version of Safari is below if you would like to confirm / replicate.
Hi Ramin,
This is Hayya again,
I have added this code but it's still not working, the jwtFn is never executed.
We have the same problem as Hayya. The jwtFn function is never executed. How to proceed?
@Hayya @Jeffrey you need to be part of the integrated Chat experience EAP for the code to work. It is currently not turned on for your accounts.
Please register for the EAP here: https://support.zendesk.com/hc/en-us/articles/360001015607-Announcing-Web-Widget-Integrated-Chat-Experience-EAP
We have the same problem as Hayya & Jeffrey and we do have the EAP activated.
Hi Jorge,
Sorry to hear that you are having trouble implementing this. Can you please chat@zendesk.com with your account information, URL where the widget is embedded and the code on your page?
We can then look and see if anything stands out.
-Ramin
We are using Web SDK implement our chat widget. does visitor authenticate need "EAP" ? we implement as this article instruction, but it can't work.
Hi panbin,
Since you are using the Web SDK, you will need to follow the instructions here: https://api.zopim.com/web-sdk/#visitor-authentication
No need to be part of the EAP.
-Ramin
Hello, we're getting a "Zendesk Chat: failed to verify token: jwt verification error" notification.
We're using code similar to:
$zopim.livechat.authenticate({
jwtFn: function (callback) {
fetch('http://localhost/security/api/security/login', { credentials: 'include' }).then(function (res) {
res.text().then(function (jwt) {
console.log(jwt);
callback(jwt);
});
});
}
});
Can anyone assist? Thank you.
Hi Rob,
Can you create a ticket for this issue by sending an email to chat@zendesk.com? The team can look at why it isn't working for you.
-Ramin
Hi Ramin,
I did so yesterday :)
Thanks!
I've followed all steps and managed to generate JWT key on my backend(PHP). I've copy-pasted code and installed Firebase\JWT. It generated token that I've managed to send when i init chat on my client side:
```
it console.logs that it failed to verify token.
`Zendesk Chat Web SDK: Error: init: Failed to verify token: jwt verification error`
Any idea what may cause this problem?
Hey Nikola,
I will create a ticket for you and we can troubleshoot the issue on the ticket.
Thanks,
Ramin
Hello, I'm getting the exact same error as NIKOLA
`Zendesk Chat Web SDK: Error: init: Failed to verify token: jwt verification error`
Can you assist me?
Best regards
Hi Tiago,
Can you email the following information to chat@zendesk.com so we can troubleshoot the issue further:
- Code being used to authenticate the visitor
- Page where the widget and authentication is on
- HAR file if possible. If you dont know how to generate this, please follow the instructions here: https://support.zendesk.com/hc/en-us/articles/204410413-Generating-a-HAR-file-for-troubleshooting
-Ramin
You need to add the following header to your JWT to get it working.
"name": "Name Surname",
"email": "aasdfds@gmail.com",
"iat": 1547699318,
"external_id": "aassdasDASDd",
"phone": 5417541343
}
Hey Team,
Any ETA on the ability to log out the user from the widget when logging out of the host app? We really want to authenticate customers but the lack of this feature is too big a security risk for us at the moment to allow us to implement.
Hi Dylan,
If you are using the Web Widget, you can use the following:
If you are using the Chat standalone widget, you can use the following:
https://api.zopim.com/files/meshim/widget/controllers/LiveChatAPI-js.html#clearAll
If you are using the Web SDK, you can use the following:
https://api.zopim.com/web-sdk/#zchat-logout
Thanks,
Ramin
Please sign in to leave a comment.