Single sign-on is a mechanism that allows you to authenticate users in your systems and subsequently tell Zendesk that the user has been authenticated. If you use single sign-on with JWT, a user is automatically verified with the identity provider when they sign in. The user is then allowed to access Zendesk without being prompted to enter separate sign-in credentials.
At the core of single sign-on is a security mechanism that allows Zendesk to trust the sign-in requests it gets from your systems. Zendesk only grants access to the users who have been authenticated by you. Zendesk SSO relies on a technology called JSON Web Token (JWT) for securing the exchange of user authentication data.
The IT team in a company is usually responsible for setting up and managing the company's JWT authentication system. Their role is to implement SSO for Zendesk on the system. Refer the team to the following topic in this article:
Related articles:
How JWT SSO for Zendesk works
Once you enable SSO, sign-in requests are routed to a sign-in page external to Zendesk Support.
Steps of the JWT SSO authentication process:
- An unauthenticated user navigates to your Zendesk Support URL. Example: https://yoursubdomain.zendesk.com/.
- The Zendesk SSO mechanism recognizes that SSO is enabled and that the user is not authenticated.
- Zendesk redirects the user to your organization's remote sign-in page. Example: https://mycompany.com/zendesk/sso.
- A script on the remote server authenticates the user using your organization's proprietary sign-in process.
- The authentication system builds a JWT request that contains the relevant user data.
- The authentication system redirects the user to the following Zendesk endpoint with the JWT payload:
https://yoursubdomain.zendesk.com/access/jwt
- Zendesk parses the user detail from the JWT payload and then grants the user a session.
As you can see, this process relies on browser redirects and passing signed messages using JWT. The redirects happen entirely in the browser and there is no direct connection between Zendesk and your systems, so you can keep your authentication scripts safely behind your corporate firewall.
Requirements for enabling JWT SSO
- The remote login URL where Zendesk users should be redirected when they attempt to access Zendesk
- (Optional) The remote logout URL where Zendesk can redirect users after they sign out of Zendesk
- (Optional) A list of IP ranges to redirect users to the appropriate sign-in option. Users making requests from the specified IP ranges are routed to the remote JWT authentication sign-in form. Users making requests from IP addresses outside the ranges are routed to the normal Zendesk sign-in form. If you don't specify a range, all users are redirected to the remote authentication sign-in form.
Confirm with the team that any Zendesk-bound traffic is over HTTPS, not HTTP.
Next, enter the information in Support to enable single sign-on. See Enabling JWT SSO.
The IT team may require additional information from Zendesk to configure the SAML implementation. Refer them to the Technical implementation worksheet in this article.
Enabling JWT SSO
You can enable JWT single sign-on only for end users, only for agents (staff members), or for both groups. If you're using both JWT and SAML, you need to select one as the primary authentication method. When signing into Zendesk, users will redirected to your primary sign-in page. Users can sign in with the secondary method by going to the secondary sign-in page. For details, see Using different SAML and JWT SSO (single sign-on) for agents and end users.
You must sign in to Zendesk Support as an administrator to enable JWT single sign-on.
To enable JWT single sign-on
- In any product, click the Zendesk Products icon (
) in the top bar, then select Admin Center.
- Click the Security icon (
) in the left sidebar, then click the Single sign-on tab.
- For JSON Web token, click Configure.
- For Remote Login URL, enter the URL where your users should be redirected when they attempt to access your Zendesk URL.
Zendesk automatically adds a brand_id parameter to the URL. This is the Zendesk Support brand the user was on when they attempted to sign in.
- For Remote Logout URL, enter the URL that Zendesk will return your users to after they sign out.
Zendesk automatically adds email, external_id, and brand_id parameters to the URL. If you prefer not having email and external id information in the URL, specify blank parameters in the logout URL. Example:
https://www.xyz.com/user/signout/?email=&external_id=
Note: If you're using an Ember.js application, you need to amend the logout URL to use blanked parameters before the hash. For example,https://somedomain.com/?brand_id=&return_to=&email=#/zendesk-login/
. - (Optional) For IP ranges, enter a list of IP ranges if you want to redirect users to the appropriate sign-in option.
Users making requests from the specified IP ranges are routed to the JWT authentication sign-in form. Users making requests from IP addresses outside the ranges are routed to the normal Zendesk sign-in form. Don't specify a range if you want all users to be redirected to the JWT authentication sign-in form.
- If you use external IDs for your users, you can update these in Zendesk Support by selecting On for Update of external ids?.
- Provide the Shared secret to your IT team. They'll need it in their JWT implementation.
Important: Keep the shared secret safe. If it's compromised, all the data in your Support account is at risk.
- Once your JWT SSO configuration is set, click Enabled so you can assign this option to users.
- Click Save.
Assigning JWT SSO to users
- In Admin Center, click the Staff members or End users tab and select the External authentication option.
- Select JSON Web Token as the Single sign-on (SSO) option in the External authentication section.
- If you want all users to only use a single sign-on method, deselect the Zendesk authentication option.
Any Zendesk passwords will be permanently deleted from the account within 24 hours.
- If you disabled Zendesk passwords, select the menu option that specifies whether only the account owner or admins (which includes the account owner) can be granted access to the account in case the sign-in provider does down.
To gain access, the account owner or an admin requests to receive an email containing an one-time access link. Clicking the link grants the person access to the account. No password is required. See Accessing the account if passwords are disabled.
- Click Save.
Managing users in Zendesk after enabling JWT SSO
After enabling JWT single sign-on in Zendesk, changes made to users outside Zendesk sync to your Zendesk account. For example, if a user is added to your internal system, the user is automatically added to your Zendesk account. If a user is deleted in your internal system, the user will no longer be able to sign in to Zendesk However, their account will still exist in Zendesk.
By default, the only user data stored in Zendesk when single-sign on is enabled is the user's name and email address. Zendesk does not store passwords. As a result, you should disable any automated email notifications from Zendesk about passwords. See Disabling password notification emails from Zendesk.
To provide a better customer experience, you might want to store more than just the user's name and email address in Zendesk. See Obtaining additional user data.
Generating a new shared secret
In some cases, you may need to issue a new JWT shared secret and provide it to your IT team. For example, if the secret is compromised. You can generate a new JWT shared secret from Zendesk Admin Center by disabling your JWT configuration and then reenabling it. This action will create a new secret and invalidate the old one.
To generate a new shared secret:
- In any product, click the Zendesk Products icon (
) in the top bar, then select Admin Center.
- Click the Security icon (
) in the left sidebar, then click the Single sign-on tab.
- For JSON Web token, click Edit.
Your current JSON Web token configuration appears.
- Deselect the Enabled checkbox.
- Save your changes.
- Click Configure next to JSON Web token to reopen the configuration.
You should see a new Shared secret in plain text at the bottom of the configuration page.
- Make a copy of the new shared secret to give it to your IT team.
- Click Enabled to reenable the configuration with the new shared secret.
- Save your changes.
Switching authentication methods
Additional information about JWT
JWT is a recent open standard that is being driven by the international standards body IETF and has top-level backers from the technology sector (for example, Microsoft, Facebook, and Google).
The fundamental building blocks of JWT are very well understood components and the result of this is a fairly simple spec, which is available here http://tools.ietf.org/html/draft-jones-json-web-token-10. There are a lot of open source implementations of the JWT spec that cover most modern technologies. This means that you can get JWT single sign-on set up without much difficulty.
One thing to be aware of is that the JWT payload is merely encoded and signed, not encrypted, so don't put any sensitive data in the hash table. JWT works by serializing the JSON that is being transmitted to a string. It then base 64 encodes that string and then makes an HMAC of the base 64 string which depends on the shared secret. This produces a signature that the recipient side can use to validate the user.
Technical implementation worksheet
This section is for the team in the company responsible for the company's JWT authentication system. It provides details about the Zendesk JWT SSO implementation.
Topics covered:
JWT algorithm
Specify HS256 as the JWT algorithm in the header of your JWT payload:
{
"typ":"JWT",
"alg":"HS256"
}
HS256 stands for HMAC SHA 256, a 256-bit encryption algorithm designed by the U.S. National Security Agency.
Zendesk JWT endpoint
After successfully authenticating the user, redirect the user along with the JWT payload to the following Zendesk endpoint:
https://yoursubdomain.zendesk.com/access/jwt
The payload should be base64-encoded and appended to the URL as a query string.
The JWT payload must be sent to your Zendesk Support subdomain using the https protocol. Example:
https://yoursubdmain.zendesk.com/access/jwt?jwt={payload}
Host-mapped subdomains are not supported.
JWT attributes
Send attributes to Zendesk as a base64-encoded hash (Ruby) or dictionary (Python). Example using Ruby:
payload = JWT.encode({
:email => "bob@example.com", :name => "Bob", :iat => Time.now.to_i, :jti => rand(2<<64).to_s
}, "Our shared secret")
Zendesk requires an email address to uniquely identify the user. Beyond the required attributes listed in the table below, you may optionally send additional user profile data. This data is synced between your user management system and Zendesk Support.
Attribute | Required | Description |
---|---|---|
iat | Yes | Issued At. The time the token was generated, this is used to help ensure that a given token gets used shortly after it's generated. The value must be the number of seconds since UNIX epoch. Zendesk allows up to three minutes clock skew, so make sure to configure NTP or similar on your servers. |
jti | Yes | JSON Web Token ID. A unique id for the token, used by Zendesk to prevent token replay attacks. |
Yes | Email of the user being signed in, used to uniquely identify the user record in Zendesk Support. | |
name | Yes | The name of this user. The user in Zendesk Support will be created or updated in accordance with this. |
external_id | No | If your users are uniquely identified by something other than an email address, and their email addresses are subject to change, send the unique id from your system. Specify the id as a string. |
locale (for end-users)
locale_id (for agents) |
No | The locale in Zendesk Support, specified as a number. |
organization | No | The name of an organization to add the user to. Note: If the option End-users can belong to multiple organizations is enabled, additional organizations append the original organization, and are considered secondary organizations. This does not delete the existing memberships.
If you'd like to pass multiple organizations at the same time, use the organizations attribute instead. The organizations need to be passed in a string, separated by commas. |
organization_id | No | The organization's external ID in the Zendesk API. If both organization and organization_id are supplied, organization is ignored. Note: If the option End-users can belong to multiple organizations is enabled, additional organizations append the original organization, and are considered secondary organizations. This does not delete the existing memberships.
|
phone | No | A phone number, specified as a string. |
tags | No | This is a JSON array of tags to set on the user. These tags will replace any other tags that may exist in the user's profile. |
remote_photo_url | No | URL for a photo to set on the user profile. |
role | No | The user's role. Can be set to "user", "agent", or "admin". Default is "user". If the user's role is different than it is in Zendesk Support, the role is changed in Zendesk Support. |
custom_role_id | No | Applicable only if the role of the user is agent. |
user_fields | No |
A JSON hash of custom user field key and values to set on the user. The custom user field must exist in order to set the field value. Each custom user field is identified by its field key found in the user fields admin settings. The format of date values is yyyy-mm-dd. If a custom user field key or value is invalid, updating the field will fail silently and the user will still log in successfully. For more information about custom user fields, see Adding custom fields to users.
Note: Sending null values in the the user_fields attribute will remove any existing values in the corresponding fields.
|
Remote login URL parameter (return_to)
When Zendesk redirects a user to your remote login page, it also passes a return_to URL parameter. The parameter contains the page that Zendesk will return the user after your system has authenticated the user. Append the parameter (name and value) to the Zendesk JWT endpoint.
For example, suppose an agent who is signed out clicks the following link to open a ticket in Support: https://mycompany.zendesk.com/tickets/1232. The flow is as follows:
- On click, Zendesk redirects the user to your remote login URL and appends the following
return_to
parameter to the URL:https://mycompany.com/zendesk/sso?return_to=https://mycompany.zendesk.com/tickets/123
- Your authentication system takes the
return_to
parameter (name and value) from the URL and, after successfully authenticating the user, appends it to the Zendesk JWT endpoint. Example:https://mycompany.zendesk.com/access/jwt?jwt=payload&return_to=https://mycompany.zendesk.com/tickets/123
- Zendesk uses the parameter to open the ticket page for the agent.
The return_to
parameter is an absolute URL for the agent interface, and a relative one for Help Center.
Whether you pass in the return_to
parameter or not is optional, but we recommend it for the best user experience.
return_to
address contains its own URL parameters, make sure that your script URI-encodes the entire return_to value when submitting the JWT token.Error handling
If Zendesk encounters an error while processing a JWT login request, it sends a message that explains the issue. If you specified a remote logout URL when you configured the JWT integration, it redirects to that URL and passes a message and a kind parameter. In case of error, the kind parameter always has the value "error". Zendesk recommends specifying a remote logout URL, as well as logging messages from Zendesk alongside the type. Most of the errors that can happen are ones that you'll want to fix. Examples: clock drifts, rate limits being hit, invalid tokens, and so on.
JWT implementation code examples
The actual JWT implementation is straightforward and most modern languages have libraries that support it. Zendesk provides a series of examples for various stacks in the following JWT SSO GitHub repository:
If you implement JWT in any other stack, we would love to feature an example of that there as well. Add a comment to this article to share what you've implemented.
In case you run IIS/AD and don't want to build your own .NET solution, we provide a full implementation in classic ASP, which requires you to adjust only a couple of variables. Download the ASP authentication script from this page on Github: https://github.com/zendesk/zendesk_jwt_sso_examples/tree/master/bundles.
96 Comments
Hi. Is there any article that clarifies the conditions when Zendesk redirects user to JWT authentication endpoint? Everything works flawlessly and completely transparently when I manually click the "sign in" button in Help Center, but I don't see any redirections when I just visit the Help Center in a freshly opened browser's incognito mode window.
Hi Aleksey,
There's no particular article for this, however we only redirect when a user selects either the "Sign In" button or directly clicks a ticket link from say, an email notification that requires sign in.
You can of course, require that all users are signed into the Help Center, to ensure they get redirected if required.
Cheers,
Dara
Hi everyone,
Can anyone confirm that SSO using JWT is possible on a "Starter" plan account? The "Plan Availability" header at the top of this article says that it is NOT available, but the main Pricing page (https://www.zendesk.com/product/pricing/) says it IS available. I've also read posts in this Forum that say that SSO via JWT is available on all plans, but maybe that person was just reading the Pricing page. Has anyone actually successfully done it?
I ask because I've attempted an SSO integration that returns a 401 "unauthorized" status page every time with body content set to this sparse and rather unenlightening message:
{"error":"Couldn't authenticate you"}
Even more interesting is the fact that an end-user account is created even though I get the error. I'd sort of figure that this would be all-or-nothing; I'd assume I'd either get a new end-user created (if needed) and logged in or I'd get completely rejected and nothing would happen. The fact that the end-user account gets created makes me believe that the JWT got decoded and verified successfully, but then I can't explain the "Couldn't authenticate you" message.
Has anyone gotten this before? Is there a "verbose" mode where you get a bit more feedback about why you can't be authenticated? Are there any other debugging tips anyone can pass along.
Thanks in advance!
-- Dan
Edit: I figured out how to get around the error. Activate Help Center from your main Admin control panel. That allows you to determine if users must register and log in or not. Turn that on. Then make sure you supply a
return_to
param with the JWT call, and make sure thereturn_to
URL is somewhere that a logged in user could go -- like the new request form. Don't leave it empty. Whatever the logic is, the JWT handler does not have a reasonable default value forreturn_to
.Hello,
I have the following issue, after doing all what is required, there is only one user get redirected with a message "Please use one of the options below to sign in to Zendesk" this case only happens for a single user, and there is nothing special in the data being sent to Zendesk through the JWT for this user, also tried to look around the website if there is any descriptions for the error am receiving, couldn't find any.
Any help?
@Moath - it sounds like you don't have SSO enabled for both agents and end users. In the security settings page, there's a separate tab for each set of users, and you have to enable (and hit save!) on both tabs. And if you're trying to sign in as an end user, make sure to have your Help Center activated. Also note that if you're signing in with an email address that is not already associated with a user profile in Zendesk and you're not also passing in a role with your JWT payload, that user will automatically be provisioned as an end user.
If you need more help, send us an email at support@zendesk.com. Thanks!
Is it possible to manually change the Shared Secret, or revert back to an old Shared Secret?
@Taylor - Due to security concerns, you cannot manually set the shared secret or revert it to an old one. Your only option is to generate another shared secret.
Question about "Error handling" section
>> If you have a return URL configured for your JWT integration, it will redirect to that and pass a "message" and a "kind" parameter.
What do you mean by "return URL"? Remote logout URL? If yes, change it in text
Hi Dmitry - the "return URL" is referring to the return_to parameter discussed in the section immediately before the "Error Handling" section. It is a parameter that you can (optionally) pass along with your JWT payload to redirect the user after they log in. The remote logout URL is separate, and is used to direct the user to your logout page in your SSO system when the user selects "logout" in Zendesk.
I have a problem with our JWT SSO setup, which is working fine in my tests but not for one user who cannot login because:
- Sign In keeps invoking our /support/logout URL (which is /support/logout in our case here).
- This invocation is done without a return_to argument being passed to it, so it has nowhere to go after signout.
I only added the Sign Out code last week, and as far as I know it was working fine then. However, at this point the two problems above are preventing this user from logging in. I've asked her to clear cache, try a different browser, etc. They all fail the same way.
Is it ever normal for my Sign Out SSO URL to be invoked on a Sign In? If so, shouldn't it specify a return_to URL?
- It's only enabled for end-users
- It's set to SSO -> JWT and the Remote URLs are:
Sign In: (domain)/support/login/
Sign Out: (domain)/support/logout/
Summary: We've set the two URL fields in the SSO JWT options to the values above and in most cases it's working fine (very smooth, no problems implementing SSO), but the second one is being invoked on a Sign In. Clearing cache, changing browsers, etc, seems to have no effect.
Hi,
I always get a 500 error page when I try to reach http://server/classic_asp_jwt_with_ad.asp based on a IIS W2008 Server.
Is anyone facing this error ?
It would be helpful to add a table of contents to the top of this article with anchor links down to each section (similar to most ZD articles). I use this page all the time! Thanks.
@Jim:
"Is it ever normal for my Sign Out SSO URL to be invoked on a Sign In?"
No, this is probably happening due to a problem in the authentication process. If an error occurs during auth, the user is automatically redirected to the remote logout URL. If you could open a ticket with us, we can help you sort out what exactly is happening.
@Eldien:
I'm not sure what URL you're looking for, but if you're looking for our example code for JWT and AD, the code is here:
https://github.com/zendesk/zendesk_jwt_sso_examples/blob/master/classic_asp_jwt_with_ad.asp
@Justin:
Thank you for your feedback, I will pass that along!
@Justin (again) - Done! Thanks again for your input!
@Anna: Yes I was made some changes for our environment and deployed.
When I access my zendesk url, it will redirect to AD basic authentication after that instead of return to my zendesk, the page return error page 500
Hello,
I am trying to setup jwt with IIS on win2008. The script classic_asp_jwt_with_ad.asp and his dependencies are located in C:\inetpub\wwwroot\zendesk on my server.
However I have an issue when I try to connect.
When I setup my Remote login URL to http://mycompany.com/zendesk/ the login works with my AD users but I just get the web page index of /zendesk/ on nothing happen (no redirection to zendesk) like the script was not executing.
If I change my Remote login URL http://mycompany.com/zendesk/script classic_asp_jwt_with_ad.asp the login works but I get an HTTP error 500...
Could you please clarify what I should exactly setup for the "Remote login URL" in order for the script to execute and redirect me to sendesk once I log in ?
Thanks
@Mat
I'm also facing the same error. Hopefully someone can help to this matter
@Mat & @Eldien - In an effort to assist you further, I've created individual tickets for you. I'll send you an update via your ticket shortly.
Hello and thank you for this helpful article.
We have been using the normal zendesk authentication for quite a while for our users and now we would like to use the SSO authentication.
If a user had already a zendesk account and then we switch to SSO auth. Does that user will end up with 2 different zendesk accounts ? Is-there some merging rule we could take advantage of ? We just don't want to lose or duplicate user data.
In advance, thank you very much,
Alexandre
Hi Alexandre,
As long as the email address that is used in the JWT login is the same one already associated with their Zendesk account, it will recognize them as the same user and no duplicate user will be created.
It is possible to merge users however, should you need to do so:
https://support.zendesk.com/hc/en-us/articles/203690896-Merging-a-user-s-duplicate-account
Thanks!
We are trying to setup JWT with IIS on Windows 2016. Using the script classic_asp_jwt_with_ad.asp and its dependencies we are able to log into Zendesk without issue.
We want to be able to pass the phone number and department with our end user logins in doing so we are trying to use the "user_fields" API. I am woefully unqualified as a Classic ASP programmer, I understand most of the code and how the Scripting.Dictionaries are working. However when I add the string "employee_department Information Technology" to the scripting object, it fails miserably.
Can anyone point me in the right direction on how to pass these hashes so that it works. I can work with pseudo code if you are unfamiliar with ASP.
Hey Matthew!
I saw that you posted this in another thread as well, and one of my colleagues was able to point you to some resources. Let us know if you need anything else!
Is it possible to authenticate users by UUID as well as email address? If a user changes his email address on our website to match someone else's, he would then be logged into that user's account on Zendesk.
Joan, we did that. I'm not sure if it's the official way, but what we did was enable the "external_id" in the authentication settings and always provide the user UUID in that. That supports both name and email changes while preserving the account.
The only negative from this that I could think of was that support for any external sources such as Facebook or Twitter may not be able to match up that user on those services with the user on zendesk, however that's probably a Good Thing anyway, if they are using different email address on another system.
Using email to sync information about accounts on external systems is a bit evil in my mind anyway, because the user in question may not want any connection between their accounts, e.g. between their Facebook and Twitter accounts, or Zendesk. In our service, users use only anonymous avatar names (and images) which do not match their real (wallet) info. Using the email to pull information from another system is potentially a serious privacy violation. For this reason, one of my urgent work items is to replace the use of gravatar profile images with the image the users have provided on their profiles for our (separate) service. Their gravatar image may be their real life identity.
Thank you Jim - I know we can pass in the UUID, but my question is whether that will be validated for login along with the email address, or is just the email address used to authenticate the user?
I can't check (I don't have admin access currently) but I believe there was a checkbox on the Admin->Auth->User tab that enabled or disabled use of the "external_id" field as the key for the user. I believe we've already done email address changes and had the zendesk account retain the previous info associated with that account. It basically just works, as far as I can tell.
However, there is a potential "gotcha" here. If you already have existing user accounts showing up in Zendesk, I'm not sure how transitions to that setup would work. If you don't already have it enabled and filled in per-user, then enable it, new JWT fetches with an external_id may determine that to be a new Zendesk user (losing access to old support requests, etc). It may just fall back to some attempt to match the email address, or at least until the next JWT is returned for that user. But I haven't found it described in this level of detail anywhere.
thank you again for your help - the existing user issue was exactly what I was thinking about - we have a large number of users who already have accounts without external ids set, so it may not work to change things now.
Hi
I am trying to use implement SSO using JWT in node js. The example provided at https://github.com/zendesk/zendesk_jwt_sso_examples/blob/master/node_jwt.js is wrong.
issue #1 : iat: (new Date().getTime() / 1000),
correct will be
issue #2 : I am getting error "The%20unique%20request%20identifier%20was%20reused.%20Please%20fix%20this%20and%20try%20again."
Below is my implementation
Hi Nehal,
I see you also sent in a ticket for the question about your JWT script. I responded to you already via this ticket. Thanks so much!
Please sign in to leave a comment.