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
David Berumen
Hi, @... could you provide us with a complete downloadable example of this topic with php.
please.
0
Dave Dyson
Hi David,
Did you see the download link in the PHP section above? PHP
0
David Berumen
hi,@....
yeah I'm very confused by now, I did all the steps and it still doesn't work. so request the downloadable I think it will help us all.
0
Dave Dyson
@... Here's the link from above: PHP-JWT
0
Andrew Reid
Hi @... thanks for this guide. After implementing the changes described, we're experiencing some odd behaviour. The user appears to be authenticated and sees their readonly profile information as expected. However, upon clicking the 'Start Chat' button, the following error message is displayed:![](/hc/user_images/Ms4w4VrmZcpmow_2d8mr0w.png)
There are no network or console errors visible in the browser, and when the logic in `webWidget.authentication.chat.jwtFn` is removed, the unauthenticated chat works as expected. Any insights into how to resolve this would be much appreciated!
Edit:
I have seen this article on this error message and have confirmed the 2 causes identified there are not applicable here.
0
Ramin Shokrizadeh
Andrew Reid Thanks for letting us know about the issue you are experiencing. Can you please reach out to our advocacy team with the link to where the widget is located and authenticating visitors so we can have a look at what is going on with your implementation?
0
Andrew Reid
Thanks @...! We were able to identify the problem. In case it's helpful for anyone else, when adding the authentication logic we forgot to remove an existing usage of the identify command. After removing that, the authenticated user was able to start the chat without issue.
0
moment long
I would like to ask how to continuously call the jwtFn method to update the token
This is the code I added when I initialised it
I am a single page application, how can I do this by calling the jwtFn method after login.
0
DJ Buenavista Jr.
Thank you for reaching out to Zendesk Support.
In regards to your question, were you able to check the provided example above for the JTW token method? In the example above, it was mentioned the following line that you need to use in order to call the jtwFn multiple times.
jwtFn: function(callback) {
fetch('JWT_TOKEN_ENDPOINT').then(function(res) {
res.text().then(function(jwt) {
callback(jwt);
Thank you and have a wonderful day ahead!
Kind regards,
0
Espartan Code
Where can I find an example of javascript to authenticate the user in the chat I'm still going around in the answers that give me an example here
0
Alessandro Battistini
Hi Espartan Code,
You can see the example on this article as mentioned in the following part:
0
Wedy Chainy
Hi,
do we have an example what JWT_TOKEN_ENDPOINT should look like?
I am after whether it's POST or GET ?
what is the response looks like e.g. JSON or text? what content-type ?
thank you
0
Tim O'Mahony
Following Wedy Chainy question:
0
Dainne Kiara Lucena-Laxamana
Hi Wedy Chainy & Tim O'Mahony,
This documentation is actually meant to be relayed to the developers of your team, as this is not beginner documentation since it requires programming skills. Rest assured that if this is relayed to the devs, they'd have everything they need.
But to clarify, even if we "fetch", this simply means that the token can be returned by a Javascript function or returned by an external page & its code logic as written in the doc
Fetch as it means, is always some kind of "GET" method, but here HTTP request methods (GET, POST, PUT, and DELETE) are not relevant as fetch is a method in JavaScript https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch
This is also not related to content-type as we expect that JWT_TOKEN_ENDPOINT returns the token string when calling it.
A JWT token string would look something like this
Ex :
Here are 2 screenshots from my colleague's implementation using PHP using Firebase
Fetch endpoint :
JWT generating :
Hope this helps!
0
Jimmy McDermott
Hi! This is helpful, thanks. If the user's external_id is already in the Zendesk system as an end-user, two questions:
1. Will it recreate the user? (I am guessing not)
2. Will this enable the user to receive articles that are scoped to the user's tags and therefore user segments?
Thanks!
0
Вячеслав Медведевских
Hey!
Can we somehow send the client's phone number to Zendesk using JWT?
Our employees use Zendesk to receive calls, but the call history is stored separately from the chat history, because the "chat client" and the "call client" are two different entities.
We need Zendesk to understand that the person who is calling now and the person who was chatting 5 minutes ago are the same client.
In this case, we believe that the call history and chat history will be tied to the same entity, and our employees will work with a single communication history.
1
Fellipe M.
According to the article Anatomy of a JWT request, it is possible to pass a Phone Number is a JWT request. You just need to ensure that the phone number is in an accepted format as described here.
If you have any difficulties, feel free to raise a ticket with the Support team and we'll be happy to assist you further.
Best,
0
Pavel Glac
Hi!
![](/hc/user_images/fXt7Y4zqJ3sZn506OF0yqA.png)
![](/hc/user_images/rzX5gkNef0_MbXmC_VcVnA.png)
Have following error
JWT token which is sended looks ok
Don't understand the error message and looks like a problem and your side bcs secret token you should already have. Do you have idea where could be the problem?
thank you
0
Jeff C
Hey Pavel,
Can you please double check if you are using the Shared Secret from the Chat dashboard and not from the Web Widget settings? This one common issue where the shared secret being used is not the correct one.
If you have confirmed that you are using the Shared Secret from Chat and have also tried regenerating a new one but still does not work, please reach out to us via Messaging or Option 2 listed here so we can assist you further.
0
Marcin Wolniewicz
Hi! I'm struggling to get this to work. I can see that the chat is making one request to my endpoint, but never another one. Also in the Agent's view there are no user details or verification. Does the algorthim need to be HS256? I found that information in your other guide, but not here so I'm a bit confused: https://support.zendesk.com/hc/en-us/articles/4408836328346
Is there any way to troubleshoot this issue? Maybe the there is some problem with decoding/encoding?
EDIT: my problem was fixed after changing the algorithm to HS256, adding the "typ":"JWT" header and parsing "external_id" to string (I was sending it as a number before). Not sure which of these changes did the trick, since I released all three together, but now it works
0
Kevin Kim
Hello, I see that when we authenticate our users using the new Messaging API, the user's external_id will show up on their profile https://developer.zendesk.com/documentation/zendesk-web-widget-sdks/sdks/web/enabling_auth_visitors/
However, when I authenticate our users through the Classic SDK, though we get the user's email and name, the external_id that we provided to get the JWT token is nowhere to be found. Is there a way to get the external ID somehow?
0
Arin Mukhrjee
*** URGENT HELP needed***
Hello, Trying to implement the Zendesk widget on javascript on my application with authentication.
the API to return JWT it is being properly called as i can see from the JS.
The JWT returned is as below :-
But i keep getting below error on my network tab on browser when widget tries to call zendesk. Any help is appreciated.
0
Viktor Osetrov
Thanks for your question.
The issue with 400 Bad Requests or failed to validate claims error seems to be related to your values.
Please make sure that you are using seconds (not milliseconds) for both iat and exp.
iat and exp: 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.
Hope it helps
0
Arin Mukhrjee
Thanks @... for the prompt response, highly appreciate it. So i am using JAVA rest API to generate the JWT and i am using below to generate the time in seconds. Any ideas if anything else you might think of is the issue possibly?
Also to add, I have tried with and without both base64 encoding the secret, same error message.
I still do not include the 'jti' as part of the claim as I read a few documentations.
Please advise.
0
Viktor Osetrov
Thanks for your quick reply. I still believe that the issue is related to values.
Could you please check "name" and "email"?
It looks like you are using the same value twice:
Hope it helps,
0
Arin Mukhrjee
Hey @..., appreciate you responding on my stuck issue. Please see below my updated JWT payload here , and I do have different name and email. Just re-iterating, i have tried with using the secret as Base64 encoded and without it as well, keep getting
.
0
Remi
Good day, Arin Mukhrjee,
Thank you for your continuous patience on this matter, hope you are doing well today!
To answer this, you cannot use attributes that are not meant to be used against our login endpoint, as we have some kind of model validator for your JWT operating in our backend.
Thus, as per your screenshot, attributes nor being part of the example provided will invalidate your payload.
Remember, for JS or any programming language to respect the example provided :
I personally use it for PhP and here is how I build my payload :
And it works like a charm!
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoiUmVtaSBTYXVtZXQiLCJlbWFpbCI6InJzYXVtZXRfemVuZGVza0BvdXRsb29rLmNvbSIsImlhdCI6MTY2ODQyMjczMCwiZXh0ZXJuYWxfaWQiOiI4In0.4u9HZPEeVdA11_lIdYGdCvne0uTMGcDsvC_UnrpLXQQ
PS: Remember for the external_idi attribute :
Hope this clarifies it! Have a great rest of your day.
Best regards,
0
webmaster groupgia
Hello good morning,
I am trying to send all the information to the chat but it does not work, I access the intranet from another computer and the history appears empty starting a new conversation
The code is the following:
And the code on the server is the following:
This should make our client see his chat history when accessing the intranet, is that correct?
0
Remi
Good day webmaster groupgia,
Thank you for your post, hope you are doing well!
Indeed, as outlined, if your authentication is successful, you should be able to view the past interaction's history for your Visitor :
I ran a test on my personal PhP authentication for Chat and can confirm if I initiate a Chat on computer 1 and then end up the Chat, go on computer 2 and login my Visitor, I can access the past interaction that I just wrapped up on computer 1.
![](/hc/user_images/Pc0WVIAKMeECNENyZuif2Q.png)
Are you able to confirm your authentication is successful? One marker is simply to make sure the green dot is present when your Visitor chats you in, for example :
And here we can see, within the widget, the past interaction and the new one when my Visitor is authenticated.
Let me know if you are still not able to make this work or if you are not able to authenticate your users, as we may need to turn this into a ticket to investigate it further.
But be reassured, I can confirm the feature works.
Have a great rest of your day!
Best regards,
0
BAKO
Hello,
We have enabled this feature recently and receiving authenticated user chats.
I have 2 questions;
If I wanted to report on just authenticated visitor chats, is there a way to filter those out in Explore or some other form of reporting? I thought about adding a tag to these chats as they start but couldn't figure out how.
Secon questions is; If I wanted to create a trigger for these authenticated user chats, what conditions can I use? Or is there even a native option for it?
Regards.
0