1

We are currently implementing SSO within our organization, have have settled on using OpenId Connect for our authentication protocol (specifically using Gluu).

The problem we are running into is passing an identity, that we can prove has been authenticated, to a chain of backend services. I've seen people pass the id_token, but from what I understand that really isn't the intent of the id_token, but instead is only really meant for the initial client to consume.

Lets say we have an Angular Application calling a related REST service, which them call some sort of data service. Currently, the angular app will re-direct an unauthenticated user to Gluu for login, and provides the id_token and an access_token.

Gluu's implementation is to provide an opaque access_token. So when we pass that token from the Angular application to the REST service, we go back to Gluu to validate the token, pull user info associated with it (based on the scopes that were used with OpenId) and client info. This all works fine with the first hop.

The problem comes when connecting from the REST service to the data service. Using the client_credential flow, the REST service calls Gluu with the scope for the data service to get a new access token. However, I have found no way to exchange the original token, for a new token which preserves the original user claims.

I've seen advice where people say, "well you're within a trusted domain, so just pass the userid and trust that they have been authenticated." This will not work for us. We were using a HMAC scheme previously, and teams were passing around userids that had never been authenticated, impersonating users without their knowledge, which is why we need a way to ensure that the user has been authenticated.

I feel like I'm missing a piece of the puzzle here. What is the "right" way to do this?

aasukisuki
  • 1,186
  • 1
  • 11
  • 33
  • In the selection of access token or id_token, I'd say use the `id_token`. Correctly used with a list of intended audiences, and needed group/role info in the token (I don't know if gluu lets you configure that), and of course detached validation, there is nothing wrong with using id_token. It is a token that contains identity claims and can be passed on, and it should be possible to renew it with the OP. – fiddur Dec 08 '16 at 09:00
  • @fiddur thanks for the response. The problem with that approach is that the front end client may not (and probably should not) know what other services are involved downstream, so the audience wouldn't be set properly, unless we had some universal audience for internal apps... – aasukisuki Dec 08 '16 at 15:01
  • If REST Service connects to Data Service using Client_Creds flow then why you need to pass the userinfo to Data Service and if that needs to be passed for getting the data related to user or some similar then userID/userName are technically input to the query sent to Data Service in which case userID/Name should be passed as data to resource server (Data Service). Please tell me if I missed something – dvsakgec Dec 09 '16 at 09:59
  • Also, ID_token and access_token are different. – dvsakgec Dec 09 '16 at 10:00
  • @dvsakgec We're using the client credentials flow, so a client_id and client_secret get passed. None of these applications have access to the user's credentials (other than the IDP, Gluu), so even if we wanted to (which we don't) we can't use the resource owner flow to pass the user credentials along with the client credentials. Proof of user authentication needs to be passed into the data service to ensure that a) the user did actually delegate access to this process, and b) that the user should actually have access to read/write that data (or subsets of) – aasukisuki Dec 09 '16 at 17:04
  • @aasukisuki, then in this case, firstly on Rest Server you cannot exchange the Client_Creds token to get a new token from Authz Server as your Rest Service Authz flows do not involve user authentication. The problem here is that you want every application in chain to be aware of authentication being done which is not required actually – dvsakgec Dec 10 '16 at 20:56
  • But if you still want and want to keep it simple then introduce custom header which every application of yours support and pass the token in that header and let every application individually verify the token – dvsakgec Dec 10 '16 at 21:00
  • Last option is, If Gluu support this then you can use a symmetric key in all applications put in some wallet/keystore and use that symmetric key in every application to verify the token, if decryption of token succeeds and token is not expired then it is good to go and Use custom header for throwing the token around. – dvsakgec Dec 10 '16 at 21:04

1 Answers1

0

Please do not pass the id_token. The OpenID Connect specification states that the id_token is for use in the client application. I have seen this problem solved in two ways

  1. Require the client application to request all required downstream scopes so their access token works for all services and the audience contains the correct services. This may not be possible in your situation but I would say this would be the easiest (maybe not the best) approach.

  2. I don't know anything about GLUU but the OAuth 2.0 specification talks about extension grants which could be useful in your situation. This just means that per the specification you can define your own grant other than 'code', 'password' and 'implicit'. I am suggesting you implement a custom grant. You can define a custom piece of information for authenticating users. There is another OAuth 2.0/OpenID Connect framework called IdentityServer that I work with. Even though it's not GLUU I think you will be able to follow this article about extension grants because at the end of the day GLUU and IdentityServer are following a well defined protocol. The article shows how extension grants can solve your specific problem of delegating authentication properly. Have a look here. It's my hope that you can implement something similar with GLUU.

Community
  • 1
  • 1
Rob L
  • 3,073
  • 6
  • 31
  • 61