Userinfo and external OIDC provider


#1

Hi,

There is one thing (at least :wink: ) I still fail to understand. Where the information provided by the userinfo endpoint is supposed to come from?

I integrate Hydra with an OIDC-capable IdP by using my login provider implementation. So the OIDC flow is actually executed between the end user, IdP and the login provider, which ultimately receives the authentication token (ID_TOKEN), validates it using whatever means it wants and then just calls Hydra’s “accept a login request” endpoint. And when calling this endpoint, the only thing I can provide is the identity of the user I have just successfully authenticated. There seems to be no way to pass any other claims from the original ID_TOKEN. So, the consent provider won’t have any of this information to add it to its “accept a consent request”.

So, what I fail to understand - is there a way to “bridge” the ID_TOKEN (selected claims) received from an external IdP somehow? So it would be available from the userinfo endpoint, for example.


#2

Information from userinfo is currently being mirrored from the session.id_token payload. You can also override the userinfo endpoint using a configuration setting: https://github.com/ory/hydra/blob/master/docs/config.yaml#L265


#3

Yes, I was aware of this “session” property - but it is only available for the consent acceptance request. And I was assuming that it is the responsibility of the login provider to deal with the user authentication - thus, the 3rd party ID_TOKEN would be only available to the login provider.

Implementing my own userinfo endpoint would mean a stateful application, which seems to be an overkill since Hydra already has the required functionality…

So, in brief, I am looking for the reference design of a system where Hydra is integrated with an external IdP using OIDC. I have a prototype working but I am having troubles to figure out the best way to somehow make the detailed identity information (claims from the ID_TOKEN) to the application.

It appears that there should be a way to carry more information from the login provider to the consent provider but I am not sure what is the best one.


#4

Oh I see, you want to forward the claims from the upstream IDP ID Token to the ID Token issued by Hydra? There’s actually an issue for that: https://github.com/ory/hydra/issues/1003


#5

Yes, thanks for pointing to this issue, I will watch it. And now I understand where session_id and login_challenge_id are coming from. Yes, basically, I was thinking about the use case like this:

  • I develop an API, it does store some personalized data based on the identity of the calling resource owner
  • I also develop an app that uses this API and allows the user to log in
  • I use an external identity provider, e.g. something like Azure AD Connect (via OIDC)
  • I also understand that OAuth2 is not a good way to implement any kind of authentication. I also understand that from the authentication point of view, the only thing I can rely on, is the fixed subject identifier+authentication “issuer”. This is the “primary key” for the user “profile” in my own system. I understand the difference between my user and Azure AD user.
  • Considering the previous point, just the subject value may not be enough in case of multiple IdPs used. I want to make sure that the users from different IdPs never clash. Currently I am thinking about generating my subject value by prefixing it with an ID/URL of the ID_TOKEN issuer.

So, technically, the challenge here is mostly about initializing this profile with email/first/last name/etc - the information from the ID_TOKEN I get from Azure AD Connect. So the app could use this information to initialize its own profile.

In the systems like Keycloak, where IdP and OAuth2 server are both implemented by one product this sounds more obvious, I think. But I really like the idea of the system where the API Gateway (like Ambassador) essentially “terminates” OAuth2 bearer token and the API (micro)services only get some relevant claims in form of HTTP headers. This makes even OAuth2 server replaceable - to certain extent, of course. Then, I like Hydra because it is a small and fast OAuth2 server that may be just enough for some use cases, like client credentials grant, for example (service-to-service, B2B-type integration). And I like the idea of having my login provider relying on real OIDC ones. This way I have completely replaceable/pluggable IdP implementation, somewhat replaceable OAuth2 server and totally authorization-agnostic backend.

I was thinking about how to pass the ID_TOKEN from the login provider to the consent provider and saw these options:

  • shared in-memory DB or cache, I need very small amount of data for a very limited time
  • session cookie (would have to still mix in the login challenge)
  • an argument/query parameters added to the final redirect from the login provider - but that would require support from Hydra

Only the first option allows to avoid extra trips for the ID_TOKEN but it requires statefulness from my, otherwise stateless, login/consent providers.