Thank you for replying, and I apologize for my delay in responding.
Thank you also for your detailed explanation about the use of the `sub` claim. I can confirm we weren't using any custom claims or changing the `sub` in any way. I'm also confused why that would have made a difference. There isn't any way we can control how Genesys interprets the claims from the JWT, nor is there any way we can modify the `sub` claim's value as sent from SalesForce.
I should have included the following information in my original post. Prior to receiving the 401 errors, we were able to create a web app portal and OAuth client within SalesForce that did successfully exchange authorization codes for Genesys JWTs. As we visually compared the settings between the working and non-working environments, we couldn't find any obvious differences.
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.
Thank you again for your help. If I hear back from Genesys with more information on why our requests failed, then I will include it here.
Original Message:
Sent: 10-29-2025 13:37
From: Fernando Sotto dos Santos
Subject: Cannot exchange OIDC auth code for Genesys JWT
Olá Matthew,
Obrigado pelo retorno e por compartilhar o conteúdo do ID token. Com base no payload que você enviou, o sub realmente está presente, mas há um ponto importante de compatibilidade entre o Salesforce como IdP e o Web Messaging do Genesys Cloud:
Quando o Genesys faz a troca no endpoint de JWT Exchange, ele não utiliza o sub exatamente como está vindo do Salesforce. O Genesys precisa conseguir relacionar esse identificador com um External Contact ou com o contexto ativo do deployment Web Messaging. Para isso, há três requisitos que normalmente precisam estar alinhados:
O valor de sub deve ser um identificador estável do usuário, não um URL completo ou formato composto
O formato que vem do Salesforce costuma ser algo como:
O Genesys não faz parsing ou extração desse userId. Ele usa o valor literal do claim para tentar localizar o usuário. Na prática, isso resulta em "não encontrado".
Se não existe um External Contact cujo externalId corresponda exatamente ao valor do sub, o Genesys não consegue correlacionar a sessão
Por padrão, o Web Messaging espera uma correspondência direta com o External Contact para identificação da pessoa na plataforma.
A integração Web Messaging deve estar configurada para aceitar o claim como identificador de usuário
Caso contrário, a associação é rejeitada e a troca do token falha com 401.
O caminho mais seguro para resolver isso é configurar para que o Salesforce envie no sub (ou em outro claim acordado, como email ou preferred_username) um identificador que exista no Genesys, por exemplo:
• um UUID de External Contact no Genesys
• um e-mail que já esteja cadastrado e seja exclusivo
• um identificador normalizado que você também salve como externalId no Genesys
Duas boas opções para ajustar rapidamente:
Opção A
Alterar a configuração da integração no Salesforce para que o sub seja um identificador simples e estável (não o URL).
Opção B
Criar/atualizar External Contacts no Genesys definindo como externalId exatamente o valor que está vindo hoje no sub.
------------------------------
Fernando Sotto dos Santos
Consultor Grupo Casas Bahia
Original Message:
Sent: 10-28-2025 17:46
From: Matthew Pfluger
Subject: Cannot exchange OIDC auth code for Genesys JWT
Hi Fernando! Thank you for the detailed reply. I am quite grateful.
I've carefully reviewed and followed all your suggestions, many of which I've already done. The one that I'm not sure I understand is this one:
> The JWT must correctly include the claim sub and match it to the Web Messaging Contact. If the sub is not present or there is no match in the context of the session, Genesys does not recognize the user.
Can you tell me more about this recommendation? If you mean the ID token which the OAuth Authorize endpoint returns when exchanging an auth code for a token, then I can confirm the `id_token` does include the sub:

Is there something about this step I'm missing? We are able to perform all the OAuth calls we need via Postman hitting SalesForce's endpoints directly, cutting Genesys out of the loop. I'm starting to suspect that something may be wrong in the backend of Genesys for either the Integration, Configuration, or Deployment - something which we cannot control. I'm hoping that Genesys Engineers see this post and give me insight into the logs using our `contextId` values... :-)
------------------------------
Matthew Pfluger
Original Message:
Sent: 10-28-2025 16:10
From: Fernando Sotto dos Santos
Subject: Cannot exchange OIDC auth code for Genesys JWT
Olá Matthew,
Quando a API retorna 401 no endpoint oauthcodegrantjwtexchange com a mensagem "Failed to identify user for token", isso normalmente significa que o token recebido pelo Genesys não pode ser associado ao deployment Web Messaging informado.
Mesmo quando o fluxo OIDC está correto no provedor de identidade, alguns pontos específicos devem ser validados no Genesys Cloud:
Associação correta entre DeploymentId e Integration
A integração Web Messaging precisa estar vinculada ao deployment específico utilizado no widget. Se houver dois deployments apontando para a mesma página ou ambiente Salesforce, pode ocorrer conflito.
O ClientID da integração Web Messaging deve ser exatamente o mesmo utilizado para gerar o código de autorização
Diferenças sutis, como maiúsculas/minúsculas ou configuração em ambiente de teste versus produção, podem gerar o erro citado.
O JWT deve incluir corretamente o claim sub e correspondê-lo ao Contact do Web Messaging
Se o sub não estiver presente ou não houver correspondência no contexto da sessão, o Genesys não reconhece o usuário.
Verificar o campo deploymentId passado no request
Sempre garantir que o valor enviado no body corresponde ao deployment ativo para aquela integração.
Certificar que não há configuração de Expiration Time muito curto
Se o código estiver expirando antes da troca, o Genesys também retorna 401.
Confirmar o redirect URI configurado no IdP e no Genesys
Ambos devem ser idênticos ao utilizado na página Salesforce, incluindo HTTPS e caminhos exatos.
Recomendações imediatas para diagnóstico:
• Validar no DevTools do navegador se o deploymentId usado na biblioteca de Web Messaging é o mesmo enviado na etapa de exchange
• Conferir se os dois ambientes (o que funciona e o que falha) utilizam a mesma Integration e o mesmo ClientID
• Regerar o código de autorização e tentar a troca imediatamente para evitar expiração
• Usar um único deployment por página para eliminar ambiguidade de roteamento
------------------------------
Fernando Sotto dos Santos
ConsultorVIA VAREJO
Original Message:
Sent: 10-28-2025 13:15
From: Matthew Pfluger
Subject: Cannot exchange OIDC auth code for Genesys JWT
Similar to this thread and this thread, we are seeing 401 response codes when invoking the oauthcodegrantjwtexchange endpoint.
```json
{
"message": "Failed to identify user for token: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX deploymentId: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
"code": "unauthorized",
"status": 401,
"contextId": "1463f088-b3ae-4559-b1f1-23f6d839ad8f",
"details": [],
"errors": []
}
```
Similar to this thread, we are seeing successes when using a different integration/configuration/deployment combination. Our authentication server in both cases is SalesForce, though there are different client apps used in both cases. We've checked all the obvious, including:
- the client ID/secret on the Integration
- confirming the well-known configuration URL
- ensuring the ClientID is correctly set in our JavaScript snippet on the web page
As far as we can tell, all the configurations in Genesys Cloud and SalesForce are the same between the two configurations, but one of them does not work.
Seeing that a few others have posted `contextId` values for Genesys Support Engineers to use for retrieving log messages, I will provide a few `contextId` values from some of our most recent failing calls:
- 52e263e5-ee68-46b7-880b-18ccf44cc279
- 7de5d9c8-6490-4121-af62-5cbb68aed050
- e94beae7-497f-4ac2-8253-327b9982cf67
How can we get more insight into why these requests are failing?
#WebMessaging
------------------------------
Matthew Pfluger
------------------------------