WebSphere Application Server & Liberty

WebSphere Application Server & Liberty

Join this online group to communicate across IBM product users and experts by sharing advice and best practices with peers and staying up to date regarding product enhancements.

 View Only
  • 1.  Authentication/authorization for users in two repositories (OpenID and standalone customer)

    Posted Tue October 25, 2022 12:55 PM
    Hello IBM Folks,

    I need to get a rather strange authentication/authorization scenario working for our WEB application deployed on a traditional WebSphere 9.0.5.10:

    I have two user repositories:

    1. A OpenIDRepository, which is managed by a n OpenID connect provider and configured as trusted authentication realm in WebSphere
    2. A StandaloneCustomRegistry

    All users and groups are contained in the StandaloneCustomRegistry. Some users/groups (which need SSO for another appplication) are contained in the OpenIDRepository, too.

    I mapped certain groups of both registries to application roles, to authorize users in both registries to access the application pages, e.g:

    Role_A -> Group_A@OpenIDRepository
    Role_B -> Group_B@StandaloneCustomRegistry

    I configured an OpenID Relying Party to call the authentication endpoint in our WEB application. The authentication endpoint requests username and password from the user and checks if the user is contained in the StandaloneCustomRegistry. If the user has a role, which requires SSO, the user agent is redirected to the redirection URI of the RP with an authorization code. The RP exchanges the tokes with the OpenID provider and redirects the user agent to the requested (protected) page. So far, so good!

    If the user doesn't require SSO, I just call the method HttpServletRequest.login() to authenticate the user by the StandaloneCustomRegistry. Then the user agent should just be redirected to the requested application page. And here starts my problem:

    If I redirect the user to the application page, the OpenID interceptor (RP) redirects the user agent again to the authentication endpoint, because it doesn't recognize, that the user is authenticated. If I redirect the user agent to the redirection URI of the RP with an error code (e.g. invalid_client. interaction_required) the RP logs an error and aborts the authentication process.

    So, the question is: is there a way to tell the RP to continue if the user is authenticated and authorized by the StandaloneCustomRegistry? Or is there another way to achieve our needs?

    Kind regards
    Thomas

    ------------------------------
    Thomas Mayr
    ------------------------------


  • 2.  RE: Authentication/authorization for users in two repositories (OpenID and standalone customer)

    Posted Wed October 26, 2022 01:23 PM
    Edited by Barbara Jensen Wed October 26, 2022 01:25 PM
    Hi Thomas,

    • See https://www.ibm.com/support/pages/node/540247/#SessionAffinity for the OIDC login flow.  I know that you are familiar with this, but it shows where the session cookie is established (step 3).  This cookie must exist and it must correspond to an entry in the OIDC session cache.  If neither of these conditions are true, the request is redirected to the OP.
    • On the requests that require SSO, your OP is redirecting to the TAI and it creates the cookie and session cache information to establish trust for the application. 
    • However, on the requests that do not require SSO, you are interrupting the OIDC flow between steps 2 and 3.  The session cookie and cache information are not created, therefore trust is not established with the TAI.
      I can think of three options:
      • Act as a real intermediary for the OP and return the OP data for SSO requests and your own data for non-SSO requests.  You would have to add a token endpoint and forward the requests intended for the real OP to the real OP and return your own data when the request is intended for you. 
      • Keep your own cache (or cookies) so that when requests are sent to your auth endpoint it knows if it needs to re-auth for non-SSO requests or not (just like the OIDC TAI does).
      • In your web app, for non-SSO authentications, obtain an OAuth token from the token endpoint of your OP (you can use OauthClientHelper).  Put this token on the Authorization header on the redirect back to your business endpoint (Bearer xxxx).  Down side: you will add 2 calls to the OP (yours to obtain the token and the TAIs to validate it).  Upside: you get the benefits of the TAI maintaining the sessions properly.  I would recommend this solution.
      Do not attempt to create and/or use the OIDC cookies yourself.  Those are implementation details that could change at any time.

      Good Luck!

      ------------------------------
      Barbara Jensen
      ------------------------------



    • 3.  RE: Authentication/authorization for users in two repositories (OpenID and standalone customer)

      Posted Mon October 31, 2022 06:51 AM
      Hello Barbara,

      for all the suggested options I need to implement at least the token endpoint in our application, and so play the OP role for the non-SSO users. In this case I had to manage ID-, access- and refresh-token and this is what I want to avoid. If I do this, we don't need a real OP provider at all.

      I have another idea, and wonder if this could work: If I configure the RP parameter:
      provider_<id>.useJwtFromRequest=ifPresent
      ... the OP is not used to authenticate the user, right? So If I add a JWT to the HTTP request header in the redirect to the protected application page after the successful login in the authentication endpoint of our application, it should work? I just wonder, which claims I must add to the JW, that the RP recognizes the group memberships of the user?

      Kind regards
      Thomas

      ------------------------------
      Thomas Mayr
      ------------------------------



    • 4.  RE: Authentication/authorization for users in two repositories (OpenID and standalone customer)

      Posted Mon October 31, 2022 10:31 AM
      Hi Thomas,

      When you set provider_(id).useJwtFromRequest=ifPresent, the JWT, if present, is locally validated for access.  If there is no JWT on the request, the normal OIDC RP flow takes over.

      The groups are in the groupIds claim.  If you want to put them in a different claim, set the provider_(id).groupIdentifier property to the name of the claim that contains the list of groups.




      ------------------------------
      Barbara Jensen
      ------------------------------



    • 5.  RE: Authentication/authorization for users in two repositories (OpenID and standalone customer)

      Posted Thu November 03, 2022 09:48 AM
      Hi Barbara,

      the JWT would be the solution of my problem. But when I set the JWT in the HTTP response it is not contained in the following HTTP request the browser is redirected to. I set the header parameter as follows:

      HttpServletResponse httpResponse = request.getResponse();
      httpResponse.setHeader("Authentication", createJWT(loginUsername, groupNames));​

      In Firefox I can see, that the header Parameter Authentication is set in the response:

      Authorization
      	eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJiQGIuZGUiLCJpc3MiOiJodHRwczovL29wZW5hbS50ZXN0LXNlcnZlci5hZzo4NDQzL29wZW5hbS9vYXV0aDIvS2lzc1JlYWxtIiwiaWF0IjoxNjY3NDY3OTg1LCJleHAiOjE2Njc1NTQzODUsImp0aSI6IjM4NjQ0MDFlLWI3MTItNDQ1My05MDhkLWQ2ZTgxMWJjZGU2MSIsImdyb3VwSWRzIjoiUm9sbGVfRWlnZW53b2hucmF1bUt1bmRlIn0.h2dSw0qRC_Gu1B1qNcIgdgH8YFm-_DmKhYP7Zji6_D3yRVmdhZ_dITjKZAQlHLCNeOGs0VM2wiA4GUwx6atkkQ

      But in the following request header this parameter is missing.

      What do I have to do to set this parameter in the following request headers?

      Kind regards
      Thomas



      ------------------------------
      Thomas Mayr
      ------------------------------



    • 6.  RE: Authentication/authorization for users in two repositories (OpenID and standalone customer)

      Posted Thu November 03, 2022 02:24 PM
      Hi Thomas,

      The format for how you send a JWT in the Authorization header is the same as for an opaque token that I mentioned in my first post: Bearer xxxx:

      HttpServletResponse httpResponse = request.getResponse();
      httpResponse.setHeader("Authentication", "Bearer "+createJWT(loginUsername, groupNames));​



      ------------------------------
      Barbara Jensen
      ------------------------------



    • 7.  RE: Authentication/authorization for users in two repositories (OpenID and standalone customer)

      Posted Mon November 07, 2022 05:15 AM
      Hi Barbara,

      I tried this without success. I also tried the header parameter Authorization, but the token is not added to the following requests. The browser should doe this, right? Is there a defined standard how to return these tokens, so that the browser recognizes them?

      Kind regards
      Thomas

      ------------------------------
      Thomas Mayr
      ------------------------------



    • 8.  RE: Authentication/authorization for users in two repositories (OpenID and standalone customer)

      Posted Mon November 07, 2022 11:57 AM
      Edited by Barbara Jensen Mon November 07, 2022 11:59 AM
      Hi Thomas,

      I apologize, yes, it is the Authorization header, not Authentication.  I get that wrong all the time.  I guess because I'm authenticating, not authorizing.  I'm sorry that I steered you wrong.

      First, if you don't already have it installed,  I want you to install OIDC 1.4.0.

      • Take an OIDC trace. 
      • The major highlights of the trace are denoted with ==>
      • Do you see your request being intercepted?  Check if isTargetInterceptor returns true
      • JWT authentication should happen in the AuthenticateUsingJWT method.
      • Do you see your JWT being returned from the getBearerAccessToken method?
      • If your request is intercepted, you entered AuthenticateUsingJWT, and your JWT is returned from getBearerAccessToken, follow the trace to find any additional errors that the TAI may have encountered.
      • If you get down to ==> OIDC: PROCESS COMPLETE (as opposed to ==> OIDC: THROWING EXCEPTION AND EXITING), then the problem is not with the TAI processing the request, but with core security not liking the Subject.  For instance, you might have to turn off registry mapping, set useRealm to the WAS_DEFAULT, or perhaps trust the inbound realm.

      ------------------------------
      Barbara Jensen
      ------------------------------