Using restricted Help Center content with the Web Widget

Return to top
Have more questions? Submit a request


  • Chris Stock
    Community Moderator

    Hi there, is it possible to verify the JWT somehow? My server side code is returning a jwt, and I'm passing it to authenticate, but my widget is only returning public articles.

    Is there a way to check whether my jwt is valid?

  • Raviraj Patel

    Hi there,
    I have followed all the steps as mentioned in the article but facing an error for the Authentication. How to validate JWT token as there's not a sample for .Net in case I am missing anything.



  • Bryan - Community Manager
    Zendesk Developer Support

    One thing Raviraj Patel to check is make sure the generated JWT is valid. You can paste it into and see if it's valid. Otherwise, providing more specific errors from the your browser's network tab and console might be a good next step.

  • Ramesh Doddi

    Hello, Server side (Rails) eg.

    current_time =

    payload = {:name =>,:email =>,:iat => current_time.to_i,:external_id =>,:exp => (current_time + 1.minutes).to_i}
    jwt = JsonWebToken.encode(payload,token id,current_time)
    frontend (angular)  i added required code snippet shared in the documentation. eg
    window.zESettings = webWidget: authenticate: chat: jwtFn: (callback) ->
      fetch(xxxxxxxxxxxxxxxxx/gettoken.json?id='+ (res) ->
         res.json().then (jwt) ->
             callback jwt
    But jwFn function never get executed to get token from my backend. could you please help if i miss anything??
  • co log

    Im getting exception console "j.createHmac is not a function" in reactjs application.


    what are alternatives for jwt.package?


    Could you please help me to fix this ?


  • Greg - Community Manager
    Zendesk Developer Support

    Hi co log! Would you mind sharing a bit more about the issue that you're running into here? Please share links to any libraries/dependencies that you're using.

  • Matt

    I was hitting the same  "* Could not be verified" issue. It was due to a couple things that were already mentioned, but here's a nice list that may help someone:

    • SSO JWT and WebWidget JWT must be different, and use different shared secrets. I have added to my webservice a check for the query "webwidget" so I can differentiate and use the correct Shared Secret when generating the JWT.
    • The SSO JWT is sent back as a 302 redirect with 'Location': https://<store><token>
    • The WebWidget JWT is sent back directly as text. One issue I had was I accidentally did "response.json(token)" instead of "response.send(token)", which put quotes " around the token, causing "* Code not be verified"
    • Use the browser's network debug tab to get the responses and plug them into to make sure they are valid JWT tokens.

    Here is what my index.html <head> looks like:

    <script type="text/javascript">
      window.zESettings = {
        webWidget: {
          authenticate: {
            jwtFn: function(callback) {
              fetch(location.protocol.concat("//").concat('/jwt?webwidget=true')).then(function(res) {
                res.text().then(function(jwt) {
    <script id="ze-snippet" src=""> </script>
    And here is what my web service (nodejs, express) looks like:
      jsonWebTokenResponse = async (request: UserRequest, response: Response) => {
    const userName = request.user.firstName + ' ' + request.user.lastName; // My authentication flow adds this to request
    const userEmail =; // My authentication flow adds this to request
    const userPhone =; // My authentication flow adds this to request
    const now = Math.floor(new Date().getTime() / 1000);
    const expiresIn = 28800;
    const notBefore = (now - 20);
        const secretSSO = !!process.env.ZENDESK_SSO_JWT_SECRET ? process.env.ZENDESK_SSO_JWT_SECRET : '';
        const secretWebWidget = !!process.env.ZENDESK_WEBWIDGET_JWT_SECRET ? process.env.ZENDESK_WEBWIDGET_JWT_SECRET : '';
        // Payload fields:
        const payload = {
          iat: now,
          jti: uuid.v4(),
          name: userName,
          email: userEmail,
          phone: userPhone
        const query = url.parse(request.url, true).query;
        let secret;
        const isWebWidget = query['webwidget'];
        if (!!isWebWidget) {
          secret = secretWebWidget;
        } else {
          secret = secretSSO;
        // Encode
        const token = jwt.sign(payload, secret, { algorithm: 'HS256', expiresIn : expiresIn, notBefore : notBefore });
        // const token = jwt.sign(payload, secret);
        if (!!isWebWidget) {
        } else {
          let redirect = 'https://<store>' + token;
          let returnTo = query['return_to'];
          if (returnTo) {
            if (returnTo instanceof Array) {
              returnTo = returnTo.length ? returnTo[0] : '';
            redirect += '&return_to=' + encodeURIComponent(returnTo);
          response.writeHead(302, {
            'Location': redirect
'JWT Redirect: ' + redirect);
  • Nicole S.
    Zendesk Community Team

    Thanks for sharing, Matt!

    Also, I see that this is your first post. Welcome to the Zendesk Community!

  • James Barry

    I think it would be well worth emphasizing Matt's points in the documents. It was not clear what the difference between the Web widget jwt and SSO jwt are and how to implement both. I spent a while using the web widget secret for sso.....

    Thanks Matt


Please sign in to leave a comment.

Powered by Zendesk