Discussion
Pegasystems Inc.
PL
Last activity: 25 Jan 2024 4:55 EST
Troubleshooting OpenID Connect (OIDC) integrations
Pega Platform can be configured to authenticate against any external Identity Provider (IdP) which supports OpenID Connect (OIDC) protocol. See for example how to do it with Okta, Auth0 or miniOrange.
In most cases such integration is straightforward and works on the first try. Sometimes however a bit of troubleshooting may be required. This article describes tools and techniques useful in investigating problems with integrations of Pega Platform with external Identity Providers.
Pega Platform logs
The first troubleshooting tool is a properly configured Pega Platform log. In Developer Studio, go to Configure > System > Operations > Logs and click "Logging level settings". Find the logger corresponding to OIDCClientHandler and set the log level to "ALL".
This will give you detailed logs for each authentication attempt involving OIDC. For example, if your Pega Platform is configured with Okta as described here, the logs for a single successful authentication look like this:
Initiating OIDC flow
Constructing authorization URL for OIDC provider
Constructed authorization URL for OIDC provider : https://dev-500306.oktapreview.com/oauth2/...
Processing authcode received from OIDC provider
Fetching access token using authCode received
Successfully fetched access token and ID token using authCode
Validating ID token received from access token end point eyJraWQiOiJ5dVBUeVBUUEdjcE1WamxpNE...
Successfully validated ID token with standard claims
Retrieving userInfo claims from user info Endpoint
Fetch operator from claim {email} from received ID token claims
Successfully established operator from received ID token claims
Successfully authenticated operator with OIDC flow
The most useful part of the log is the ID token, which you can see in line 7 of the example above. In order to extract human-readable information from the ID token, we will use a 3rd party tool.
JWT Debugger
JWT Debugger provided by Auth0 allows to decode any JWT token and verify its signature. Copy paste the token from your log files into the "Encoded" field of the debugger. The "Decoded" filed will show you the header and payload of your token in form of easy to read JSON objects. This allows you to see information specific to the user who attempted to log in, such as name and email, and information specific to the integration.
You can now compare information from the token with information from the authorization request initiated by Pega. Take a closer look at line 3 of the log file. It contains the authorization URL with a number of parameters, in particular:
- client_id = 0oagl4s7p9LyhbUop0h7
- nonce = 460b76114f7dc13c9de8f92d67de57877bf95b5fc6f71b26d6df1a3cd6b1591e
You should verify that:
- Audience ("aud") from the token matches the client_id from the request parameters
- Nonce ("nonce") from the token matches the nonce from the request parameters
- Additionally, that issuer (“iss”) from the token matches the Issuer in your Pega authentication service configuration
JSON Web Token debugger allows you to also verify the token signature. In order to do it, you need to locate the public key corresponding to unique key identifier ("kid") from the ID token header. The key is available in the keystore used by your Pega authentication service. Go to the authentication service configuration and open the keystore associated with the service.
In case of our Okta example it looks like this:
Download the keystore from the URL. It's a JSON file so you can open it in a text editor, but it's much more convenient to use yet another tool.
JQ Play
JQ Play service allows to conveniently view and manipulate JSON files in a web browser. Paste the contents of the downloaded JWKS keystore into the "JSON" field and enter . (dot) as the filter. This will show the contents of the keystore in a nicely formatted form in the "Result" field.
Find the key with "kid" corresponding to the "kid" from the ID token. In our example the "kid" in ID token header in JSON Web Token debugger is "yuPTyPTPGcpMVjli4CcYXHZU0rBU3Jl_ODGN9-3UjOs". It corresponds to the first key in the keystore displayed in JQ Play.
Copy the whole key, from { to } characters, and paste it into the field labeled "Public Key or Certificate" in the JWT Debugger.
Pasting this key into JWT Debugger triggers the signature verification and if successful, shows the "Signature Verified" message.
Postman
In case an integration is not working and it's difficult to identify whether the problem is on Pega platform side or Identity Provider side, it's a good idea to try the same scenario with only one of these parties involved. You can use Postman to act as OIDC client, so you can use this tool to remove Pega Platform from the equation.
Start Postman, create a new request, and switch to the “Authorization” tab. Choose “OAuth 2.0” as the type. This will give you "Get New Access Token" button, which allows to initiate the OIDC authentication flow.
After clicking "Get New Access Token" you get a configuration dialog. Copy configuration from your Pega authentication service to the corresponding fields in Postman. Notice that the state parameter is not part of the authentication service configuration, but is chosen randomly by Pega Platform for each request. You can see a sample value of the "state" parameter in authorization URL we examined in a previous section. For Postman you can use any random string there.
The screenshot below shows Postman configuration corresponding to the Pega authentication service configured with miniOrange.
Click “Request Token”. This will trigger the authentication process and on successful completion will present you with a token obtained from Identity Provider, without any participation from the Pega platform.
You can now copy the value of the ID token and use JWT Debugger to analyze the contents of the token and verify its signature. As described here, miniOrange provides their key in the PEM format. This is not a problem for JWT debugger, you can use a key in PEM format directly to verify the token signature.
If the OIDC flow executed with Postman succeeded , the token contained the expected information and was verified successfully, yet the integration with Pega does not work, you now that the problem may be misconfiguration on the Pega side. However, if you were able to reproduce the problem with the integration using just Postman, you now know that it has nothing to do with Pega and you should focus your investigation on the Identity Provider.
Appendix: list of software
This article used the following versions of the described software:
- Pega Platform 8.1.1
- JWT Debugger
- JQ Play 1.6
- Postman 6.5.3
-
Reply
-
Mohamad Shokor Pawel Adamczuk Tom Zhang Yao Yao -
Share this page Facebook Twitter LinkedIn Email Copying... Copied!
Ford Motor Company
US
Hi @Jarek
Do these settings work on Pega 7.4 running inside Openshift? I have configured the log level as you had indicated. I have also configured the Authenticator service to connect using OpenID. However, I see the message in the PegaRULES-ALERT.log as "Error authenticating xxxxx: The user must use external authentication". Can you tell me how to troubleshoot the issue?
Thanks!
Balaji
Pegasystems Inc.
PL
Hi Balaji,
Each Pega user (aka operator) which logs in via OpenID must be configured on the Pega side to use external authentication. If you go to the operator record in Pega Designer Studio, and click "Security" tab, you will see a checkbox labeled "Use external authentication". This must be checked to allow the operator to log in via OpenId.
Ford Motor Company
US
@Jarek, Thanks for the reply. I have configured the operator id to have external authentication. But, still I get the above error. (Error authenticating xxxx: This user must use external authentication) How do I troubleshoot this issue?
Pegasystems Inc.
PL
Hi Balaji,
I looked further into this problem. The message "Error authenticating [UserName]: This user must use external authentication." is logged in case a user with external authentication checkbox checked is trying to log-in using Pega authentication. This would suggest, that your operator is properly configured, but you try to login in via Pega, instead of external identity provider.
Can you confirm that when you log in, you enter the credentials on a login page served by external OpenID provider, not on any page or servlet served by Pega?
Ford Motor Company
US
I am not able to get the login page of the external IDP when I try to hit the login URL configured in the Pega authenticator service. I am suspecting the integration with IDP is not configured correctly. I am following up with the IDP. I will post back with my comments. Thanks!
Pegasystems Inc.
PL
Hi @BalajiR1491,
Yes, with properly configured integration going to Login URL should redirect you to Identity provider login page.
You may try to set logging level to ALL for "com.pega.pegarules.integration.engine.internal.sso.oidc.OIDCClientHandler " and look into the log file. There should be a message "Constructed authorization URL for OIDC provider" followed by the URL to which Pega redirects when you acess the Login URL. This may help you with troubleshooting.
Ford Motor Company
US
I configured the Authentication service to be similar to your definition above but I did not get redirected to the IDP login screen. Instead, I only get the Pega login screen. However, I was able to generate an access token using postman client. Also, even with the log levels configured in Pega, I did not see any entries in the PegaRULES.log relating to the OIDC connect authentication. We are working with the beta version of Pega 7.4 running inside Docker container. I am guessing that the Docker image does not have the PRAuth modules relating to the OIDC Connect. I will contact Pega if they have any updates. Thanks!
Pegasystems
IN
Please check your web.xml and see if PRAuth is one of the servlet defined. I am suspecting you are using a prweb from a older release.
Accenture
JP
Hi I'm working on OIDC integration with Pega 8.1.1.
At Authentication Service in DEV STUDIO, OIDC Auth Service does not provide Authentication Activity and Timeout Activity. I need to imprement timeout mechanizm with OIDC. What is the extention point for timeout with OIDC as SSO providor?
Pegasystems Inc.
PL
Hello,
At the bottom of OIDC Authentication Service configuration, in the Advanced section, there is a checkbox which allows you to make the service respect the authentication timeout specified in the operator's access group.
Accenture
JP
I already knew "Use access group timeout" and it corresponds Data-Admin-AuthService.pySupportsPegaTimeout to "true".
but when i login to pega through OIDC, nothing occurs nevertheless Authentication Timeout specified in AccessGroup settings. Of course non-SSO authenticated operator belongs to same AccessGroup can recieved re-login attempt dialog.
Pegasystems Inc.
PL
Tamon, I will ask some of my colleagues with more knowledge on the subject to take a look at your question.
Pegasystems
IN
The access group timeout is the inactivity timeout. There are no hooks for timeout activity for OIDC. Can you describe what you expect to happen upon timeout?
Accenture
JP
Hi Srikanth
Thank you for your relply.
When thinking about SSO, once Pega as RP apps kill an operator's requestor after timeout, then the operator try to access to pega and the operator redirected to IDP. IDP comfirms the request still be authenticated it self because IDP's session remains. so, the operator can re-login to pega without any challenges held by IDP. this makes loop that RP kills its session, then IDP allow to login to RP, then RP kills its session and so on. To end this loop, i must imprement kill IDP's session by timeout within RP's session. Thus i need to hook timeout.
In particular, after timeout in Pega(RP) i have to make browser redirected to call end_session_endpoint to IDP for killing IDP's session. ("end_session_endpoint" is specified OpenID connect spec at "https://openid.net/specs/openid-connect-session-1_0.html#RPLogout".)
Tentatively I've implemented setting Authentication Timeout Activity to OIDC Authentication Service(Data-Admin-AuthService) and it enabled to hook authentication timeout with SSO operator.
but as you mentioned OIDC does not provide functionality to setting "Authentication Timeout Activity(.pyTimeoutActivity)". So this way is not garanteed by anything else. What is the correct way?
My corregue asked about this at SR-C80960.
Cognizant Technology Solutions
US
Hi @Jarek.Cora
We have an application which going to accessible over Web and mobile app. If I can configure the authentication service rule based on the link https://collaborate.pega.com/discussion/configuring-pega-mobile-client-authenticate-against-okta , can I leverage it for both Web & Mobile. In that article, in step 1, I see that in the Okta console there is an option to choose the platform and its either one of mobile or web. How can this be made to work for both web and mobile.
And unlike SAML, I don't see any activity in the authentication service rule which is called post authentication, in which we can any further details to the operator ID. Is there any such provision in Open ID connect
Thanks
Venkat
Pegasystems Inc.
PL
Hi Venkat,
Thank you for your questions. The configuration described in https://collaborate.pega.com/discussion/configuring-pega-mobile-client-authenticate-against-okta will work for both web and mobile. The fact that we choose "native" type of integration in Okta console does not prevent it from working in web. In fact Step 4 in Part One of this article describes testing this setup with a desktop browser.
As for post-auth activity, this should work with OIDC. However, since Pega 8.2, operator provisioning supports DataTransform , so in many cases there is no longer need to use post-auth activity.
Services Australia
AU
@Jarek.Cora - Nice article, Iam trying to get OpenID connect working with OpenAM as the IDP. After enabling the logs i can see the following in the logs
- Initiating OIDC flow
- Constructing authorization URL for OIDC provider
- Constructed authorization URL for OIDC provider :
- Processing authorization code recieved from OIDC provider
- StateParam Validation is successful
- Fetching access token using authCode received
- Successfully fetched accesss token and ID token using authCode
- Validating ID token received from access token end point
- JWT is Signed
- Successfully authenticated operator with OIDC flow
However, i still see an error message "Unable to execute OIDC flow : Caught exception while parsing the id token" in the browser and PegaRULES-SecurityEvent.log. Any ideas ?
Pegasystems Inc.
PL
Hello Satish,
I'm really sorry the OIDC integration is not working for you out-of-the-box for you. From what you described the exception happens after " Successfully authenticated operator with OIDC flow", which is a bit puzzling. I think the best next step will be to open a support ticket to have one of Pega OIDC experts debugs your particular case.
I apologize I cannot provide you with a more concrete advice.
Services Australia
AU
No worries mate, i will follow it up with the support team.
Services Australia
AU
Just an update, based on the resolution provided by the engineering team after changing the signing algorithm of the ID Token to asymmetric keys we were able to get the SSO working. ie, changing from HS256 to RS256.
NJ Courts
US
Hi Jarek,
Great article. We configured Open ID with 8.2.2 Pega cloud version and are sucessfully seeing below steps:
Hi Jarek,
Great article. We configured Open ID with 8.2.2 Pega cloud version and are sucessfully seeing below steps:
Initiating OIDC flow
- Constructing authorization URL for OIDC provider
- Constructed authorization URL for OIDC provider :
- Processing authorization code recieved from OIDC provider
- StateParam Validation is successful
- Fetching access token using authCode received
- Successfully fetched accesss token and ID token using authCode
- Validating ID token received from access token end point
Receiving an error after seeing above in logs. We have enabled client.oauth2.OAuth2ClientImpl as well which gave below message:
Creating access token page for Client ID = XXXXXXXXXXXX
After this we are seeing response details
Response details:
access_token = *********
refresh_token = *********
scope = openid
id_token = Some data
token_type = bearer
expires_in = 3599
And running into error after:
com.pega.pegarules.pub.PRRuntimeException: Unable to execute OIDC flow : Caught exception while parsing the id token at com.pega.pegarules.session.internal.mgmt.authentication.SchemePRAuth.authenticateOperator(SchemePRAuth.java:386) ~[prprivate.jar:?] at com.pega.pegarules.session.internal.mgmt.authentication.Authentication.doAuthentication(Authentication.java:508) ~[prprivate.jar:?] at com.pega.pegarules.session.internal.engineinterface.service.HTTPAuthenticationHandler.performAuthentication(HTTPAuthenticationHandler.java:251) ~[prprivate.jar:?] at com.pega.pegarules.session.internal.engineinterface.service.HTTPAuthenticationHandler.doHttpReqAuthentication(HTTPAuthenticationHandler.java:94) ~[prprivate.jar:?] at com.pega.pegarules.session.internal.engineinterface.service.HttpAPI.handleAuthentication(HttpAPI.java:2639) ~[prprivate.jar:?] at com.pega.pegarules.session.external.engineinterface.service.EngineAPI.activityExecutionProlog(EngineAPI.java:597) ~[prenginext.jar:?] at com.pega.pegarules.session.external.engineinterface.service.EngineAPI.processRequestInner(EngineAPI.java:436) ~[prenginext.jar:?] at sun.reflect.GeneratedMethodAccessor122.invoke(Unknown Source) ~[?:?] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_171] at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_171] at com.pega.pegarules.session.internal.PRSessionProviderImpl.performTargetActionWithLock(PRSessionProviderImpl.java:1382) ~[prprivate.jar:?] at com.pega.pegarules.session.internal.PRSessionProviderImpl.doWithRequestorLocked(PRSessionProviderImpl.java:1114) ~[prprivate.jar:?] at com.pega.pegarules.session.internal.PRSessionProviderImpl.doWithRequestorLocked(PRSessionProviderImpl.java:968) ~[prprivate.jar:?] at com.pega.pegarules.session.external.engineinterface.service.EngineAPI.processRequest(EngineAPI.java:361) ~[prenginext.jar:?] at com.pega.pegarules.session.internal.engineinterface.service.HttpAPI.invoke(HttpAPI.java:892) ~[prprivate.jar:?] at com.pega.pegarules.session.internal.engineinterface.etier.impl.EngineImpl._invokeEngine_privact(EngineImpl.java:331) ~[prprivate.jar:?] at com.pega.pegarules.session.internal.engineinterface.etier.impl.EngineImpl.invokeEngine(EngineImpl.java:274) ~[prprivate.jar:?] at com.pega.pegarules.session.internal.engineinterface.etier.impl.EngineImpl.invokeEngine(EngineImpl.java:251) ~[prprivate.jar:?] at com.pega.pegarules.priv.context.JNDIEnvironment.invokeEngineInner(JNDIEnvironment.java:275) ~[prpublic.jar:?] at com.pega.pegarules.priv.context.JNDIEnvironment.invokeEngine(JNDIEnvironment.java:220) ~[prpublic.jar:?] at com.pega.pegarules.web.impl.WebStandardImpl.makeEtierRequest(WebStandardImpl.java:728) ~[prwebj2ee.jar:?] at com.pega.pegarules.web.impl.WebStandardImpl.doPost(WebStandardImpl.java:412) ~[prwebj2ee.jar:?] at sun.reflect.GeneratedMethodAccessor139.invoke(Unknown Source) ~[?:?] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_171] at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_171] at com.pega.pegarules.internal.bootstrap.PRBootstrap.invokeMethod(PRBootstrap.java:381) ~[prbootstrap-8.2.2-354.jar:8.2.2-354] at com.pega.pegarules.internal.bootstrap.PRBootstrap.invokeMethodPropagatingThrowable(PRBootstrap.java:422) ~[prbootstrap-8.2.2-354.jar:8.2.2-354] at com.pega.pegarules.boot.internal.extbridge.AppServerBridgeToPega.invokeMethodPropagatingThrowable(AppServerBridgeToPega.java:224) ~[prbootstrap-api-8.2.2-354.jar:8.2.2-354] at com.pega.pegarules.boot.internal.extbridge.AppServerBridgeToPega.invokeMethod(AppServerBridgeToPega.java:273) ~[prbootstrap-api-8.2.2-354.jar:8.2.2-354] at com.pega.pegarules.internal.web.servlet.WebStandardBoot.doPost(WebStandardBoot.java:141) ~[prbootstrap-api-8.2.2-354.jar:8.2.2-354] at com.pega.pegarules.internal.web.servlet.WebStandardBoot.doGet(WebStandardBoot.java:102) ~[prbootstrap-api-8.2.2-354.jar:8.2.2-354] at javax.servlet.http.HttpServlet.service(HttpServlet.java:624) ~[servlet-api.jar:?] at com.pega.pegarules.internal.web.servlet.WebStandardBoot.service(WebStandardBoot.java:167) ~[prbootstrap-api-8.2.2-354.jar:8.2.2-354] at javax.servlet.http.HttpServlet.service(HttpServlet.java:731) ~[servlet-api.jar:?] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303) ~[catalina.jar:7.0.88] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) ~[catalina.jar:7.0.88] at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) ~[tomcat7-websocket.jar:7.0.88] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) ~[catalina.jar:7.0.88] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) ~[catalina.jar:7.0.88] at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219) ~[catalina.jar:7.0.88] at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:110) ~[catalina.jar:7.0.88] at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:498) ~[catalina.jar:7.0.88] at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:169) ~[catalina.jar:7.0.88] at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103) ~[catalina.jar:7.0.88] at org.apache.catalina.valves.RemoteIpValve.invoke(RemoteIpValve.java:683) ~[catalina.jar:7.0.88] at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:1025) ~[catalina.jar:7.0.88] at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116) ~[catalina.jar:7.0.88] at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:445) ~[catalina.jar:7.0.88] at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1139) ~[tomcat-coyote.jar:7.0.88] at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:637) ~[tomcat-coyote.jar:7.0.88] at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.doRun(AprEndpoint.java:2555) ~[tomcat-coyote.jar:7.0.88] at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:2544) ~[tomcat-coyote.jar:7.0.88] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:1.8.0_171] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:1.8.0_171] at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-coyote.jar:7.0.88] at java.lang.Thread.run(Thread.java:748) [?:1.8.0_171] Caused by: com.pega.pegarules.pub.PRRuntimeException: Unable to execute OIDC flow : Caught exception while parsing the id token at com.pega.pegarules.integration.engine.internal.auth.oidc.OIDCClientHandler.processAuthcodeRes(OIDCClientHandler.java:140) ~[printegrint.jar:?] at com.pega.pegarules.integration.engine.internal.auth.oidc.OIDCClientHandler.authenticate(OIDCClientHandler.java:70) ~[printegrint.jar:?] at com.pega.pegarules.session.internal.mgmt.authentication.SchemePRAuth.authenticateOperator(SchemePRAuth.java:372) ~[prprivate.jar:?] ... 55 more Caused by: com.pega.pegarules.pub.PRRuntimeException: Caught exception while parsing the id token at com.pega.pegarules.integration.engine.internal.auth.oidc.NimbusOIDCClientHandler.processIDToken(NimbusOIDCClientHandler.java:79) ~[printegrint.jar:?] at com.pega.pegarules.integration.engine.internal.auth.oidc.OIDCClientHandler.processIDToken(OIDCClientHandler.java:200) ~[printegrint.jar:?] at com.pega.pegarules.integration.engine.internal.auth.oidc.OIDCClientHandler.processAuthcodeRes(OIDCClientHandler.java:126) ~[printegrint.jar:?] at com.pega.pegarules.integration.engine.internal.auth.oidc.OIDCClientHandler.authenticate(OIDCClientHandler.java:70) ~[printegrint.jar:?] at com.pega.pegarules.session.internal.mgmt.authentication.SchemePRAuth.authenticateOperator(SchemePRAuth.java:372) ~[prprivate.jar:?] ... 55 more Caused by: java.lang.NullPointerException at com.pega.pegarules.session.external.authorization.KeystoreData.addPublicKeyCertificatesToAliasMap(KeystoreData.java:493) ~[prenginext.jar:?] at com.pega.pegarules.session.external.authorization.KeystoreData.<init>(KeystoreData.java:560) ~[prenginext.jar:?] at com.pega.pegarules.session.internal.authorization.KeyStoreCacheImpl.put(KeyStoreCacheImpl.java:464) ~[prprivate.jar:?] at com.pega.pegarules.session.internal.authorization.KeyStoreCacheImpl.loadKeyStoretoCache(KeyStoreCacheImpl.java:288) ~[prprivate.jar:?] at com.pega.pegarules.session.internal.authorization.KeyStoreCacheImpl.loadKeyStoreIfKeyStoreNotCachedYet(KeyStoreCacheImpl.java:438) ~[prprivate.jar:?] at com.pega.pegarules.session.internal.authorization.KeyStoreCacheImpl.getPublicKey(KeyStoreCacheImpl.java:626) ~[prprivate.jar:?] at com.pega.pegarules.integration.engine.internal.util.KeyStoreUtilsImpl.getPublicKey(KeyStoreUtilsImpl.java:1088) ~[printegrint.jar:?] at com.pega.pegarules.integration.engine.internal.security.jwt.NimbusJWTProcessor.getJWSKeySelectorFromPubKey(NimbusJWTProcessor.java:547) ~[printegrint.jar:?] at com.pega.pegarules.integration.engine.internal.security.jwt.NimbusJWTProcessor.getJWSKeySelector(NimbusJWTProcessor.java:480) ~[printegrint.jar:?] at com.pega.pegarules.integration.engine.internal.auth.oidc.NimbusOIDCClientHandler.processIDToken(NimbusOIDCClientHandler.java:76) ~[printegrint.jar:?] at com.pega.pegarules.integration.engine.internal.auth.oidc.OIDCClientHandler.processIDToken(OIDCClientHandler.java:200) ~[printegrint.jar:?] at com.pega.pegarules.integration.engine.internal.auth.oidc.OIDCClientHandler.processAuthcodeRes(OIDCClientHandler.java:126) ~[printegrint.jar:?] at com.pega.pegarules.integration.engine.internal.auth.oidc.OIDCClientHandler.authenticate(OIDCClientHandler.java:70) ~[printegrint.jar:?] at com.pega.pegarules.session.internal.mgmt.authentication.SchemePRAuth.authenticateOperator(SchemePRAuth.java:372) ~[prprivate.jar:?]
Please help. Thanks!
Pegasystems Inc.
PL
Hi Chaithanya,
Looking at the log you provided the root cause is NullPointerException in com.pega.pegarules.session.external.authorization.KeystoreData.addPublicKeyCertificatesToAliasMap(KeystoreData.java:493)
This indicates that there might be something wrong with keystore you provided to verify signature of the id token. However, the problem should have been handled gracefully by Pega and you should have received a meaningful information about the problem, instead of NullPointerException hidden in the log files.
My initial assessment is that should be fixed in the platform. It would be great if you could report a ticket to Pega support for this case, so they pass it the the appropriate team. You still may need to modify the keystore, but at least you should receive meaningful info what's wrong with it.
Thank you.
NJ Courts
US
Hi Jarek,
Thanks a lot for your quick response. I will raise a ticket with Pega and will also bring this up with IDP team ( IBM ISAM) about the keystore.
But as you suggested in troubleshooting, I actually took the access token and decoded to fetch keyID. At the same time, fetched key ID block from KeyStore (JWK url provided by IDP). After inputting the KeyID from Keystore into JWT debugger, it confirmed that Signature is verified.
Please suggest if you still think there is a problem with the KeyStore ?
By any chance is our issues similar to what happened in below link: https://community.pega.com/support/support-articles/unable-integrate-sso-platform-using-jwt We are on version 8.2.2 .
Thanks a lot for all your help.
Chaits
Pegasystems Inc.
PL
It might not be the problem with the keystore itself, but for some reason Pega cannot extract a key from it. I looked at the actual source code and it seems that for some reason Key Id extracted by Pega from the keystore is null.
What might help in troubleshooting would be to set the log level for com.pega.pegarules.session.external.authorization.KeystoreData to debug. This should generate more information. In particular this should give you the following messages:
"Extract keys from JWK keystore : <key store name>"
and
"kid is null and keys size is <size> so substituting with keystore name <key store name>"
NJ Courts
US
Thanks Marek. After enabling KeyData logger, seeing the below. Not seeing KeyID null message but saw below messages before getting the exception.
Pegasystems Inc.
PL
Apparently the situation is more complex than I initially assumed. I think it you need to wait for the support ticket to be resolved by the Pega experts in the area of OIDC authentication.
NJ Courts
US
Hi Jarek,
Thanks a lot for your response. We are raising a high severity SR right away. Thanks!
NJ Courts
US
We made a small change to Keystore in Pega, instead of referencing JWK using the url, we uploaded the jks file into Keystore RuleInstance. We are seeing below log messages and different exception.
Raising a SR in parallel. Sorry to bother you. Any thoughts on new exception ?
We made a small change to Keystore in Pega, instead of referencing JWK using the url, we uploaded the jks file into Keystore RuleInstance. We are seeing below log messages and different exception.
Raising a SR in parallel. Sorry to bother you. Any thoughts on new exception ?
Pegasystems Inc.
PL
Hi Chaits,
I looked at the new exception your are now getting. It's thrown in case the public key retrieved by Pega from the keystore is null. So although the message is different, and the exception is thrown from a different place of the code, the underlying reason seems to be the same as before - for some reason Pega finds a "null" key in your keystore.
I know this information is not of much help to you, sorry about it. I hopey the SR will be resolved promptly.
Jarek
Pegasystems Inc.
FR
Hi Jarek,
Is it difficult to setup an OpenID SSO with PingFederate on a Development environment? Do we have any documentation to setup such SSO?
Thank you
Cognizant
IN
Hi Jarek,
I have implemented the OpenID service. When I try to hit the external url it redirects to it perfectly. But once I login on that screen I am not able to see the Pega screen. I get below exception on screen:
Unable to execute OIDC flow : Caught exception while parsing the id token
And below error in logs:
Certificate does not exist, Keystore Entry is not either PrivateKeyEntry or TrustedCertificateEntry
Please suggest!
Thank You.
Pegasystems Inc.
PL
Hello,
It seems that Pega cannot verify signature of the Id Token received from your identity provider. The fist step would be to look at the configuration of your Identity Provider and make sure you it's configured to use asymmetric keys algorithm, such as RS256. You can verify it by looking at the token, as described in this article, in the "JWT Debugger" section. Paste your token into the JWT Debugger and look at the "Header" section in the "Decoded" column. There are two fields there: "kid" and "alg". Make sure "alg" says RS256. If it says HS256 instead, you need to change configuration of your Identity Provider.
If the alg is set to RS256 but the problem persists, make sure the key with id equal to "kid" is present in the keystore specified in the Authentication Service configuration in Pega Platform.
Cognizant
IN
Thank you for the inputs.
I have tested the token with JWT debugger . As per the debugger alg is set to RS256 and kid is verified and present in the keystore specified in the service. Signature is verified successfully.
But still the problem persists.
Regards,
Jill Haria
Pegasystems Inc.
PL
OK, I looked at the source code and I have a suspicion what may be the problem. If your keystore contains, in addition the the required key, also other unrelated entries, it may trigger this error. To verify, please try to modify your keystore to contain just the required key and nothing else. If this helps, you found the root cause.
Infosys McCamish Systems LLC
CA
Hello,
We have been able to successfully configure and enable SSO using Open ID connect. This post has been helpful in answering some of the debugging questions.
One of the follow-up requirements for us is to use the id token after log on for other security validations.
We realize that D_pzSSOAttributes data page contains decoded claim information from the token, but Is the id token retained on clipboard that can be used for other purposes such as secure integrations etc. If the id token is not available on clipboard, can we capture this during post authentication process.
Any direction around this would be helpful.
Inovar
IN
Dear,
Can you please let me know where we can find jwt token in JSON format on clipboard?, or how we can get it ?
Thanks,
Vodafone
IN
Does Pega handles token refresh ootb or it has to be customized?
(client.oauth2.OAuth2ClientImpl) Response details: access_token = ********* refresh_token = ********* id_token = token_type = bearer expires_in = 599
Macquarie
AU
Hi @Jarek , thanks for your post, its really helpful. I had the same question around the refresh token, does Pega handle it OOTB or any customisation is needed ?
I did not see any setting around that while configuring the Authentication service rule for OpenID Connect.
Also, I had a question around the token getting generated, can we configure something in pega to get a IMR/Opaque token from OpenID connect provider ? I guess, the token generated by default is a JWT token, could you please clarify ?
Murex
LB
Hello @Jarek
In our current application we are using SAML for sso we are trying to switch to OAuth OpenID, Everything is done and the user can now authenticate with Azure and login to the system. However w are trying to get the Access Token and the ID Token to use it for communication with other systems. In the logs we managed to see the Token ID in the OIDCClientHandler logger, but the Access Token it is shown as ***** when enabling the debug mode on client.oauth2.OAuth2ClientImpl. Nevertheless we couldn't find anything related to retrieve the Token from the Authentication service.
Do you have any input on this? like the activity that is calling the OICD handler so that we take the token?
Thanks,
Mohamad
Areteans
GB
Please check this article : https://www.howtopega.info/2021/12/open-id-connect-sso-authentication-with.html which explains on the same OIDC concept.
Please check if your OIDC Provider uses this one NimbusOIDCClientHandler. In that case, you can enable debug logger on the same. Please refer to the above article (during the end of the video you would notice the ID token). Hope that helps.
Thanks,
Pavan.
Stratosphere Technology Consulting LLC
US
@PavanKumarNaidu @Jarek Hi, Hope you will be able to help me with my query below. I have implemented OpenID connect authentication in my application and is working fine. After the authentication, system access the external REST API to retrieve a user Token unique for a user. This user Token is used to make all Connect-REST calls to the external system in that user session. To get the user token from external system, we are required to pass AccessToken retrieved during the Authentication. I am able to get the AccessToken from DB using the oAuth2Client API and pass the AccessToken to the external API to receive the customer token. The user Token received from the external system is valid only for 20mins. Each time we refresh the User Token, we have to retrieve and pass the AccessToken. If the AccessToken is expired, we have to refresh the AccessToken and pass the latest AccessToken. How do we refresh the AccessToken. Is there any API available to refresh the AccessToken. I am looking at making a Connect-REST call to Token API to retrieve the AccessToken. To do this i need to retrieve the RefreshToken sent from IDP. But I am not seeing any Pega API to retrieve the RefreshToken for the current user. I looked at the AccessToken Blob in DB, RefreshToken is encrypted. Unable to retrieve the decrypted value of RefreshToken. The scenario i mentioned, is this supported in Pega 8.6.3.
PT Bank Mandiri Persero Tbk
ID
Hi @SReddyR87,
it there any update for your issue ?, i have the same problem now and still looking the way. is there anyone can help ?.
Thank you,
Musa
Infosys Ltd
AU
@JarekWe are facing an issue with OIDC where in the authorisation URL itself is not creating. The log says constructing authorisation url and then, input text is empty and then there is an exception thrown of PRRuntimeException. It says Input text cannot be empty.
any ideas what could cause this? Thanks
shikhar