If you are using Web Widget (Classic) 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 live chat:
- Zendesk Chat Phase 4 – Chat-only or with Support)
- Zendesk Chat Phase 3 – with the integrated Chat experience in the Web Widget (Classic)
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 (Classic) 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 a shared secret
- From the Chat dashboard, go to Settings > Widget > Widget Security tab.
- 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(jwt).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, see the Web Widget (Classic) Settings reference.
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 Web Widget (Classic) 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.
34 comments
Remi
@Good day BAKO,
Thank you for your post, hope all is well on your end today!
To answer your questions :
1 - I'm no Explore expert, but I don't believe you will be able to build a report based on whether the user is authenticated or not, for the reason that authentication isn't a recorded state / nor an attribute, therefore, Explore will have no way to pull this data from Support/Chat dataset.
Which leads to your second question
2 - Same as above, End-user authentication isn't "recorded" in any API or attribute.
Thus, one answer to both of your questions as a "best solution" would be simply to pass a Tag via our API for Chat Widget when your user is authenticated.
So basically, build your code and logic to apply/build the JWT, wait for the JWT to be passed to our endpoint and then, once confirmed, in parallel push/add a Tag such as "user_authenticated" via this Chat API > chat:addTags, which will be passed to the Chat session through the widget.
This means, then, you can build your Report in Explore based on these tags, as we will know they only exist for authenticated users.
Same for your Trigger, you can then use the "Contains at least one of the following" tag "user_authenticated" as a condition, which means your Trigger will fire only for authenticated users.
Hope this helps! Have a lovely rest of your day and a great weekend as well.
Best regards,
0
Adam Dreier
The key takeaway here though is once I had everything working and configured you need to make sure that the token does not have quotes around it, Please update this documentation because res.text() in the res for javascript creates a string and causes a 400 response from the API. You need to tell devs that the token needs to be wrapped in a JSON.parse(jwt) to remove the quotes or else it wont work.
0
Nova Dawn
1
Dave Goddard
Hello. I am receiving exactly the same 403 from https://marketplacer.zendesk.com/embeddable/authenticate when using
the below.
The documentation said to add “chat" between “authenticate” and “jwtFn”, however when I do that nothing happens at all. I noticed that the javascript code specifies both so tried this.
I should mention that I have tried placing this both before and after the script tag for “https://static.zdassets.com/ekr/snippet.js?key=[MYKEY]”
Is there any way to see logs in zendesk for "embeddable/authenticate" to debug the problem?
0