Id_token vs. access_token to propagate authentication


#1

I am using the OIDC flow with id_token for authentication. This is an server-side MVC app using Authorization Code flow.

Once a user is logged in, I want to propagate authentication context to microservices in the same application. Those services are accessed through HTTP endpoints, back-end to back-end.

What’s the best practice to solve this? The two alternatives I can think of are:

  • Pass the id_token itself in HTTP headers, and the recipient validates its signature and expiration.

    • Pros: convenient.
    • Cons: everything I’ve found on the topic (mostly for other products) says not to do this.
  • Pass the access_token in HTTP headers, and the recipient uses the access token to call the Okta /userinfo endpoint.

    • Pros: more consistent with standards.
    • Cons: not clear why this is better than passing the id_token itself. It feels awkward because breaking up my application into multiple microservices is an implementation decision internal to my app, not creating a concept of a “resource server”. And there is no concept of the user authorizing component A to call component B on their behalf; component B just needs to know which user is logged into component A.
  • Pass the access_token in HTTP headers. Recipient validates the token and gets claims off of it directly.

    • Pros: as convenient as id_token
    • Cons: not standards-compliant – OIDC spec does not require access tokens to be JWT; access tokens can be opaque.

#2

Hey @wrschneider,

From a very practical perspective, I think passing the access token is better, since you can always get the user info given the access token (but not the other way around). It does have the benefit of being more spec compliant as well. :slight_smile:

If the user info needed at your microservice layer is small (just the sub claim, for example), I think #3 would be the best choice. When you create a custom authorization server in Okta, you have a lot of control over which claims are included in access tokens, so you could ensure all your tokens have the info you need.

You’re right that the access tokens are not guaranteed to be JWTs. We don’t have any plans to switch our access tokens to opaque tokens, but even if we did, you could still make an introspection request to see the access token’s claims.


#3

If I’m going to validate and take claims off the access token directly, why is that better than using the ID token for the same? What would break, or what vulnerability would I create, if I used the ID token for that?


#4

hi @wrschneider, what option did you finally select? I have a very similar architecture as you described.


#5

I am going with id_token for authentication, access_token for authorization.

API that receives the access_token can obtain user information by validating the claims on the access_token directly via signature, or by calling Okta APIs with the access token.

The distinction is subtle and doing this mostly because access_token for API calls seems more standards-compliant, and does not make assumptions about how the user was authenticated. An id_token is coupled to an OIDC authentication flow.

However, from the client’s perspective, getting an access_token and id_token at the same time is a good reason to use OIDC flows for authentication vs. SAML.