Genesys Cloud - Developer Community!

 View Only

Sign Up

  • 1.  Authenticated Web Messaging HTTP 401

    Posted 05-05-2025 13:12
    Edited by Matthew Sorensen 05-13-2025 07:59

    I'm hoping you can shed some light on the cause of this error. I'm trying to setup a web messaging demo following the posted blueprint. When the browser makes the POST request to api/v2/webdeployments/token/oauthcodegrantjwtexchange it returns with a 401. The contextId seems to change, so I've attached the last 3 that I've seen. 

    CLI 
    {
      "message": "Failed to identify user for token: YYYYYYYYYYYYYYYYY deploymentId: XXXX-XXXXX-XXXX-XXXX",
      "code": "unauthorized",
      "status": 401,
      "contextId": "ffe737c8-b8e0-4369-b43f-988cf95e7039",
      "details": [],
      "errors": []
    }
    
    
    Browser
    #1
    {
        "message": "Failed to identify user for token: YYYYYYYYYYYYYYYYY deploymentId: XXXX-XXXXX-XXXX-XXXX",
        "code": "unauthorized",
        "status": 401,
        "contextId": "c08f988c-8959-495d-9491-223d5d72d6e1",
        "details": [],
        "errors": []
    }
    
    
    #2
    {
        "message": "Failed to identify user for token: YYYYYYYYYYYYYYYYY deploymentId: XXXX-XXXXX-XXXX-XXXX",
        "code": "unauthorized",
        "status": 401,
        "contextId": "e2cd03fd-57c1-4ae6-b6e0-af1d848bc392",
        "details": [],
        "errors": []
    }

    I've manually requested and decoded the jwt and confirmed it contains the following

    Decoded ID Token:
    {
      "sub": "XXXXXXXXXXXXX",
      "name": "First LastName",
      "email": "XXXXXXXXXXXXX@EMAILPROVIDER.TLD",
      "ver": 1,
      "iss": "https://OKTA-DOMAIN.okta.com/oauth2/default",
      "aud": "XXXXXXXXXXXXX",
      "iat": 1746458026,
      "exp": 1746461626,
      "jti": "ID.tXHjHmgxkUIU6i9paW3q5MThmnsS-XW4LHIpOoNdKQc",
      "amr": [
        "mfa",
        "otp",
        "pwd"
      ],
      "idp": "XXXXXXXXXXXXX",
      "preferred_username": "XXXXXXXXXXXXX@EMAILPROVIDER.TLD",
      "auth_time": 1746456707,
      "at_hash": "V9MnrVDzty-U46kAckRxjw"
    }
    
    Decoded Access Token:
    {
      "ver": 1,
      "jti": "AT.9d5248liJDGiFH8Bf9W6ObTNL-DXoBTKXjOkPjFjV4s",
      "iss": "https://OKTA-DOMAIN.okta.com/oauth2/default",
      "aud": "api://default",
      "iat": 1746458026,
      "exp": 1746461626,
      "cid": "XXXXXXXXXXXXX",
      "uid": "XXXXXXXXXXXXX",
      "scp": [
        "email",
        "openid",
        "profile"
      ],
      "auth_time": 1746456707,
      "sub": "XXXXXXXXXXXXX"
    }

    From what I can find, it appears the required information is present. If you are able to provide more context around the error Genesys is seeing, I would greatly appreciate it. 


    #WebMessaging

    ------------------------------
    Matthew Sorensen
    Business Systems Analyst
    ------------------------------
    #WebMessaging



  • 2.  RE: Authenticated Web Messaging HTTP 401

    Posted 23 days ago

    Good morning, fellow Matthew! :-)

    My team and I are experiencing a similar issue.  Did you ever get resolution to yours?  If you did and can provide any insight that helps us get past it ourselves, then I'll buy you a coffee!



    ------------------------------
    Matthew Pfluger
    ------------------------------



  • 3.  RE: Authenticated Web Messaging HTTP 401

    Posted 23 days ago
    Edited by Matthew Sorensen 23 days ago

    Hey!
    I did, but I strayed pretty far. I'll have to wait until I get home to grab the config I used. IIRC, there were a few functions(Not sure if that is the right word) that weren't called in the default template. I'm not sure if I did something wrong setting it up initially, though.
    Give me like 5-6 hours and I'll get it posted. Unless I forget 



    ------------------------------
    Matthew Sorensen
    Business Systems Analyst
    ------------------------------



  • 4.  RE: Authenticated Web Messaging HTTP 401

    Posted 22 days ago

    Good morning, Matthew!  If you have any time to shed light on your solution, I'd greatly appreciate it and will make good on my coffee offer. :-) I'd also be happy to offer any insight my team and I can share as well.

    Thanks in advance for your help!



    ------------------------------
    Matthew Pfluger
    ------------------------------



  • 5.  RE: Authenticated Web Messaging HTTP 401

    Posted 22 days ago
    Edited by Matthew Sorensen 22 days ago

    Morning! I apologize for the delay. I've moved away from Genesys a bit and lost quite a lot of access. Anyway, don't worry about the coffee order. This is the code that is working for me. Be warned, this was my first adventure into Javascript, but it does mostly work when using Keycloak as the OIDC provider (I wasn't able to get logout working, but that didn't matter for my purposes). 

    I don't remember which part cleared that error, sadly. 
     


    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8" />
      <meta name="viewport" content="width=device-width, initial-scale=1.0" />
      <title>Keycloak + Genesys Integration</title>
      <style>
        body { font-family: Arial, sans-serif; margin: 2rem; }
        button { margin: 0.5rem; padding: 0.5rem 1rem; font-size: 1rem; }
        #userinfo { margin-top: 1rem; white-space: pre-wrap; }
      </style>
    </head>
    <body>
      <h1>Keycloak + Genesys Web Messaging Auth</h1>
    
      <button id="login-btn">Login via Keycloak</button>
      <button id="logout-btn" style="display:none;">Logout</button>
    
      <!-- Genesys SDK -->
      <script type="text/javascript" charset="utf-8">
        (function (g, e, n, es, ys) {
          g['_genesysJs'] = e;
          g[e] = g[e] || function () {
            (g[e].q = g[e].q || []).push(arguments)
          };
          g[e].t = 1 * new Date();
          g[e].c = es;
          ys = document.createElement('script');
          ys.async = 1;
          ys.src = n;
          ys.charset = 'utf-8';
          document.head.appendChild(ys);
        })(window, 'Genesys', 'https://apps.mypurecloud.com/genesys-bootstrap/genesys.min.js', {
          environment: 'prod',
          deploymentId: 'REPLACE_WITH_DEPLOYMENT_ID'
        });
      </script>
    
      <script>
        const keycloak = {
          issuer: 'https://USE_ENV_OR_REPLACE_WITH_DOMAIN/realms/REPLACE_WITH_REALM',
          clientId: 'REPLACE_WITH_CLIENT_ID',
          redirectUri: window.location.origin + window.location.pathname,
          scopes: ['openid', 'profile', 'email', 'offline_access'],
        };
    
        let authCode = null;
        let nonce = null;
    
        function generateRandom(len = 16) {
          const arr = new Uint8Array(len);
          crypto.getRandomValues(arr);
          return Array.from(arr, b => ('0' + b.toString(16)).slice(-2)).join('');
        }
    
        document.getElementById('login-btn').addEventListener('click', () => {
          nonce = generateRandom();
          const state = generateRandom();
          sessionStorage.setItem('oauth_state', state);
          sessionStorage.setItem('oauth_nonce', nonce);
    
          const params = new URLSearchParams({
            client_id: keycloak.clientId,
            response_type: 'code',
            scope: keycloak.scopes.join(' '),
            redirect_uri: keycloak.redirectUri,
            state,
            nonce
          });
          window.location.href = `${keycloak.issuer}/protocol/openid-connect/auth?${params}`;
        });
    
        async function handleAuthCallback() {
          const params = new URLSearchParams(window.location.search);
          const code = params.get('code');
          const returnedState = params.get('state');
          const storedState = sessionStorage.getItem('oauth_state');
          const storedNonce = sessionStorage.getItem('oauth_nonce');
    
          if (code && returnedState === storedState) {
            authCode = code;
            nonce = storedNonce;
            sessionStorage.removeItem('oauth_state');
            sessionStorage.removeItem('oauth_nonce');
    
            document.getElementById('login-btn').style.display = 'none';
            document.getElementById('logout-btn').style.display = 'inline-block';
    
            activateGenesysPlugin();
          }
    
          window.history.replaceState({}, '', window.location.pathname);
        }
    
        function activateGenesysPlugin() {
          Genesys('registerPlugin', 'AuthProvider', (AuthProvider) => {
            AuthProvider.registerCommand('getAuthCode', (e) => {
              e.resolve({
                authCode,
                redirectUri: keycloak.redirectUri,
                nonce,
                maxAge: 3600,
                codeVerifier: null,
                iss: keycloak.issuer
              });
            });
    
            AuthProvider.registerCommand('reAuthenticate', (e) => {
              document.getElementById('login-btn').click();
              e.resolve();
            });
    
            document.getElementById('logout-btn').onclick = function () {
              AuthProvider.command('Auth.logout').then(async () => {
                await new Promise(resolve => setTimeout(resolve, 250));
                performAppLogout();
              });
            };
    
            AuthProvider.ready();
          });
        }
    
        function performAppLogout() {
          sessionStorage.clear();
          authCode = null;
          nonce = null;
    
          document.getElementById('login-btn').style.display = 'inline-block';
          document.getElementById('logout-btn').style.display = 'none';
    
          const logoutUrl = `${keycloak.issuer}/protocol/openid-connect/logout' +
             '?id_token=${idToken}' +
             '?post_logout_redirect_uri=${encodeURIComponent(keycloak.redirectUri)}`;
          window.location.href = logoutUrl;
        }
    
        handleAuthCallback();
      </script>
    </body>
    </html>



    ------------------------------
    Matthew Sorensen
    Business Systems Analyst
    ------------------------------



  • 6.  RE: Authenticated Web Messaging HTTP 401

    Posted 22 days ago

    I want to add a bit more information. I encountered a lot of the same issues you are facing and fell down the same holes. I can't speak to further features, but I can tell you this allows the 'caller' to appear to the agent with their name as listed in the OIDC provider.
     
    My setup
    OIDC Provider - KeyCloak with a couple users listed. I did not modify anything from their default docker container as far as user claims, etc. 
    Genesys - No External Contacts setup. These users do not exist in Genesys. The only way Genesys could identify them is the oauthtojwt endpoint with Keycloak. 
    Website - Full code is listed above.



    ------------------------------
    Matthew Sorensen
    Business Systems Analyst
    ------------------------------



  • 7.  RE: Authenticated Web Messaging HTTP 401

    Posted 19 days ago

    Good afternoon, Matthew!  I apologize for my delay in responding.  I really appreciate your time and input.

    Quite annoyingly, we were not able to determine the root cause of the 401 error, though we have managed to get around it by recreating the resources in both SalesForce (the OAuth client, though they call it "External Client App") and in Genesys (the Integration, Configuration, and Deployment).  I'm not sure exactly which of these replacements caused everything to work, though my suspicion is actually that something was wrong within SalesForce.

    I say that only because my final test at my client was to replace only the OAuth client in SalesForce and update the Integration and Web App to use this new client.  After making these changes, we were able to load the authenticated web messaging SDK.  However, on previous tests, we were unclear as to whether the issue was in Genesys or SalesForce.  Sadly, to date, we haven't heard from Genesys Engineers on our ticket as to what caused our requests to fail (as documented here), so I don't have any further information.

    Finally, as I compare your code to ours (and thank you for providing it!), I see a lot of similarities.  We also did not modify the default settings of SalesForce OAuth clients beyond the obvious (i.e. redirectURLs, id token timeouts, etc.), and we used no custom claims.  In Genesys, we also didn't use any external contacts.  One major difference between yours and ours is that our client doesn't wish to use PKCE, so we don't have quite the rigor which you did.

    At this point, I'm not sure why we were receiving the 401 errors, and I'm not sure I'll ever know.  However, I do appreciate you taking time to help us.  Thanks again!



    ------------------------------
    Matthew Pfluger
    ------------------------------



  • 8.  RE: Authenticated Web Messaging HTTP 401

    Posted 17 days ago
    Thanks for the detailed reply. I'm glad you got it working! Hopefully, the code and information can help someone else. My biggest struggle was not being able to see a working implementation to compare against. 

    ––––––­­–

    Matthew Sorensen 

    Service Desk Analyst 

    Western Governors University 

    matthew.sorensen@wgu.edu

    877-435-7948 

     

    Image