IBM Support

TroubleShoot: OpenID Connect, WebSphere traditional

Troubleshooting


Problem

Use this document to troubleshoot WebSphere OIDC.  This document contains troubleshooting information for OpenID Connect (OIDC) Trust Association Interceptor (TAI) problems in the WebSphere® Application Server traditional.  This document can help address common issues with this component before you call IBM support and save you time.

Resolving The Problem


Component: Topic: Overview
This topic contains error messages and common issues that require an OpenID Connect trace to determine the root cause of the problem. The instructions to obtain an OpenID Connect trace are in the 'Collecting data manually' section of the Collect data tab. If a trace string required for a specific problem is different than what is shown on the Collect data tab, the trace string is in the steps to diagnose the problem. In the rest of this document, 'OpenID Connect' is referred to as 'OIDC'.

Note:
This document uses the term Full Profile to refer to WebSphere Application Server v9.0 traditional, WebSphere Application Server v8.5 full profile, WebSphere Application Server v8.0 and earlier, WebSphere classic, traditional WebSphere, traditional WAS, and tWAS.

 

How do I set up the OIDC TAI

For more information on how to configure your server to protect a resource by using the OIDC TAI, see the following IBM Documentation articles:

 

How do I turn on OIDC trace?

Here are some basic steps for enabling SAML trace on WebSphere Application Server:
  1. Find the right trace specification:
    1. Navigate to MustGather: Web Single Sign-on problems with WebSphere Application Server
    2. Click SSO Trace specifications > WebSphere traditional
    3. Copy the string that is shown under OpenID Connect (OIDC), OpenID 2.0, and JWT authentication
  2. Enable OIDC trace:
    1. In the administrative console, click Troubleshooting > Logs and trace
    2. Click the server that you want to trace.
    3. Click Diagnostic trace > Change log detail levels
    4. In the box, enter the trace specification that you want to use
    5. Click OK
  3. Restart the server.
 
For more detailed instructions, see the Single Sign-on trace entry in the Items to collect table by clicking Collect data for WebSphere traditional > Step-by-step on the Collect data tab.

Where can I find the WebSphere OIDC TAI messages?

You can find the messages that the WebSphere OIDC TAI emits into the ffdc, trace.log, SystemOut.log, and SystemErr.log files in the IBM Documentation. The IBM Documentation has the explanation and action for each message. The messages are located by prefix:

 

How can I ensure that I have the latest version of the OIDC TAI

For more information on how to obtain the latest OpenID Connect runtime, see the technote Obtaining WebSphere OpenID Connect (OIDC) latest version, or click 'Get the Latest OIDC TAI' tab.
 

 

How can I see the version of the OIDC TAI from the JAR file

From the (was_home)/plugins directory, run the following command:

java -cp ./com.ibm.ws.security.oidc.client.jar com.ibm.ws.security.oidc.util.Version

com.ibm.ws.security.oidc.client.jar
1.4.0

If you are running a JAR file that was installed from an interim fix, a version number like 1.4.0 is displayed.  If you are running a JAR file that was installed from an initial installation or fix pack, a version number like 8.5.5 cf091605.01 is displayed.  This version number is the fix pack build identifier and why it looks odd.  In this example, 8.5.5 cf091605.01 means WebSphere version 8.5.5.9, built on the first day of the 5th week of 2016.
If the com.ibm.ws.security.oidc.util.Version class is not found in your com.ibm.ws.security.oidc.client.jar JAR file, you are running an out-dated version of the JAR file.  IBM recommends that you update it by installing the latest interim fix. For more information, see Obtaining WebSphere OpenID Connect (OIDC) latest version.

How can I find what version of the OIDC TAI I am running in a trace

To find the version of the OIDC TAI from a trace, search for getVersion:

[1/25/17 11:39:54:156 CST] 00000001 RelyingParty < getVersion returns [1.01] Exit


 

How can I tell if a trace is from server startup

IBM support requires that traces be gathered from server startup. If you want to make sure that your traces are gathered from server startup, check for the following string in your trace:
 
Search string
Full message
e-business WSVR0001I: Server {0} open for e-business


 

Where do I find the custom properties for the OIDC TAI

Technote

To see a complete list of the custom properties that are supported in the latest published version of the OIDC TAI, see the technote WebSphere OpenID Connect, Full Profile Custom Properties.

IBM Documentation
The custom properties for the OIDC TAI can be found in the IBM Documentation, see:

WebSphere OpenID Connect Relying Party custom properties for v8.5.5

If you want to see the custom properties for a version other than 8.5.5, use the Version drop-down on the IBM Docs page.


Utility method
Since the OIDC TAI is frequently serviced outside the normal WebSphere Application Server fix pack schedule, the OIDC custom properties documented in the IBM Documentation are sometimes out of date. To alleviate this problem, a Usage command was added to the OIDC TAI JAR file in version 1.01.

From the (was_home)/plugins directory, run the following command:
java -cp ./com.ibm.ws.security.oidc.client.jar com.ibm.ws.security.oidc.util.Usage

Component name: OpenID Connect Relying Party TAI
TAI class name: com.ibm.ws.security.oidc.client.RelyingParty
Version: 1.02

Custom properties:

[[[
REQUIRED PARAMETERS, OP SPECIFIC], [, ]], [[
PROPERTY NAME, DEFAULT], [, DEFINITION]], [[

provider_<id>.clientId, ], [, Specifies the id used to identify the OpenID Connect RP instance to the OpenID connect Provider server. It must be unique among all the RP clients registered to the provider.]], [[

provider_<id>.identifier, ], [, Specifies a unique name for each OpenID connect provider identified by the <id> in the provider_<id> prefix. This identifier is used to build the redirect URL that is registered with the OP.]], [[
...

This output from this command is not beautiful, but it is serviceable. The custom properties that are displayed from this command are valid for the version of the JAR file from which they were displayed. Properties displayed from a version 1.02 JAR file are not necessarily valid for version 1.01.


 

How can I tell if trust association is enabled in a trace

To find if trust association is enabled in an OIDC trace, search for the isTrustAssociationEnabled:

[1/25/17 11:36:29:375 CST] 00000001 TrustAssociat 3 isTrustAssociationEnabled returns [true]


 

How do I find all the configured TAIs in a trace

To find all the interceptors configured in an OIDC trace, search for the getInterceptors:

[1/25/17 11:36:29:375 CST] 00000001 TrustAssociat 3 getInterceptors returns [not null]
[1/25/17 11:36:29:375 CST] 00000001 TrustAssociat 3 TAI class name[0]: com.ibm.ws.security.web.TAMTrustAssociationInterceptorPlus
[1/25/17 11:36:29:375 CST] 00000001 TrustAssociat 3 TAI class name[1]: com.ibm.ws.security.spnego.TrustAssociationInterceptorImpl
[1/25/17 11:36:29:375 CST] 00000001 TrustAssociat 3 TAI class name[2]: com.ibm.ws.security.oidc.client.RelyingParty


 

How do I find my OIDC TAI configuration in a trace

If you have a trace from application server startup, you can find the raw OIDC TAI custom properties by searching for the following string in an OIDC trace:
 
loadInterceptor

If the OIDC TAI is configured and enabled, a trace block that looks like this is emitted; make sure you find the one that's loading com.ibm.ws.security.oidc.client.RelyingParty:
 
[1/25/17 11:39:54:016 CST] 00000001 TrustAssociat > loadInterceptor Entry
com.ibm.ws.security.oidc.client.RelyingParty
{provider_1.filter=request-url^=RP1|snoop, provider_1.clientId=oidcclient, provider_1.discoveryEndpointUrl=https://localhost:9444/oidc/endpoint/OP/.well-known/openid-configuration, provider_1.identifier=RP1, provider_1.clientSecret=password, provider_2.authorizeEndpointUrl=https://localhost:8020/oidc/endpoint/OP/authorize, provider_2.clientId=client01, provider_2.clientSecret=secret_01, provider_2.identifier=RP2, provider_2.filter=request-url^=RP2|mylogin, provider_2.introspectEndpointUrl=https://localhost:8020/oidc/endpoint/OP/introspect, provider_2.scope=BAD profile, provider_2.tokenEndpointUrl=https://localhost:8020/oidc/endpoint/OP/token, useStateCookies=false}

If you want to see the resolved properties, search for the following string:
 
com.ibm.ws.security.oidc.client.OidcTAIConfig

And find:
 
[8/5/20 19:02:36:280 EDT] 00000001 RelyingParty 3 com.ibm.ws.security.oidc.client.OidcTAIConfigultraLogout=[false], _anyRpConfigSupportsRevoke=[false], _anyRpConfigSupportsRevokeOnEviction=[false], _clientCredFlowConfig=[null], Partner: 1com.ibm.ws.security.oidc.client.RelyingPartyConfig(index=[0], providerId=[RP1], initializationComplete=[true], protectedContextPaths=[not null], excludedPathFilter=[not null], clientId=[oidcclient], clientSecret=[not null], clientBasicAuth=[Basic b2lkY2NsaWVudDpwYXNzd29yZA==], serverUrl=[null], signinCB=[null], signinCBEnc=[null], introspectEndpoint=[https://localhost:9444/oidc/endpoint/OP/introspect], userinfoEndpoint=[https://localhost:9444/oidc/endpoint/OP/userinfo], revokeEndpoint=[null], revokeAccessToken=[false], revokeTokensWhenEvicted=[false], authorizeEndpoint=[https://localhost:9444/oidc/endpoint/OP/authorize], authorizeEndpointHasParameter=[false], tokenEndpoint=[localhost:9444/oidc/endpoint/OP/token], loginErrorUrl=[null], loginErrorUrlHasParameter=[false], sendParamsTologinErrorUrl=[false], cbServletContext=[/oidcclient], endpointsInitialized=[false], RPCookieName=[OIDCSESSIONID_RP1], rpScope=[openid profile], rpCallbackHostAndPort=[null], responseType=[code], responseTypeEnum=[CODE], authRequestIsImplicit=[false], allowImplicitTokenAuthentication=[false], accessTokenRequired=[true], urlEncodeEnabled=[false], createHttpSession=[false], isRefreshEnabled=[true], postParameterCookieSize=[4093], sslOnly=[true], httpOnly=[true], trustStore=[null], verifyingAlias=[null], stateCookieName=[OIDCSTATE_RP1], urlCookieName=[OIDCREQURL_RP1], cbUri=[null], usePostForIntrospection=[true], tokenEndpointAuthMethodIsPost=[true], defaultRealmName=[null], useRealm=[null], verifyIssuerInIat=[false], overrideIdTokenExp=[false], sessionTimeoutMillis=[0], encodeNewline=[true], useDefaultIdentifierFirst=[false], includePortInDefaultRedirectUrl=[true], audiences=[not null], tokenReuse=[true], setLtpaCookie=[true], useJwtFromRequest=[no], useJwt=[NO], headerName=[null], allAudience=[false], acrValues=[null], nonceEnabled=[false], contentSecurityPolicy=[null], contentSecurityPolicyHasNonce=[false], discoveryEndpoint=[localhost:9444/oidc/endpoint/OP/.well-known/openid-configuration], endSessionEndpoint=[https://localhost:9444/oidc/endpoint/OP/end_session], useDiscovery=[true], grantType=[null], clientCredentialsFlow=[false], useJavaScript=[true], userinfoEndpointEnabled=[true], mapIdentityToRegistry=[false], introspectClientId=[null], introspectClientSecret=[null])


 

How can I tell if the OIDC TAI is processing a request or not

To see whether the OIDC TAI is processing a request, search for an entry that looks like the following in an ODIC trace:

RelyingParty > isTargetInterceptor(req[not null]) Entry

Then, a trace block that looks something like this:
 
[7/13/20 10:57:59:245 CST] 0000008d TAIWrapper > isTargetInterceptor() Entry
[7/13/20 10:57:59:245 EDT] 000000b0 RelyingParty  >  OIDC: isTargetInterceptor(https://localhost:9443/snoop) Entry
[7/13/20 10:57:59:245 CST] 0000008d OidcTAIConfig > getRelyingPartyConfig Entry
[7/13/20 10:57:59:245 CST] 0000008d OidcTAIConfig > isAcceptedByRegx Entry
[7/13/20 10:57:59:245 CST] 0000008d OidcTAIConfig 3 Evaluating for request uri: [/snoop]
[7/13/20 10:57:59:245 CST] 0000008d OidcTAIConfig 3 The url [/snoop] is being intercepted by OIDC RelyingParty
[7/13/20 10:57:59:245 CST] 0000008d OidcTAIConfig < isAcceptedByRegx returns [true] Exit
[7/13/20 10:57:59:245 CST] 0000008d RelyingParty 3 The URL: [
https://localhost:9443/snoop] accepted by OIDC RelyingParty
[7/13/20 10:57:59:245 CST] 0000008d RelyingParty < ==> OIDC: isTargetInterceptor returns [true] Exit
[7/13/20 10:57:59:245 CST] 0000008d TAIWrapper < isTargetInterceptor(): Jazz Security Architecture OIDC TrustAssociationInterceptor returning true Exit

In this case, the TAI config was:
 
[1/25/17 11:43:17:813 CST] 00000001 TrustAssociat 3 Trust Properties =
{clientId=s_app_a, authorizeEndpointUrl=https://localhost:8020/oidc/endpoint/OP/authorize, introspectEndpointUrl=https://localhost:8020/oidc/endpoint/OP/introspect, callbackServletContext=/oidcclient, interceptedPathFilter=/oidctestapp.*,/snoop, useStateCookies=false, clientSecret=app_a_secret, tokenEndpointUrl=https://localhost:8020/oidc/endpoint/OP/token, scope=openid general}


 

How can I tell if my application is protected

An application must have web constraints in order for it to be protected by any TAI, or even a form login.

To find out whether your application URI has web constraints, search the trace for either your URI or getConstraints. Example:

[1/10/20 11:29:18:001 EST] 0000009a WebConstraint > getConstraints: Entry
                    /myLogin
                    GET
[1/10/20 11:29:18:001 EST] 0000009a WebConstraint 3 %webConstraintsTable.length = 0
[1/10/20 11:29:18:001 EST] 0000009a WebResourceCo > isStandardHTTPMethod Entry
                    GET
[1/10/20 11:29:18:001 EST] 0000009a WebResourceCo < isStandardHTTPMethod Exit
                    true
[1/10/20 11:29:18:001 EST] 0000009a WebConstraint < getConstraints Exit
[1/10/20 11:29:18:001 EST] 0000009a WebCollaborat 3 No WebConstraints for URI = /myLogin, method = GET

If your application does not have web constraints, see the security-constraints element in Configuring Security Using Deployment Descriptors in the Oracle Java documentation.
image-20230113083757-9 In addition to web constraints, your application must also require at least one role for core security to send the request to the set of TAIs.  Search the trace for doTAI.  This is an example of an application that has a security-constraint but no security-role:
[1/19/24 10:30:05:470 GMT] 00000152 WebResourceCo 3   Checking URL: /app1/*
[1/19/24 10:30:05:470 GMT] 00000152 WebResourceCo <  no match Exit
[1/19/24 10:30:05:470 GMT] 00000152 WebConstraint <  getConstraints Exit
[1/19/24 10:30:05:470 GMT] 00000152 WebCollaborat 3   securityConstraints=null
[1/19/24 10:30:05:470 GMT] 00000152 WebCollaborat >  invokeTAI Entry
[1/19/24 10:30:05:470 GMT] 00000152 WebCollaborat 3    everyoneAllowed: false reqRole: No required role(s) persistCred: true performTAIForUnprotectedURI: false isFileTransferApp: false rsaToken in the request header: null
[1/19/24 10:30:05:470 GMT] 00000152 WebCollaborat <  invokeTAIReturning doTAI:false Exit
If your application does not have a role, see the security-role element in Configuring Security Using Deployment Descriptors in the Oracle Java documentation.

Where is the entry point for the OIDC TAI

The entry point for the OIDC TAI is negotiateValidateandEstablishTrust. Search for an Entry for this method on the RelyingParty class:
 
[1/25/17 11:40:21:797 CST] 0000008c TAIWrapper > negotiateAndValidateEstablishedTrust() Entry
[1/25/17 11:40:21:797 CST] 0000008c RelyingParty > negotiateValidateandEstablishTrust(req[not null,res[not null]) Entry
[1/25/17 11:40:21:797 CST] 0000008c OidcTAIConfig > getRelyingPartyConfig Entry
[1/25/17 11:40:21:797 CST] 0000008c OidcTAIConfig > isAcceptedByRegx Entry
[1/25/17 11:40:21:797 CST] 0000008c OidcTAIConfig 3 Evaluating for request uri: [/snoop]
[1/25/17 11:40:21:797 CST] 0000008c OidcTAIConfig 3 The url [/snoop] is being intercepted by OIDC RelyingParty
[1/25/17 11:40:21:797 CST] 0000008c OidcTAIConfig < isAcceptedByRegx returns [true] Exit
[1/25/17 11:40:21:797 CST] 0000008c RelyingParty 3 RelyingParty processing the request for: [/snoop]


 

What should I look for to see if this is the initial request from the browser

[1/25/17 11:40:21:797 CST] 0000008c RelyingParty > initiateLogin(req[not null,res[not null], rpConfig[not null]) Entry
[1/25/17 11:40:21:797 CST] 0000008c RelyingParty 3 ==> OIDC: INITIATING LOGIN


 

What should I look for to see if this is the redirect from the OP

[1/25/17 11:40:23:938 CST] 0000008c RelyingParty > handleSigninCallback(req[not null,res[not null], rpConfig[not null]) Entry
[1/25/17 11:40:23:938 CST] 0000008c RelyingParty 3 ==> OIDC: PROCESS LOGIN RESPONSE FROM OP


 

How can I see the POST/GET sent to the OP to obtain the JWT

To see the request that is sent to the OP to obtain the JWT, search the trace for Request to URL

[1/25/17 11:40:23:938 CST] 0000008c RelyingPartyU 3 POST Request to URL: https://localhost:8020/oidc/endpoint/OP/token
[1/25/17 11:40:23:938 CST] 0000008c RelyingPartyU 3 Content: grant_type=authorization_code&code=1mkLbwqnhWXLGmMMEsptPQBAwdq3uJ&redirect_uri=https%3A%2F%2Flocalhost%3A9443%2Foidcclient%2Fprovider1&client_id=app_a&


 

How can I see the response from the OP

To find the response from the OP, search the trace for getData:

[1/25/17 11:40:24:156 CST] 0000008c RelyingPartyU < getData returns [{"access_token":"xgPKFmHWrViGDaYtamd84BzJjruzZgnpHlTUrShO","token_type":"Bearer","expires_in":14,"scope":"openid general","refresh_token":"ogePSzIQ4OmEJUxvwkRHtl4So2lLA5motrBndc7VYp8Dkf1whJ","id_token":"eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL2xvY2FsaG9zdDo4MDIwL29pZGMvZW5kcG9pbnQvT1AiLCJpYXQiOjE0ODUzNjYwMjQsImdyb3VwSWRzIjpbImdyb3VwMSIsImdyb3VwMiJdLCJzdWIiOiJ0ZXN0dXNlciIsImV4cCI6MTQ4NTM2NjA1NCwiYXVkIjoiYXBwX2EiLCJyZWFsbU5hbWUiOiJCYXNpY1JlYWxtIiwidW5pcXVlU2VjdXJpdHlOYW1lIjoidGVzdHVzZXIiLCJhdF9oYXNoIjoiWGMtWmdEOENDWDNndVdkMS1WTGR6QSJ9.xpNN7qGWEellulDtuzdr3Ft7xQo7Z2iIu-GvpLwHrQs"}] Exit


 

Can I see the JWT in readable format

The OIDC runtime attempts to emit the ID token and access token in readable format. You can search for "id token[" or "access token[":
 
[1/25/17 11:40:24:188 CST] 0000008c SessionData 3 id token[header[{"alg":"HS256"}], claims[{"iss":"https://localhost:8020/oidc/endpoint/OP","iat":1485366024,"groupIds":["group1","group2"],"sub":"testuser","exp":1485366054,"aud":"app_a","realmName":"BasicRealm","uniqueSecurityName":"testuser","at_hash":"Xc-ZgD8CCX3guWd1-VLdzA"}]]
[1/25/17 11:40:24:188 CST] 0000008c SessionData 3 access token[NotJWTFormat]


 

Is there an easy way to follow the overall flow in an OIDC trace

If your editor has the ability to list all instances of a search string, you can search for "==> OIDC:" to see a high-level flow of the OIDC TAI processing in a trace. Example:
 
Find all "==> OIDC:", Match case
165 54:[8/5/20 19:45:36:318 EDT] 00000001 RelyingPartyU 3 ==> OIDC: BEGINNING TO CALL OUT TO DISCOVERY ENDPOINT ON OP
180 54:[8/5/20 19:45:37:584 EDT] 00000001 RelyingPartyU 3 ==> OIDC: RETURNED FROM DISCOVERY ENDPOINT
5859 53:[8/5/20 19:47:18:069 EDT] 00000097 RelyingParty < ==> OIDC: isTargetInterceptor returns [true] Exit
5886 54:[8/5/20 19:47:18:069 EDT] 00000097 RelyingParty 3 ==> OIDC: Inbound request [https://localhost:9443/snoop]
5919 54:[8/5/20 19:47:18:069 EDT] 00000097 RelyingParty 3 ==> OIDC: INITIATING LOGIN
6060 54:[8/5/20 19:47:18:178 EDT] 00000097 RelyingParty 3 ==> OIDC: Sending redirect to [https://localhost:9444/oidc/endpoint/OP/authorize] via javascript
6063 54:[8/5/20 19:47:18:194 EDT] 00000097 RelyingParty 3 ==> OIDC: PROCESS COMPLETE
6578 53:[8/5/20 19:47:24:782 EDT] 00000097 RelyingParty < ==> OIDC: isTargetInterceptor returns [true] Exit
6605 54:[8/5/20 19:47:24:798 EDT] 00000097 RelyingParty 3 ==> OIDC: Inbound request [https://localhost:9443/oidcclient/client1?code=mw73jEP6LoWqvNr9sxRidPY97lVjcq&state=-256255792_1596671238069]
6613 54:[8/5/20 19:47:24:798 EDT] 00000097 RelyingParty 3 ==> OIDC: PROCESS LOGIN RESPONSE FROM OP
6654 54:[8/5/20 19:47:24:798 EDT] 00000097 RelyingParty 3 ==> OIDC: BEGINNING CALL OUT TO TOKEN ENDPOINT ON OP
6676 54:[8/5/20 19:47:24:892 EDT] 00000097 RelyingParty 3 ==> OIDC: RETURNED FROM CALL OUT TO TOKEN ENDPOINT
6761 54:[8/5/20 19:47:24:892 EDT] 00000097 RelyingPartyU 3 ==> OIDC: BEGINNING TO CALL OUT TO USERINFO ENDPOINT ON OP
6779 54:[8/5/20 19:47:24:923 EDT] 00000097 RelyingPartyU 3 ==> OIDC: RETURNED FROM USERINFO ENDPOINT
6981 54:[8/5/20 19:47:25:079 EDT] 00000097 RelyingParty 3 ==> OIDC: Sending redirect to [https://localhost:9443/snoop]
6984 54:[8/5/20 19:47:25:079 EDT] 00000097 RelyingParty 3 ==> OIDC: PROCESS COMPLETE
7244 53:[8/5/20 19:47:25:095 EDT] 00000097 RelyingParty < ==> OIDC: isTargetInterceptor returns [true] Exit
7271 54:[8/5/20 19:47:25:095 EDT] 00000097 RelyingParty 3 ==> OIDC: Inbound request [https://localhost:9443/snoop]
7292 54:[8/5/20 19:47:25:110 EDT] 00000097 RelyingParty 3 ==> OIDC: AUTENTICATING USING SESSION COOKIE.
7405 54:[8/5/20 19:47:25:110 EDT] 00000097 RelyingParty 3 ==> OIDC: PROCESS COMPLETE Total found: 20
 
If your editor can't list all, then you can do repetitive searches on "==> OIDC:" to follow the flow through the trace.
 

Does the OIDC TAI require session affinity

In most cases, the OIDC TAI requires session affinity in a cluster environment.   Alternatively, you can use a load balancer that is using an algorithm that sends rapid requests from the same client to the same cluster member.  If you are using IHS as your front end, ensure that you have the OIDC TAI property, provider_<id>.createSession set to true. The default is false. This property directs the OIDC runtime to create the JSESSIONID cookie that IHS requires to maintain session affinity.
 
Although the TAI keeps state and some session information in cookies, the initial request and the entire authentication flow must be to the same WebSphere JVM.  Here is an overview of the OIDC login flow from the browser perspective:
Request
Number
Request Response Cookies
1 Request to the secure application URL  Set redirect to the OP login URL Set state cookie
2 Request to the OP login URL
Set redirect to the WAS OIDC client URL
(/oidcclient by default)
3
Request to the WAS OIDC client URL
(/oidcclient by default)
Set redirect to the application URL Remove state cookie
Set session cookie
4 Request to the application URL
Set LTPA cookie
(if configured)
In this sequence, requests 3 and 4 must be to the same JVM. Session affinity is required with almost all load balancer algorithms.
 
  • When state cookies are enabled, the OIDC TAI uses a local cache with cookie backup for state data. This phase does not require affinity.
  • The phase when the TAI redirects to the protected application requires session affinity:
    • Unless a custom JNDI cache is configured, the TAI's session data cache is not shared across cluster members.
    • When the TAI's session data cache is shared across cluster members, you would think that the session affinity issue is covered.
    • However, the problem is that the OIDC TAI authenticated the user on step 3, but then the request is sent back into the TAI on step 4 by core security requesting authentication again. This step requires the session data in the cache.
    • The time elapsed between steps 3 and 4 is not long enough for the cache to replicate, therefore, requests 3 and 4 must be handled by the same JVM. The result of this process means that the entire login process must occur on a single JVM.

 

How can I enable OpenId Connect across multiple clusters within the cell

The protected resources must reside on the same application server on which the OIDC RP application, WebSphereOIDCRP.ear, is installed and accepting requests.
 
  • To meet this requirement in a multiple cluster environment, the OIDC TAI requires session affinity across multiple clusters.
  • You must use Intelligent Management for Web Server plug-ins to set session affinity across multiple clusters.
  • The following steps are required to enable OpenId Connect across multiple clusters within the cell:
    For more information, see Configuring Intelligent Management for web servers for information on how to configure Intelligent Management.
    1. The WebSphereOIDCRP application must be installed with a different application name and context root on each cluster.
      • The web server plug-in requires distinct context roots in order to be able to maintain affinity with back-end servers in each cluster.
    2. Set the following OIDC TAI properties:
      callbackServletContext=(WebSphereOIDCRP context)
      provider_<id>.createSession=true
    3. Map the OIDC RP application to the clusters where you intend to use it.
    4. Configure Intelligent Management.
 

Can you make the OIDC TAI not write an LTPA cookie

The OIDC TAI itself does not write LTPA cookies. However, when the OIDC TAI passes information to core security to create the Subject, it can say to create LTPA cookie or not. There is an OIDC TAI configuration option for setting the LTPA cookie. The property to use is provider_(id).setLtpaCookie.
 
The OIDC TAI can operate in two modes: an OpenID Connect Relying Party and JWT authentication. In OIDC RP mode, the setLtpaCookie property defaults to true. In JWT authentication mode, setLtpaCookie defaults to false.
 

How can I use OIDC to protect the WebSphere admin console

You can use the OIDC TAI to protect the WebSphere administrative console. See Configuring WebSphere admin console to login with OIDC.  

How does the OIDC TAI use DynaCache

How can I see that DynaCache is enabled?
When the DynaCache feature is enabled on your server, the OIDC TAI uses DynaCache to manage the session and state caches regardless of the TAI's clusterCaching setting. When you set clusterCaching=false, a DistributedObjectCache named OIDCRPDistributedCacheMap is still created, but KEY_ENABLE_CACHE_REPLICATION is set to false instead of true. This scheme means that each cluster member has its own cache.

The DynaCache feature is enabled on all application servers by default and it can be used in single server, cell, and cluster environments. Unless you know that you went through the steps to disable DynaCache, assume that it is enabled. If you have an OIDC TAI trace, you can check for the following entry to make sure that DynaCache is enabled:
[3/1/17 13:37:29:774 CST] 0000008c DynaCacheUtil 3 isDynamicCacheEnabled returns [true].

If the DynaCache feature is enabled on your server, you can customize the caching behavior by creating your own JNDI cache definition. If you create your own JNDI cache for use by the OIDC TAI, the property to pass it to the TAI is -jndiCacheName. See Using object cache instances for additional information about setting up a JNDI cache.

If the DynaCache feature is not enabled on your application server, local in-memory state and session caches are used. There are some local cache customization settings for the TAI:
 
sessionCacheSize
sessionCacheCleanupFrequency
maxStateCacheSize


 

CWTAI2028W: The OpenID Connect test fix will stop taking requests on [2/2/2017 12:00 PM]

This message means several things:

  • You have a test fix for an APAR in the OpenID Connect component in WebSphere Application Server installed.
  • The test fix is classified as 'tightly controlled' by IBM L3 WebSphere security support.
  • Some, but not many, OIDC test fixes are classified as tightly controlled by IBM WebSphere security support.
  • When the date and time in the message is in the past:
    • The RelyingParty.isTargetInterceptor method always returns false. Resources are not protected by the OIDC TAI.
    • The OIDC test fix is no longer taking requests message is emitted each time RelyingParty.isTargetInterceptor is invoked.
  • If a test fix is tightly controlled, the OIDC test fix will stop taking requests message is emitted at the Warning level when the OIDC interceptor is initialized by the Trust Manager.
  • The "fix will stop taking requests" message is not customizable.

If you received an OIDC test fix that is tightly controlled, test the fix, then uninstall it as soon as you can to return to your original level.


 

The TAI is not intercepting any requests

The OIDC TAI is configured to intercept my requests, but the requests are going directly to my application and not redirected to the OP

In this example, we are going to debug the following issue:
 
  • The URI that we want to redirect to the OP for authentication is /myLogin.
  • When the request is received by the application server, the request is sent directly to /myLogin; an authentication request is not sent to the OP.

Debug procedure:
  1. Make sure that application security is enabled.
    • An entry like this appears in your trace when application security is not enabled and requests are not sent to any TAI for processing:
      [2/22/23 23:48:17:433 EST] 00000112 EJSWebCollabo 3   preInvoke
                                       Skip authorization for non-system apps when app security is disabled.
    • Take action:
      Action: Enable application security
      1. In the administrative console, navigate to Security > Global Security
      2. Under Application security, check Enable application security
      3. Click OK
      4. Click Save
      5. Restart the server
  2. Make sure that trust association is enabled:
    [1/10/20 13:25:05:163 EST] 00000001 TrustAssociat 3 isTrustAssociationEnabled returns [true]
    • Take action:
      Action: Enable trust association
      1. In the administrative console, navigate to Security > Global Security > Web and SIP security > Trust association
      2. If Enable trust association is not selected, select it, then click Apply
      3. Click Save
      4. Restart the server
  3. Make sure the RelyingParty class is a configured TAI:
    [1/10/20 13:24:54:345 EDT] 00000001 TrustAssociat 3 getInterceptors returns [not null]
    [1/10/20 13:24:54:345 EDT] 00000001 TrustAssociat 3 TAI class name[0]: com.ibm.ws.security.web.TAMTrustAssociationInterceptorPlus
    [1/10/20 13:24:54:345 EDT] 00000001 TrustAssociat 3 TAI class name[1]: com.ibm.ws.security.spnego.TrustAssociationInterceptorImpl
    [1/10/20 13:24:54:345 EDT] 00000001 TrustAssociat 3 TAI class name[2]: com.ibm.ws.security.oidc.client.RelyingParty
    • Take action:
      Action: Verify the configured interceptors
      1. In the administrative console, navigate to Security > Global Security > Web and SIP security > Trust association > Interceptors
      2. Verify that com.ibm.ws.security.oidc.client.RelyingParty is in the list and that it is spelled correctly.
  4. Make sure the RelyingParty class and configuration were loaded successfully:
    [1/10/20 13:24:54:345 EDT] 00000001 TrustAssociat A SECJ0121I: Trust Association Init class com.ibm.ws.security.oidc.client.RelyingParty loaded successfully
    ...
    [1/10/20 13:24:54:345 EDT] 00000001 RelyingParty < initialize Exit
    [1/10/20 13:24:54:345 EDT] 00000001 RelyingParty < getVersion returns [1.3.0] Exit
    [1/10/20 13:24:54:345 EDT] 00000001 TrustAssociat A SECJ0122I: Trust Association Init Interceptor signature: 1.3.0
    [1/10/20 13:24:54:345 EDT] 00000001 TrustAssociat < loadInterceptor (success) Exit
     
    • Take action:

      Action: Fix the configuration error.

      1. Search the trace for the entries like this:
        [1/10/20 13:24:54:345 EDT] 00000001 TrustAssociat < loadInterceptor (exception) Exit
      2. Page back in the trace to find the configuration error.
  5. Is the RelyingParty.isTargetInterceptor method invoked for the URI?
    1. Search the trace for isTargetInterceptor.
    2. Check a few lines down to find the URI being evaluated.  Example:
      [1/10/20 13:24:54:355 EST] 00000094 OidcTAIConfig 3 Evaluating for request uri: [/myLogin]
      •  If you do not find an isTargetInterceptor entry for your URI, make sure that your URI is protected. If the URI has no web constraints, the request does not go through any TAI:
        [1/10/20 11:29:18:001 EST] 0000009a WebConstraint > getConstraints: Entry
                            /myLogin
                            GET
        [1/10/20 11:29:18:001 EST] 0000009a WebConstraint 3 webConstraintsTable.length = 0
        [1/10/20 11:29:18:001 EST] 0000009a WebResourceCo > isStandardHTTPMethod Entry
                            GET
        [1/10/20 11:29:18:001 EST] 0000009a WebResourceCo < isStandardHTTPMethod Exit
                            true
        [1/10/20 11:29:18:001 EST] 0000009a WebConstraint < getConstraints Exit
        [1/10/20 11:29:18:001 EST] 0000009a WebCollaborat 3 No WebConstraints for URI = /myLogin, method = GET

        Action: If your URI is not protected, protect it.  See the security-constraints element in Configuring Security Using Deployment Descriptors in the Oracle Java documentation.
      •  If you find web constraints for your URI, make sure that it has role requirements.  If the URI has no role requirements, the request does not go through any TAI:
        [1/19/24 10:30:05:470 GMT] 00000152 WebResourceCo 3   Checking URL: /app1/*
        [1/19/24 10:30:05:470 GMT] 00000152 WebResourceCo <  no match Exit
        [1/19/24 10:30:05:470 GMT] 00000152 WebConstraint <  getConstraints Exit
        [1/19/24 10:30:05:470 GMT] 00000152 WebCollaborat 3   securityConstraints=null
        [1/19/24 10:30:05:470 GMT] 00000152 WebCollaborat >  invokeTAI Entry
        [1/19/24 10:30:05:470 GMT] 00000152 WebCollaborat 3    everyoneAllowed: false reqRole: No required role(s) persistCred: true performTAIForUnprotectedURI: false isFileTransferApp: false rsaToken in the request header: null
        [1/19/24 10:30:05:470 GMT] 00000152 WebCollaborat <  invokeTAIReturning doTAI:false Exit

        Action: If your URI does not have at least one role requirement, add one.  See the security-role element in Configuring Security Using Deployment Descriptors in the Oracle Java documentation.
      •  If you find an entry for your URI, check a little farther down in the trace to see whether the TAI is intercepting the request:
        [1/10/20 13:24:54:357 EST] 00000094 RelyingParty < isTargetInterceptor returns [false] Exit
        Action: Assuming that isTargetInterceptor returns false, adjust your OIDC TAI filter settings to make sure that your URI is intercepted.
        • If your URL is going through the TAI, but you are being sent to your endpoint and not the OP, then isTargetInterceptor must be returning false.
        • If isTargetInterceptor returns true, and you are not redirected to the OP, then some error occurred in the TAI, and you would be getting a 403.
      • If isTargetInterceptor returns false, but your filter is set correctly, the problem might be that you have only provider_<id>.grantType configuration entries.

        Here is an example of an OIDC TAI trace where there are only grantType configuration entries. The TAI does not attempt to process any filters.  The getRelyingPartyConfig method is invoked and it returns null:

        [11/29/22 22:04:09:190 UTC] 000000d9 TAIWrapper > isTargetInterceptor() Entry
        [11/29/22 22:04:09:190 UTC] 000000d9 RelyingParty > OIDC: isTargetInterceptor(https://localhost:9444/snoop) Entry
        [11/29/22 22:04:09:190 UTC] 000000d9 OidcTAIConfig > getRelyingPartyConfig(HttpServletRequest) Entry
        [11/29/22 22:04:09:190 UTC] 000000d9 OidcTAIConfig < getRelyingPartyConfig returns [null] Exit
        [11/29/22 22:04:09:190 UTC] 000000d9 RelyingParty 3 The URL: [https://localhost:9444/snoop] ignored by OIDC RelyingParty
        [11/29/22 22:04:09:190 UTC] 000000d9 RelyingParty < OIDC: isTargetInterceptor returns [false] Exit


        When the grantType parameter is specified on a provider entry, that entry is not used for OIDC or JWT authentication.
         
        • Action: Check your configuration to make sure that configuration entry that contains the filter that you intend to match does not contain a grantType property:

          provider_<id>.grantType=client_credentials

     

    CWTAI2007E: The OpenID Connect relying party (RP) encountered a failure during the login. The exception is [StateId parameter is null]. Check the logs for details that lead to this exception.

    The "StateId parameter is null" error occurs when an endpoint that has the same context root of WebSphereOIDCRP.ear is invoked with an HTTP request that does not contain a StateId parameter. The default context root for OIDC RP callback ear, WebSphereOIDCRP.ear is /oidcclient. The OIDC RP callback in intended to be called directly by an OP and those requests must contain a StateId parameter. This error ordinarily occurs when the endpoint was invoked by a browser instead of an OP. Alternatively, the OP might be failing to send the StateId parameter.
     

    CWTAI2009I: The OpenID Connect relying party (RP) did not find an entry for session cookie OIDCSESSION_12345678 in the Session cache

    The OIDC TAI maintains session data for a client in DynaCache or a local cache. The session data entries in the cache hold the JWTs and other information required to maintain the session. The index into the session data cache is held in a browser cookie. It is possible that the browser cookie can still exist, but there is no session data entry in the cache to go with it. You get this error only if you are running in a cluster environment and clusterCaching=true (the default). Common causes for this error are:
     
    • You do not have session affinity and not enough time elapsed for DynaCache to replicate across the cluster.
    • The volume of active users is causing OIDC sessions to be evicted from the cache.

    Remediation:

    Do one or more of the following:
     
    • Enable session affinity.
    • If you cannot enable session affinity and your load balancer is using the round-robin algorithm, consider changing your load balancer algorithm to something that is more likely to hit the same cluster member for requests from the same client in rapid succession.
    • If the DynaCache feature is enabled on your server, consider customizing the caching behavior by creating your own JNDI cache definition. For more information, see the entry, How does the OIDC TAI use DynaCache?, for information about how the OIDC TAI uses DynaCache.
    • Remove the OIDC class, com.ibm.ws.security.oidc.client.RelyingParty, from the base security custom property com.ibm.websphere.security.InvokeTAIbeforeSSO so that the session is maintained by the LTPA cookie instead of the OIDC cookie. Consider the following when you make this decision:
      • What happens when you add the class to InvokeTAIbeforeSSO?

        If you add the OpenID Connect Relying Party TAI (OIDC RP TAI) to the InvokeTAIbeforeSSO list, the TAI is invoked each time a request is made to the protected resource.
        1. The first time a user logs in, they are redirected to the OpenID Connect provider (OP) and a set of JSON Web Tokens (JWT) is sent to the application server for the user.
        2. On the first request that the application server receives after the access token from the JWT expires, a refresh cycle begins. Depending on OIDC and OP settings, one of the following occurs:
          • The user is redirected to the OP
          • The refresh token from the JWT is sent to the OP to get a new access token.
      • What happens when you do not add the class to InvokeTAIbeforeSSO?

        If you do not add the OpenID Connect Relying Party TAI class to the InvokeTAIbeforeSSO list, the server checks for LTPA cookies on the request before the TAI is in invoked.
        1. The first time a user logs in, they are redirected to the OpenID Connect provider (OP) and a set of JSON Web Tokens (JWT) is sent to the application server for the user.
        2. On the first request that the application server receives after the LTPA expires, the user is redirected to the TAI.
          • If the access token is also expired, a refresh cycle begins (see the previous explanation).
          • If the access token is not expired, a new LTPA token is created.
      •      Avoid trouble: If the LTPA expiration is longer than the access token, it is possible to end up with expired JWTs on a user's WebSphere Subject. If your down-stream applications use the JWTs stored on the WebSphere Subject, this behavior must be taken into consideration.


             Avoid trouble: If LTPA keys are shared with other WebSphere cells in your environment, then the LTPA cookies already generated by those cells are valid for access to the protected resources. Until the user is redirected to the OP after the LTPA expires, the Subject contains only what was placed on it by the other cell.


     

    Does my application have access to the JWTs that were received from the OP

    The OpenID Connect TAI puts the ID token, access token and refresh token in a Hashtable in the private credentials on WebSphere runAs Subject. The OIDC TAI provides an application programming interface called com.ibm.websphere.security.oidc.util.OidcClientHelper. You can use this API to perform many functions related to the TAI.  The OidcClientHelper API is available starting in WebSphere fix packs 8.5.5.16 and 9.0.5.0, and OIDC TAI v1.2.0.
     

    You can retrieve the tokens from the runAs Subject in one of two ways:

    • Use the com.ibm.websphere.security.oidc.util.OidcClientHelper API to retrieve the tokens from the runAs Subject for you. 
      import com.ibm.websphere.security.oidc.util.OidcClientHelper;
      
      private static String getIdToken() throws java.lang.Exception {
        try {
          return OidcClientHelper.getIdTokenFromSubject();
        } catch (java.lang.Exception e) {
          return null;
        }
        return null;
      }
    • Retrieve the tokens from the runAs Subject yourself:
      This example uses the WSSUtilFactory.getRunAsSubject() convenience method to get the WebSphere runAs Subject. This method is available starting in fix packs 8.0.0.13, 8.5.5.10 and 9.0.
      import java.util.Hashtable;
      import java.util.Iterator;
      import javax.security.auth.Subject;
      import com.ibm.websphere.wssecurity.wssapi.WSSUtilFactory;
      
      private static final String ID_TOKEN = "id_token";
      private static final String ACCESS_TOKEN = "access_token";
      private static final String REFRESH_TOKEN = "refresh_token";
      private static final String USER_INFO = "user_info";
      private static final String TOKEN_TYPE = "token_type";
      private static final String SCOPE = "scope";
      
      private static String getIdToken() {
        String idToken = null;  
        WSSUtilFactory wssuf = WSSUtilFactory.getInstance();
        Subject subject = wssuf.getRunAsSubject();  
      
        if (subject != null) {
          Iterator authIterator = subject.getPrivateCredentials(Hashtable.class).iterator();
          if ( authIterator.hasNext() ) {
            Hashtable creds = (Hashtable) authIterator.next();
            if ( creds != null ) {
              idToken = (String) creds.get(ID_TOKEN);
            }
          }
        }
        return idToken;
      }


     

    CWTAI2007E: The OpenID Connect relying party (RP) encountered a failure during the login. The exception is [com.ibm.ws.security.oidc.client.RelyingPartyException: CWTAI2031E: The OpenID Connect state cookie [OIDCSTATE_sp1] does not exist on the HTTP request.]

    You see this error message when the OIDC TAI is unable to perform a complete login. However, depending on of the environment, this error message might be expected and can be ignored. Further information and direction can be obtained from the Explanation and User Action for the CWTAI2031E message:

    Explanation:
    When you get this message, the OIDC TAI was unable find its state cookie on the HTTP request. When you receive this message as part of CWTAI2007E, the OIDC TAI was unable to retrieve the state information from the local cache.  It must use cookies for state data instead of local storage and then the state cookie was not found on the HTTP request.

    The stateId is created by the OIDC TAI when the client makes a request. This stateId is sent to the OP and the OP returns this stateId to the OIDC TAI. This stateId is used to associate the authentication response from the OP with the client's original request data to the protected resource.

    This message means that there was either no OIDC state cookie or no data in the OIDC state cookie with which to restore the client's original request data.

    This problem can occur if:
    1. Your OP redirects back to a hostname that is not the same as the hostname in the original client request. For instance, when an IP address, hostname, or cluster member hostname is used instead of the general cluster hostname.
    2. The user's login request timed out, or
    3. The following sequence of events occurred on the same browser implementation on the same workstation:
      1. Access to a protected resource is requested, but the login to the OP is not completed,
      2. You then access and complete the login for the same or another protected resource in the same, or another WebSphere Application Server instance where the resource is associated with the same OIDC TAI clientId as the first,
      3. When you go back and complete the login flow for the first request, you get this error because the OIDC cookie was deleted in step b.


    User Action:
     
    • First, make sure that your users complete the login process within the time frame required by your -stateIdTimeoutSeconds OIDC TAI setting (default=600).
    • Make sure one login sequence is complete in each browser implementation on a workstation before you start a new one.
    • When both cookies and local state caching are enabled, the TAI uses local storage first, then use the cookie as a backup. If you receive many of these errors and you have local storage turned off, you might want to consider turning local storage back on by setting -maxStateCacheSize to a value other than 0 (zero).
    • If you already have local storage enabled or you do not want to enable local storage, make sure that the hostname from the user's initial request to the page that the TAI intercepted is the same as the hostname that the OP is redirecting the user back to after the OP login.  This action makes sure that the browser sends the cookie to WebSphere Application Server.
    • If the OP is sending the cookie, but the OIDC TAI still isn't receiving it, ensure that your load balancer or proxy server is not stripping off cookies.


     

    CWTAI2019E: The state id [8he53qrmnp4mtkm20f1v357vq6_1495623614293] in the OpenID Connect relying party (RP) state cookie [OIDCSTATE_sp1] does not match the state id [9if64rsnoq5nuln31g2w468wr7_2506734725304] received from the OpenID Connect provider

    This error message is emitted because the OIDC TAI was unable to perform a complete login. Further information and direction can be obtained from the Explanation and User Action for the CWTAI2019E message:



    Explanation:
     
    When you receive this message, the OIDC TAI is using cookies to retrieve the state data for the request either because the state data was not found in the local cache, or local caching was disabled.

    The stateId is created by the OIDC TAI when the client makes a request. This stateId is sent to the OP and the OP returns this stateId to the OIDC TAI. This stateId is used to associate the authentication response from the OP with the client's original request data to the protected resource.

    This message means that the stateId in the authentication response from the OP is different than the stateId in the OIDC TAI state cookie, therefore the client's original request data cannot be restored. The most likely cause for this problem is that the client initiated a request to a protected resource.  Before the user completes the login with the OP, the user initiates a login to another protected resource and the cookie written by the first request was overwritten by the second.


    User Action:
     
    There are several things that you can do about this issue:
    1. To ensure that you are more likely to find the state data in the cache, tailor how long the state data remains in the cache by using the -maxStateCacheSize and -stateIdTimeoutSeconds properties,
    2. Ensure that each login is completed before you start a new one,
    3. Ensure that each provider_<id>.clientId property is set to a unique value across all application servers that are running the OIDC TAI,
    4. Change the OIDC TAI configuration to use unique cookie names for each request instead of a single cookie name for all requests; you can configure unique state cookies by setting useUniqueStateCookies to true.


     

    CWTAI2030I: The OpenID Connect TAI was unable to retrieve the request data with stateId [8he53qrmnp4mtkm20f1v357vq6_1495623614293] from the state map. It may have expired

    This message is informational. If it is part of a CWTAI2007E, there is an error because the OIDC TAI was unable to perform a complete login. However, depending on of the environment, this error message might be expected and can be ignored. Further information and direction can be obtained from the Explanation and User Action for the CWTAI2030I message:



    Explanation:
    When you receive this message as part of CWTAI2007E, the OIDC TAI is using only local storage for state data with no cookie backup.

    The stateId is created by the OIDC TAI when the client makes a request. This stateId is sent to the OP and the OP returns this stateId to the OIDC TAI. This stateId is used to associate the authentication response from the OP with the client's original request data to the protected resource.

    This message means that the OIDC TAI was unable to retrieve the data for the client's original request from local storage by using the stateId that was returned from the OP. This error can be caused by several things:
    1. The stateId was created on a different application server.
    2. The OP replayed an authentication response; stateIds can be used only once.
    3. The value for stateIdTimeoutSeconds is less than the number of seconds that the user spent to log in to the OP; the default is 600,
    4. The value maxStateCacheSize is too small for the server's load; the default is 10,000.

    If you see this message in a log without it being part of a CWTAI2007E error, the OIDC TAI logged this message before it attempted to use the cookie. No action is required in this case unless you also get an error with the cookie.


    User Action:
    If you are running in a cluster environment, you need to ensure:
    • Session affinity is enabled
    • The value for provider_<id>.createSession is set to true if you are using IHS as your front end.

    When both cookies and local state caching are enabled, the TAI uses local storage first, then use the cookie as a backup.
    • If you receive many of these errors and you configured to not use cookies, you might want to consider turning cookies back on by setting -useStateCookies=true (the default).
    • If you set -maxStateCookieSize=0, -useStateCookies defaults to false. The value for -maxStateCookieSize defaults to the value for -maxCookieSize.
    • If you don't want to change your configuration to use state cookies and you are receiving this message many times when users are logging in a timely manner, use a combination of -maxStateCacheSize and -stateIdTimeoutSeconds that handles the server's load.

    To debug this issue, do the following:
     
    • Ensure that you are running the latest version of the OIDC TAI.
    • When you debug this issue, the OIDC TAI trace must be from server startup.
    1. Search the trace for the first occurrence of the CWTAI2030I message:
      [7/19/17 9:14:33:761 GMT] 00000191 StateData 3 CWTAI2030I: Unable to retrieve the OIDC request data with stateId [sfkg71qpvk4gmomcia5rp8tjds_1500455672550] from the state map. It may have expired.
    2. Check whether the stateId was created on this server:
      1. Search backwards for the stateId show in the message.
      2. If you do not find an instance of getNewStateId that contains the stateId in the CWTAI2030I message, then the stateId was not created on this server. Here is an example of the output from getNewStateId:
        • [7/19/17 9:04:29:060 GMT] 00000191 StateData 3 getNewStateId returns [pmbt6rttkm5tae9jf0o1f0gm88_1500455069060]
      3. If the stateId was not created on this server, you might have one of the following issues:
      • Session affinity is not being maintained.
      • The OP is making up stateIds .
    3. If you find a getNewStateId trace statement that contains the stateId in the CWTAI2030I message, check to see whether the login timed out:
      1. Find where the stateId was created:
        [7/19/17 9:04:29:060 GMT] 00000191 StateData 3 getNewStateId returns [sfkg71qpvk4gmomcia5rp8tjds_1500455672550]
      2. Subtract the time that the stateId was created from the time of the error.
        • In this case, it is (9:14:33:761) - (9:04:29:060); about 10minutes and 4 seconds
      3. Find your stateId timeout setting by searching for initStateMap (initStateMap is run only once, so you really need a trace from server startup):
        [7/19/17 02:49:31:180 GMT] 00000001 StateData 3 ==> initStateMap
        [7/19/17 02:49:31:180 GMT] 00000001 StateData > initStateMap(useCookies[true], stateCacheSize[10000], maxCookieSize[4093], stateCookieTimeout[600], uniqueStateCookies[false]) Entry
        1. The stateCookieTimeout is in seconds.
        2. In this case, its 600 seconds (10 minutes; the default).
        3. Since the timeout is 10 minutes and the elapsed time is 10minutes, 4 seconds, the login timed out.
          • Make sure that users log in within the configured timeout period.
          • You can configure a longer timeout period with the stateIdTimeoutSeconds OIDC TAI property.
    4. If the stateId was returned from the OP within the timeout period, make sure that the stateId was not previously processed by this server:
      1. Just after the entry to RelyingParty.handleSigninCallback, find the entry to RelyingPartyUtils.createSessionDataObjectFromStateData that contains the stateId :
        [7/19/17 09:52:41:539 GMT] 0000008e RelyingPartyU > createSessionDataObjectFromStateData(stateId[m5d41lrv0u5u6o1iuj6j2mtmfd_1489089159164], req[not null], res[not null], rpConfig[not null]) Entry
      2. Are more than one of the createSessionDataObjectFromStateData statements that contain the stateId in the CWTAI2030I message?
      • You must have only one of these createSessionDataObjectFromStateData statements for each stateId that is created. Once this process is complete, the entry in the state cache for the state id is removed. If the same stateId is returned from the server more than once, you get the CWTAI2030I message. The OP is not allowed to reuse stateIds .
    5. If you eliminated all the previous causes, it is possible that the entry was eliminated from the cache by the cache manager.
      1. When the cache limit is reached, the entries are removed with an LRU scheme.
      2. The default state cache size is 10,000.
      3. If you want to modify the setting for maxStateCacheSize, consult the description for the maxStateCacheSize property in WebSphere OpenID Connect, Full Profile Custom Properties.
      The OIDC TAI is designed to use the in-memory cache as the primary storage for state information. It writes a cookie as backup so that it has something to revert to in case the state information was evicted from the cache. If you get random CWTAI2030I messages in you logs, but you can see the runtime picking up its cookies and logging in successfully, then the runtime is working as designed.

      Do not set maxStateCacheSize=0 just because you don't like getting the CWTAI2030I message in your log. This setting turns off the in-memory state cache and causes other behavior that you might find less than desirable. You modify this setting only when you are tuning your runtime as a whole, considering:

      stateIdTimeoutSeconds
      useStateCookies
      useUniqueStateCookies
      maxStateCacheSize


      Do not turn off the state cache in a production environment without confirming that you are comfortable with the behavior of the OIDC TAI in a test environment.
     

    CWTAI2007E: The OpenID Connect relying party (RP) encountered a failure during the login. The exception is [com.ibm.ws.security.oidc.client.RelyingPartyException: The value for the OIDC state cookie [OIDCSTATE_NGE3OGY0NGQtY2E0ZS00] failed validation]


    To debug this error, do the following:
     
    • Ensure that you are running the latest version of the OIDC TAI.
    • When you debug this error, the OIDC TAI trace must be from server startup.
    1. Search the trace for the first occurrence of the error:
      [7/19/17 9:14:33:762 GMT] 00000191 RelyingParty E CWTAI2007E: The OpenID Connect relying party (RP) encountered a failure during the login. The exception is [com.ibm.ws.security.oidc.client.RelyingPartyException: The value for the OIDC state cookie [OIDCSTATE_NGE3OGY0NGQtY2E0ZS00] failed validation.]. Check the logs for details that lead to this exception.
    2. Search backwards for the CWTAI2030I cache miss message on the same thread; it is only a few lines up:
      [7/19/17 9:14:33:761 GMT] 00000191 StateData 3 CWTAI2030I: Unable to retrieve the OIDC request data with stateId [sfkg71qpvk4gmomcia5rp8tjds_1500455672550] from the state map. It may have expired

      If you find a CWTAI2030I and are using a state cache (the default), stop here and follow the debug procedures for the CWTAI2030I message.
      If you do not see a CWTAI2030I message, continue with this debug procedure.
    3. Search backwards for the return from calculateCookieValue on the same thread (it is immediately before the error):
      [7/19/17 9:14:33:762 GMT] 00000191 StateData < calculateCookieValue returns [rO0ABXNyABNqYXZhLnV0aWwuSGFzaHRhYmxlE7sPJSFK5LgDAAJGAApsb2FkRmFjdG9ySQAJdGhyZXNob2xkeHA/QAAAAAAACHcIAAAACwAAAAN0AAZyZXFVcmx0ADRodHRwczovL3czLTAxLmlibS5jb20vdG9vbHMvd3NlL3dtaS9wcm90ZWN0L21lbnUud3NzdAAHc3RhdGVJZHQAKHFwODhzMXMyMnVvNmF0NmthM2hiYzFvbHBnXzE1MDA0NTUzNTk4OTR0AAZtZXRob2R0AANHRVR4_-1760675135] Exit
    4. Search backwards for the entry to resolveCookieValue on the same thread:
      [7/19/17 9:14:33:762 GMT] 00000191 StateData < resolveCookieValue(cookieValue[rO0ABXNyABNqYXZhLnV0aWwuSGFzaHRhYmxlE7sPJSFK5LgDAAJGAApsb2FkRmFjdG9ySQAJdGhyZXNob2xkeHA/QAAAAAAACHcIAAAACwAAAAN0AAZyZXFVcmx0ADRodHRwczovL3czLTAxLmlibS5jb20vdG9vbHMvd3NlL3dtaS9wcm90ZWN0L21lbnUud3NzdAAHc3RhdGVJZHQAKHFwODhzMXMyMnVvNmF0NmthM2hiYzFvbHBnXzE1MDA0NTUzNTk4OTR0AAZtZXRob2R0AANHRVR4_-1336340697], secret[not null]) Entry
      • The value after the underscore must match. When they don't, you get the state cookie validation error.
      • When you get this cookie validation error, the most likely cause is that this cookie was written out by an OIDC TAI on another server that uses the same clientId as this server with a different clientSecret. You also have this message in the trace:
        [7/19/17 9:14:33:761 GMT] 00000191 StateData 3 CWTAI2030I: Unable to retrieve the OIDC request data with stateId [sfkg71qpvk4gmomcia5rp8tjds_1500455672550] from the state map. It may have expired.
    5. Verify that this cookie was not written by this server by searching backwards in the trace for the cookie value passed to resolveCookieValue in a 'Creating state cookie' entry. For instance:
      [7/19/17 2:59:43:717 GMT] 00000999 StateData 3 Creating state cookie [OIDCSTATE_NGE3OGY0NGQtY2E0ZS00] with value [rO0ABXNyABNqYXZhLnV0aWwuSGFzaHRhYmxlE7sPJSFK5LgDAAJGAApsb2FkRmFjdG9ySQAJdGhyZXNob2xkeHA/QAAAAAAACHcIAAAACwAAAAN0AAZyZXFVcmx0AENodHRwczovL3czLTAxLmlibS5jb20vdG9vbHMvd3NlL3J1bnRpbWUvdWF0L3Byb3RlY3QvZXNpZ24vaW5kZXgud3NzdAAHc3RhdGVJZHQAKGprcXV2bmRsY2Y4aTZyY3YzcmQ0Ymo1NTIyXzE1MDA0MzMxODM3MTZ0AAZtZXRob2R0AANHRVR4_1057642553]

    If you find that you are getting this cookie validation error and you verified that your process did not produce the cookie, if you are operating in a cluster environment, do the following:
    1. Ensure that session affinity is configured on your front end.
    2. If you are using IHS as your front end, ensure that you have the provider_<id>.createSession OIDC TAI custom property set to true. The default is false. This property directs the OIDC runtime to create the JSESSIONID cookie that IHS requires to maintain session affinity.

    This realm is not the current realm, nor the admin realm, nor a trusted realm

    When you access your protected resource, then successfully log in to the OP, you might be presented with a form login. When get get the form login, you might see an entry like one the following in one of the most recent FFDC files:
    com.ibm.websphere.security.auth.WSLoginFailedException: This realm is not the current realm, nor the admin realm, nor a trusted realm: SomeForeignRealm com.ibm.ws.security.config.SecurityConfigImpl@855256a2 C:\was90011_base\WebSphere\AppServer\profiles\server\config\cells/wsx7Cell/security.xml  (admin) :com.ibm.websphere.security.auth.WSLoginFailedException: This realm is not the current realm, nor the admin realm, nor a trusted realm: SomeForeignRealm

    To debug the issue, do the following one of the following:
    1. Go to the end of your OIDC trace, then search backwards for _idToken's realm
      [6/11/19 15:32:40:670 EDT] 000000cd SessionData 3 _idToken's realm=[SomeForeignRealm]
    2. If you search backwards again for id token, a copy of the idToken that was sent from the OP is emitted. Example
      [6/11/19 15:32:40:670 EDT] 000000cd SessionData 3 id token[header[{"kid":"aScdFNCZH3oAkPKaPYuE","alg":"RS256"}], claims[{"sub":"Jackson","realmName":"SomeForeignRealm","uniqueSecurityName":"Jackson","at_hash":"pH7yHIsYCSDjmeefvPcT5Q", "iss":"https://localhost:9444/oidc/endpoint/OP","aud":"oidcclient","exp":1560288759,"iat":156028155"}]]
      • In this case, SomeForeignRealm came from the realmName claim.
      • If the realmName claim is not in the idToken, then the realmName defaults to the iss claim.
      • If the text is in the token, but not on the realmName or iss claim, you most likely configured a provider_<id>.realmIdentifier TAI custom property.
      • If you don't see the text from the message in the token at all, you might have configured the realm on the provider_<id>.defaultRealmName or provider_<id>.useRealm properties.
      • Note the Liberty OP includes a realmName claim by default. Its default value is BasicRegistry.
     
    Remediation:
    Regardless of where the value came from, perform one of the following actions to fix this issue:
    • Hardcode the OIDC TAI to use the local realm:
      • Add the provider_<id>.useRealm=(localRealmName) property to your OIDC TAI configuration.
        • If you are running OIDC 1.4.0 or later, or WebSphere 8.5.5.23 or 9.0.5.13 or later, you can set the property to WAS_DEFAULT.
        • Otherwise, to find your local realm name, perform the following actions:
          1. In the administrative console, navigate to Security > Global security
          2. Your realm name is in the Realm name field under User account repository.
    • -OR- Add the OP's realm as a trusted realm:
      1. Click Security > Global security.
      2. In the User account repository section, click Configure....
      3. In the Related Items section, click Trusted authentication realms - inbound > Add External Realm.
      4. In the External realm name field, enter the realm name displayed in the error message; SomeForeignRealm in this example.
      5. Click OK.

    SECJ5008W: The realm specified in com.ibm.wsspi.security.cred.realm (someForeignRealm) does not match the current realm (theLocalRealm). This could cause problems when trying to make a downstream request.

    When you see this warning in a trace it might be a sign of a problem, but it might not. You only need to worry about it if think that the mis-matched realm is causing is a problem. If you want to get rid of this warning for a realm that is from your OIDC OP, see the first remediation step at This realm is not the current realm, nor the admin realm, nor a trusted realm to hardcode the OIDC TAI to use the local realm.

    SESN0008E: A user authenticated as user:oidcForeignRealm/oidcUser has attempted to access a session owned by theLocalRealm/uid=localUser,o=theLocalRealm.

    Although this error might occur when you attempt to login to your application using the OIDC TAI, the error is a related to session security and is remediated with Web authentication settings. For more information, see Session security support:
    You can integrate HTTP sessions and security in WebSphere® Application Server. When security integration is enabled in the session management facility and a session is accessed in a protected resource, you can access that session only in protected resources from then on. Session security (security integration) is enabled by default.
    You cannot mix secured and unsecured resources accessing sessions when security integration is turned on. Security integration in the session management facility is not supported in form-based login with SWAM.
    To remediate the problem, see Web authentication settings.

    CWTAI2108E: None of the following claims are present in the JWT: [sub]

    The OIDC TAI gets the wrong user name from my IdToken or JWT

    The OIDC TAI defaults to using the sub claim to obtain the user name from the JWT or IdToken. If that claim is not in the token, or that claim does not contain the user name that you want to use, set the provider_(id).userIdentifier property to the claim name that you want to identify the user. The requirements of the claim that you specify for provider_(id).userIdentifier are that same as that of the sub claim:
    A locally unique and never reassigned identifier within the Issuer for the End-User, which is intended to be consumed by the Client, e.g., 24400320 or AItOawmwtWwcT0k51BayewNvutrJUqsvl6qs7A4. It MUST NOT exceed 255 ASCII characters in length. The sub value is a case sensitive string.
    The user name must be associated with a claim in the IdToken or JWT for the OIDC TAI to discover it.  For example, in this IdToken:
    { 
      "iss": "http://my-domain.auth0.com", 
      "sub": "123456789", 
      "aud": "1234abcdef", 
      "exp": 1311281970, 
      "iat": 1311280970,  
      "username": ["jane_doe"],
      "given_name": "Jane", 
      "family_name": "Doe",
      "email": "jane_doe@sampleco.com"
    }
    
    The default user name is the value for the sub claim, which is 123456789.  Other claims that are available to use as the user name are given_name, family_name, and email.  You cannot use the username claim because the value is expressed as an Array, not a String
    The user name that you want to use with WebSphere must appear in the JSON String for the IdToken or JWT.  If it does not, there is no way for the OIDC TAI to know the value.  If you do not see the desired user name in the IdToken or JWT for the user, contact your OP administrator to find out if the JSON can be modified to contain the information that you require.

    The groups from the IdToken or JWT are not on the Subject

    If the OIDC TAI is not configured to map to the user registry, it uses claims from the IdToken or JWT to assign group names to the WebSphere Subject. The provider_(id).groupIdentifier property controls the claim from which the groups are obtained. The default value for this property is groupIds.
     
    If you find that you have groups in your IdToken or JWT that aren't being populated onto the Subject, check the token to see if the groups are in a claim. If you find the claim that has the groups, set the provider_(id).groupIdentifier to the claim that contains the group names for the user.
     

    OIDC cookies are not deleted when I log out

    In order for OIDC cookies to be deleted on logout, the HttpServletRequest.logout method must be invoked from an OIDC protected URL. When the logout is invoked in this way, the RelyingParty.logout method is invoked. If you have this problem, you need to see whether the RelyingParty.logout is invoked. Search your OIDC trace for:
     
    ==> OIDC: PERFORMING LOGOUT

    If you don't see that entry in your OIDC trace, these causes are most likely:

    • There is no code that invokes HttpServletRequest.logout.
    • The code that invokes HttpServletRequest.logout is not intercepted by the TAI because:
      • The endpoint is not intercepted by the TAI's filters.
      • The endpoint does not have security constraints so it does not enter the TAI.
    For mor information, see Enabling programmatic logout for an OpenID Connect Relying Party in the IBM Documentation for information on how to perform OIDC logout to ensure that OIDC cookies are removed upon WebSphere logout.
     

    I'm in a login loop

    If the requests to your OIDC protected application end up in a login loop (see the process in Does the OIDC TAI require session affinity?), check for the following problems:

    How can I set up my Google™ API Console project so that I can use the Google OP with the WebSphere OIDC TAI

    If you want to use the Google OP with the OIDC TAI, you must first have a Google API Console project. Your console project must have at least one web client configuration.
     
    Go to the Examples: OpenID Connect, Liberty and WebSphere traditional page to see steps for Setting up a Google™ API Console project to use the Google OP with a WebSphere traditional or Liberty OIDC RP.
     
     

    How can I set up the WebSphere OIDC RP TAI to use the Google™ OP

    You can configure the WebSphere traditional OIDC RP to use the Google as the OP server.

    Go to the Examples: OpenID Connect, Liberty and WebSphere traditional page to see steps for Setting up the WebSphere traditional OIDC RP TAI to use the Google™ OP.
     

    How can I set up Microsoft® Azure™ to use with the WebSphere OIDC TAI

    If you want to use the Azure OP with the OIDC TAI, you must first have an Azure Active Directory application registered in the Azure portal.
    You can find a guide to walk you through setting up an application in a tenant from scratch or modifying an existing application in a tenant for use with the OIDC relying party at Set up Microsoft Azure as an SSO identity provider for WebSphere Application Server and Liberty clients in github.
     

    How do I configure OIDC with wsadmin

    You can configure OIDC by using the administrative console or the configureInterceptor task in wsadmin
    The following is an example of an interactive wsadmin command that configures the OIDC TAI:
    AdminTask.configureInterceptor('-interceptor com.ibm.ws.security.oidc.client.RelyingParty -customProperties ["provider_1.identifier=RP1","provider_1.discoveryEndpointUrl=https://localhost:8020/oidc/endpoint/OP/.well-known/openid-configuration","provider_1.interceptedPathFilter=/testpage/myservlet/ep1","provider_1.clientId=client1","provider_1.clientSecret=secret1"] ')
    The following is an example of a wsadmin script that enables the OIDC TAI.  This script does the following:
    • Configures the OIDC Relying Party TAI with the properties required for three provider configurations.
      • The configureInterceptor task is run three times, but in the end, all the properties are combined together under a single Trust Association entry for the com.ibm.ws.security.oidc.client.RelyingParty class.
    • Turns on Trust Association.
    • Adds https://issuer.com and BasicRealm as trust realms.
    • Sets the com.ibm.websphere.security.InvokeTAIbeforeSSO core Security custom property to com.ibm.ws.security.oidc.client.RelyingParty.
      configBegin="-interceptor com.ibm.ws.security.oidc.client.RelyingParty -customProperties '"
      configEnd="'"
      
      config = configBegin
      id="provider_1"
      config += "\"" + id + ".identifier=RP1\","
      config += "\"" + id + ".discoveryEndpointUrl=https://localhost:8020/oidc/endpoint/OP/.well-known/openid-configuration\","
      config += "\"" + id + ".interceptedPathFilter=/testpage/myservlet/ep1\","
      config += "\"" + id + ".clientId=client1\","
      config += "\"" + id + ".clientSecret=secret1\","
      config += "\"" + id + ".audiences=Audience\","
      config += "\"" + id + ".issuerIdentifier=http://issuer.com\","
      config += "\"" + id + ".signVerifyAlias=jwttestercert\","
      config += "\"" + id + ".verifyIssuerInIat=true\","
      config += "\"" + id + ".useJwtFromRequest=ifPresent\","
      config += "\"" + id + ".scope=openid general\""
      config += configEnd
      print "\n configuring " + config
      AdminTask.configureInterceptor(config)
      
      config = configBegin
      id="provider_2"
      config += "\"" + id + ".identifier=tokens\","
      config += "\"" + id + ".discoveryEndpointUrl=https://localhost:8020/oidc/endpoint/OP/.well-known/openid-configuration\","
      config += "\"" + id + ".clientId=tokens\","
      config += "\"" + id + ".clientSecret=password\","
      config += "\"" + id + ".interceptedPathFilter=/oidcoauth/jaxrs/test/.*,/oidcoauth/jaxrs/endpoint/.*\","
      config += "\"" + id + ".excludedPathFilter=/oidcoauth/jaxrs/test/unsecure.*\""
      config += configEnd
      print "\n configuring " + config
      AdminTask.configureInterceptor(config)
      
      config = configBegin
      id="provider_3"
      config += "\"" + id + ".identifier=oauth\","
      config += "\"" + id + ".discoveryEndpointUrl=https://localhost:8020/oidc/endpoint/OP/.well-known/openid-configuration\","
      config += "\"" + id + ".clientId=tokens\","
      config += "\"" + id + ".clientSecret=password\","
      config += "\"" + id + ".scope=openid\","
      config += "\"" + id + ".grantType=all\""
      config += configEnd
      print "\n configuring " + config
      AdminTask.configureInterceptor(config)
      
      AdminTask.addTrustedRealms('[-communicationType inbound -realmList http://issuer.com|BasicRealm]')
      AdminTask.configureTrustAssociation("-enable true")
      AdminTask.setAdminActiveSecuritySettings(' -customProperties \'"com.ibm.websphere.security.InvokeTAIbeforeSSO=com.ibm.ws.security.oidc.client.RelyingParty"\'')
      AdminConfig.save() 
    When you run this wsadmin script, the following is output:
    WASX7209I: Connected to process "server1" on node wsx61Node using SOAP connector; The type of process is: UnManagedProcess

    configuring -interceptor com.ibm.ws.security.oidc.client.RelyingParty -customProperties '"provider_1.identifier=RP1","provider_1.discoveryEndpointUrl=https://localhost:8020/oidc/endpoint/OP/.well-known/openid-configuration","provider_1.interceptedPathFilter=/testpage/myservlet/ep1","provider_1.clientId=client1","provider_1.clientSecret=secret1","provider_1.audiences=Audience","provider_1.issuerIdentifier=http://issuer.com","provider_1.signVerifyAlias=jwttestercert","provider_1.verifyIssuerInIat=true","provider_1.useJwtFromRequest=ifPresent","provider_1.scope=openid general"'

    configuring -interceptor com.ibm.ws.security.oidc.client.RelyingParty -customProperties '"provider_2.identifier=tokens","provider_2.discoveryEndpointUrl=https://localhost:8020/oidc/endpoint/OP/.well-known/openid-configuration","provider_2.clientId=tokens","provider_2.clientSecret=password","provider_2.interceptedPathFilter=/oidcoauth/jaxrs/test/.*,/oidcoauth/jaxrs/endpoint/.*","provider_2.excludedPathFilter=/oidcoauth/jaxrs/test/unsecure.*"'

    configuring -interceptor com.ibm.ws.security.oidc.client.RelyingParty -customProperties '"provider_3.identifier=oauth","provider_3.discoveryEndpointUrl=https://localhost:8020/oidc/endpoint/OP/.well-known/openid-configuration","provider_3.clientId=tokens","provider_3.clientSecret=password","provider_3.scope=openid","provider_3.grantType=all"'
    And you can see the following when you navigate to Security > Global Security > Web and SIP security > Trust association > Interceptors > com.ibm.ws.security.oidc.client.RelyingParty in the administrative console:

      image-20221220115339-1

    What open source projects are included in the OIDC jar?

    The open source projects that are included in the OIDC jar include, but are not limited to:
    Open source
    project
    Open source 
    version
    v90 fix pack
    (if updated from the
    one included in the
    first version of the
    TAI)
    Open source 
    version for v855
    (if different than v90)
    v855 fix pack
    (if updated from the
    one included in the
    first version of the
    TAI)
    delivery version
    Apache Commons Codec 1.15 9.0.5.17 8.5.5.25 1.5.0
    Apache HttpClient 4.5.14 9.0.5.17 8.5.5.24 1.4.0
    jose4j 0.9.3 9.0.5.17 8.5.5.25 1.5.0
    0.9.5 1.5.2
    Google Guava 32.1.1 9.0.5.17 30.1.1.1 8.5.5.25 1.5.0
    Ported CVE: CVE-2023-2976
    image-20231017135929-1  This data for the open source projects is provided for information purposes only. 
    • None of the open source classes are exported by the OIDC jar for use by customer applications. 
    • Open source projects might be updated, added, or removed from use by the TAI at any time.
    • Open source projects are updated if the OIDC TAI requires an update to function properly or there is a CVE discovered in the open source project.

    How do I find if my sigature algorithm is supported

    In OIDC 1.4.0 and later, and WebSphere 8.5.5.23, and 9.0.5.13 and later, the OIDC TAI relies on its embedded jose4j open source library to handle the signature and encryption algorithms. Which signature and encryption algorithms are and are not supported is controlled by the jose4j version that is included by the OIDC TAI. 
     
    In OIDC 1.4.0 and later, and WebSphere 8.5.5.23, and 9.0.5.13 and later, to let jose4j control the supported signature algorithms, you must either set the provider_<id>.signatureAlgorithm property to HEADER or do not set the property.  If you set provider_<id>.signatureAlgorithm to any value other than HEADER, the OIDC TAI uses that value and it can be set to one of the values that was previously supported.
     
    Support for PS256 is added in fix packs 8.5.5.24 and 9.0.5.16 with APAR PH52459.
     
    Before OIDC 1.4.0 and WebSphere fix packs 8.5.5.23, and 9.0.5.13, the following signature algorithms are supported:
     
    • HS256 and RS256
    • Support for RS512 was added in fix packs 8.5.5.18 and 9.0.5.4 with APAR PH23697.
    • Support for none was added in fix packs 8.5.5.23 and 9.0.5.13 with APAR PH45740.
     
    image-20230113083757-9 If you want the OIDC TAI to restrict the signature algorithms that jose4j accepts for your JWTs, you can use the provider_<id>.signatureAllowList and provider_<id>.signatureDenyList OIDC TAI properties.  See the OpenID Connect Relying Party custom properties page in IBM Docs to see how to use these properties.
    To find if the signature or encryption algorithm that you are looking for is supported, use the following information:
    • In WebSphere Application Server 8.5.5.24 and 9.0.5.16 and earlier, and OIDC 1.4.0 and earlier, the OIDC runtime uses the jose4j 0.6.5 library.
    • In OIDC 1.5.0, the jose4j library is updated to 0.9.3.
    1. The WebSphere traditional OIDC runtime supports any encryption and signature algorithm supported by the version of the jose4j library that it includes.
    2. If an algorithm is found in one of the tables and the support is questionable, the jose4j release notes can be checked to see whether support was added after the jose4j library in use.
    image-20230113083757-9 Here is an example for finding support for the PS256 signature algorithm:
    • There is an issue with Jose4j interacting with IBM JDKs for the RS256 algorithm. An update to OIDC in WebSphere is required to use PS256: APAR PH52459 that is delivered in fix packs 8.5.5.24 and 9.0.5.16.
    1. In a browser, go to the link for the signature and encryption algorithms supported by the latest jose4j: https://bitbucket.org/b_c/jose4j/wiki/Home
    2. Search the page for PS256
      • image-20230113082532-2
    3. Go to the jose4j release notes: https://bitbucket.org/b_c/jose4j/wiki/Release%20Notes
    4. Search for the string PS256:
      • image-20230113083326-7
      • That statement is not for adding the algorithm, search again:
      • image-20230113083516-8
      • The PS256 was added in jose4j 0.3.5 in April 2014.
      • Since the OIDC TAI uses jose4j 0.6.5 or 0.9.3, PS256 is supported.

    CWWDR0008E: Runtime exception occured : Unable to locate Replication Domain: DynaCacheCluster

    If you see the following errors in your OIDC trace, you can ignore them:

    [20/02/23 16:06:45:969 GMT] 0000015d MultibrokerDo E CWWDR0008E: Runtime exception occured : Unable to locate Replication Domain: DynaCacheCluster
    [20/02/23 16:06:45:971 GMT] 0000015d CacheServiceI E Replication domain for cache instance "ws/OIDCRPDistributedCacheMap" not found. Therefore, the cache replication is disabled.
     
    The OIDC runtime sets up a DynaCache distributed map called OIDCRPDistributedCacheMap and configures it for replication.  The OIDCRPDistributedCacheMap map is always a local map due to the session affinity requirement and there is no need to replicate the map with the cluster members.   The code remains in the runtime in case the session affinity requirement is removed.  In that event, it is the responsibility of the user to create the DynaCacheCluster replication domain. 

    SECJ0129E: Authorization failed for user

    You might see an error like the following for one or more of the users from your OP:

    [4/19/23 20:05:47:339 UTC] 00000138 WebCollaborat A SECJ0129E: Authorization failed for user opUser1 while invoking GET on default_host:/endpoint1/, Authorization failed, Not granted any of the required roles: example_group1 example_group2
     
    In this specific case, opUser1 is not a member of any of the groups required to access the protected resource, endpoint1. The required groups are shown in the message.

    Remediation:

    If you expect your OP users to have permission to the protected endpoints, but they do not, perform at least one of the following actions:

    • image-20230113083757-9 If the OP users are in the WebSphere registry, set the following OIDC TAI property and value:
      provider_<id>.mapIdentityToRegistryUser true
    • image-20230113083757-9 If at least one of the groups in the message are picked up from your id_token, but they have the OP's realm prepended to them instead of the WebSphere realm, set the following OIDC TAI property and value:
      provider_<id>.useRealm WAS_DEFAULT
    • image-20230113083757-9 If at least one of the groups in the message are in the id_token, but the TAI is not picking it up, check if your id_token has the groups in a claim other than the groupIds claim.  If it does, set the following OIDC TAI properties and values:
      provider_<id>.groupIdentifier = (claimName)
      provider_<id>.useRealm = WAS_DEFAULT
    • image-20230113083757-9 If none of the above methods work, or are not appropriate, follow the steps in WebSphere application security role mapping to external groups.
    Cookie “OIDCSESSION_12345678” does not have a proper “SameSite” attribute value.
    In the FireFox browser, you might encounter a warning that is similar to this one for the OIDCSESSION* or LTPAToken2 cookies:
    Some cookies are misusing the recommended “SameSite“ attribute:
    - Cookie “OIDCSESSION_12345678” does not have a proper “SameSite” attribute value. Soon, cookies without the “SameSite” attribute or with an invalid value will be treated as “Lax”. This means that the cookie will no longer be sent in third-party contexts. If your application depends on this cookie being available in such contexts, please add the “SameSite=None“ attribute to it. To know more about the “SameSite“ attribute, read https://developer.mozilla.org/docs/Web/HTTP/Headers/Set-Cookie/SameSite for navigator request
    Action:
    When you see an error like the following, you might have incorrect credentials configured for your OP:

    [8/11/23 6:51:51:134 CEST] 0000014b RelyingParty E CWTAI2007E: The OpenID Connect relying party (RP) encountered a failure during the login. The exception is [ResponseCode: 401]. Check the logs for details that lead to this exception.

    [8/11/23 6:51:51:136 CEST] 0000014b WebAuthentica E SECJ0126E: Trust Association failed during validation. The exception is com.ibm.websphere.security.WebTrustAssociationFailedException: CWTAI2007E: The OpenID Connect relying party (RP) encountered a failure during the login. The exception is [ResponseCode: 401]. Check the logs for details that lead to this exception.

    To find if this is the problem, check the trace for the following entry:

    [8/11/23 6:51:51:134 CEST] 0000014b RelyingParty 3 The TAI encountered failure while exchanging the authorization_code with accessToken.

    [8/11/23 6:51:51:134 CEST] 0000014b RelyingParty 3 The OP server responded with return code:[401] and message:[{"error_description":"Invalid client or client credentials.","error":"invalid_client"}]

    Note that the error_description and error that you see is returned from the OP and is specific to the OP implementation (like WebSphere Liberty, Azure, PingOne, etc).
    Action:
    • To fix this error, make sure that your provider_(id).clientId and provider_(id).clientSecret OIDC TAI property values match the values that are configured on your OP.
    Why do I get a 401 reply on my initial request?
    com.ibm.ws.security.web.WebSecurityException on initial request
     
    When you make a request to an endpoint that is protected by the OIDC TAI (or any TAI) and that request is redirected to another endpoint for authentication, it is expected to see 401 HTTP result and a com.ibm.ws.security.web.WebSecurityException.  Here is an example trace snip that applies to both OIDC and SAML:
    [2/20/24 16:33:56:211 SAST] 00000176 WebCollaborat 3   URI -  /process.getSomething.GET is protected
    [2/20/24 16:33:56:211 SAST] 00000176 WebCollaborat 3   Saving previous subject null
    [2/20/24 16:33:56:211 SAST] 00000176 WebCollaborat 3    >>> Authentication failed. Reason: null
    [2/20/24 16:33:56:211 SAST] 00000176 TAIChallengeR >  TAIChallengeReply(401) Entry
    [2/20/24 16:33:56:211 SAST] 00000176 TAIChallengeR <  TAIChallengeReply() Exit
    [2/20/24 16:33:56:211 SAST] 00000176 WebCollaborat 3   TAI authentication challenge - sending 401
    [2/20/24 16:33:56:211 SAST] 00000176 WebCollaborat <  checkAuthStatus Exit
                                     com.ibm.ws.security.web.TAIChallengeReply@8f7491d6
    [2/20/24 16:33:56:211 SAST] 00000176 WebCollaborat <  authorize Exit
                                     com.ibm.ws.security.web.TAIChallengeReply@8f7491d6
    [2/20/24 16:33:56:211 SAST] 00000176 EJSWebCollabo >  handleException Entry
                                     com.ibm.ws.webcontainer.srt.SRTServletRequest@eebc2f07
                                     com.ibm.ws.webcontainer.srt.SRTServletResponse@4c9348e9
                                     com.ibm.ws.security.web.WebSecurityException
    	at com.ibm.ws.security.web.EJSWebCollaborator.preInvoke(EJSWebCollaborator.java:453)
    	at com.ibm.ws.webcontainer.collaborator.WebAppSecurityCollaboratorImpl.preInvoke(WebAppSecurityCollaboratorImpl.java:230)
    	at com.ibm.wsspi.webcontainer.collaborator.CollaboratorHelper.preInvokeCollaborators(CollaboratorHelper.java:436)
    	at com.ibm.ws.webcontainer.filter.WebAppFilterManager.invokeFilters(WebAppFilterManager.java:1089)
    	at com.ibm.ws.webcontainer.webapp.WebApp.handleRequest(WebApp.java:4075)
    	at com.ibm.ws.webcontainer.webapp.WebGroup.handleRequest(WebGroup.java:304)
    	at com.ibm.ws.webcontainer.WebContainer.handleRequest(WebContainer.java:1019)
    	at com.ibm.ws.webcontainer.WSWebContainer.handleRequest(WSWebContainer.java:1817)
    	at com.ibm.ws.webcontainer.channel.WCChannelLink.ready(WCChannelLink.java:213)
    	at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleDiscrimination(HttpInboundLink.java:463)
    	at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleNewRequest(HttpInboundLink.java:530)
    	at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.processRequest(HttpInboundLink.java:316)
    	at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.ready(HttpInboundLink.java:287)
    	at com.ibm.ws.ssl.channel.impl.SSLConnectionLink.determineNextChannel(SSLConnectionLink.java:1188)
    	at com.ibm.ws.ssl.channel.impl.SSLConnectionLink$MyReadCompletedCallback.complete(SSLConnectionLink.java:695)
    	at com.ibm.ws.ssl.channel.impl.SSLReadServiceContext$SSLReadCompletedCallback.complete(SSLReadServiceContext.java:1833)
    	at com.ibm.ws.tcp.channel.impl.AioReadCompletionListener.futureCompleted(AioReadCompletionListener.java:175)
    	at com.ibm.io.async.AbstractAsyncFuture.invokeCallback(AbstractAsyncFuture.java:217)
    	at com.ibm.io.async.AsyncChannelFuture.fireCompletionActions(AsyncChannelFuture.java:161)
    	at com.ibm.io.async.AsyncFuture.completed(AsyncFuture.java:138)
    	at com.ibm.io.async.ResultHandler.complete(ResultHandler.java:204)
    	at com.ibm.io.async.ResultHandler.runEventProcessingLoop(ResultHandler.java:775)
    	at com.ibm.io.async.ResultHandler$2.run(ResultHandler.java:905)
    	at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1892)
    
    [2/20/24 16:33:56:212 SAST] 00000176 EJSWebCollabo 3   Response is already committed
    [2/20/24 16:33:56:212 SAST] 00000176 EJSWebCollabo 3   com.ibm.websphere.security.allow.committed.response is false
    [2/20/24 16:33:56:212 SAST] 00000176 WebSecurityCo 3   Getting pushed security value "true" for: com.ibm.ws.security.web.WebSecurityContext@84aff0cb
    [2/20/24 16:33:56:212 SAST] 00000176 EJSWebCollabo 3   handleException popped resource COMPANY_CO_Application_One of type Application
    [2/20/24 16:33:56:212 SAST] 00000176 WebSecurityCo 3   Getting pushed admin value "false" for: com.ibm.ws.security.web.WebSecurityContext@84aff0cb
    [2/20/24 16:33:56:212 SAST] 00000176 EJSWebCollabo <  handleException Exit
    [2/20/24 16:33:56:213 SAST] 00000176 EJSWebCollabo >  postInvoke Entry
                                     com.ibm.ws.security.web.WebSecurityContext@84aff0cb
    [2/20/24 16:33:56:213 SAST] 00000176 EJSWebCollabo 3   Resetting invoked: null and received: nullsubjects
    [2/20/24 16:33:56:213 SAST] 00000176 WebSecurityCo 3   Getting pushed security value "true" for: com.ibm.ws.security.web.WebSecurityContext@84aff0cb
    [2/20/24 16:33:56:213 SAST] 00000176 EJSWebCollabo 3   postInvoke popped null resource
    
    In the case of OIDC, earlier in the trace, you can see where the request is redirected. You can find a similar trace entry for SAML.
    [2/20/24 16:33:56:209 SAST] 00000176 RelyingParty  3   ==> OIDC: Sending redirect to [https://company.co/authorization] via javascript
    2/20/24 16:33:56:210 SAST] 00000176 RelyingParty  3   Creating TAIResult with SC_UNAUTHORIZED [401]
    [2/20/24 16:33:56:210 SAST] 00000176 RelyingParty  <  initiateLogin returns [not null] Exit
    [2/20/24 16:33:56:210 SAST] 00000176 RelyingParty  3   ==> OIDC: PROCESS COMPLETE
    [2/20/24 16:33:56:210 SAST] 00000176 RelyingParty  <  negotiateValidateandEstablishTrust returns [not null] Exit
    CWTAI2048E: The JSON Web Token (JWT) or ID token signature is not valid. JWT rejected due to invalid signature.

    You might get a CWTAI2048E error if you are using a Microsoft Azure or Entra OP and have custom signing key for your id_token.  When Azure is configured to use a custom signing key for the id_token, instead of exposing the kid for the id_token in the JWK URL from the discovery information for the tenant, it exposes the kid in a custom JWK URL that is associated with the clientId.

    If you are configured to use a Microsoft Azure or Entra OP and get a CWTAI2048E error, first navigate to the JWK URL for your tenant:

    https://login.microsoftonline.com/(tenant)/discovery/v2.0/keys
     

    Where (tenant) is your Azure tenant name.

    Example:

    https://login.microsoftonline.com/48a9f237-2fe4-2dbb-6eb1-eee2a0c6fd38/discovery/v2.0/keys
     

    Following is example output from an Azure JWK URL:

    {"keys":[{"kty":"RSA","use":"sig","kid":"AgORTaxZrBReLMtO-0A74wQqR4","x5t":"NgORTaxPrWOeTvJtO-0N74wWqK4","n":"(binary)","e":"AQAB","x5c":["(binary)"]}]},{"keys":[{"kty":"RSA","use":"sig","kid":"VgYGTaxKrLGeTBtP-0A=R74wYqT4","x5t":"AgRTVaxMrRBeGvQtO-0P74wCqL4","n":"(binary)","e":"AQAB","x5c":["(binary)"],"issuer":"https://login.microsoftonline.com/48a9f237-2fe4-2dbb-6eb1-eee2a0c6fd38/v2.0"]}]}
     

    Then, in another browser tab or window, navigate to the following JWK URL:

    https://login.microsoftonline.com/(tenant)/discovery/v2.0/keys?appid=(clientId)
    Where (tenant) is your Azure tenant name and (clientId) is the value for your provider_(id).clientId property.

    Example:

    https://login.microsoftonline.com/48a9f237-2fe4-2dbb-6eb1-eee2a0c6fd38/discovery/v2.0/keys?appid=38fc27d-31ca-55ad-1c47-92c8ef065046
     

    Following is example output from an Azure client-specific JWK URL:

    {"keys":[{"kty":"RSA","use":"sig","kid":"ZgORTaxZrBReLMtO-0A74wOP89Y","x5t":"RgANEaxUrBAeNvPtO-0M74wUqZ4","n":"(binary)","e":"AQAB","x5c":["(binary)"],"issuer":"https://login.microsoftonline.com/48a9f237-2fe4-2dbb-6eb1-eee2a0c6fd38/v2.0"}]}
     

    Compare the output from the first JWK URL to the second.  If the kid in the second URL is not included in the first, to fix the CWTAI2048E error, you need to set your provider_(id).jwkEndpointUrl property to the client-specific JWK URL. 

    image-20231017135929-1 At this time, if you must set a custom provider_(id).jwkEndpointUrl property, you cannot set the provider_(id).discoveryEndpointUrl property to use discovery because discovery overrides your custom JWK URL setting.  You must instead use discrete endpoints for the rest of the properties that are associated with your OP.  The properties that must be set individually include, but are not limited to:
    provider_(id).issuerIdentifier
    provider_(id).authorizeEndpointUrl
    provider_(id).tokenEndpointUrl

    Note:

    This document uses the term WebSphere traditional to refer to WebSphere Application Server v9.0 traditional, WebSphere Application Server v8.5 full profile, WebSphere Application Server v8.0 and earlier, WebSphere classic, traditional WebSphere, traditional WAS, and tWAS.
     
     

    [{"Business Unit":{"code":"BU048","label":"IBM Software"},"Product":{"code":"SSEQTP","label":"WebSphere Application Server"},"ARM Category":[{"code":"a8m50000000CdESAA0","label":"Security-\u003ESSO-\u003EOpenId Connect"}],"ARM Case Number":"","Platform":[{"code":"PF002","label":"AIX"},{"code":"PF010","label":"HP-UX"},{"code":"PF012","label":"IBM i"},{"code":"PF016","label":"Linux"},{"code":"PF027","label":"Solaris"},{"code":"PF033","label":"Windows"},{"code":"PF035","label":"z\/OS"}],"Version":"8.5.5;9.0.0","Line of Business":{"code":"LOB67","label":"IT Automation \u0026 App Modernization"}}]

    Document Information

    Modified date:
    04 April 2024

    UID

    swg21975593