Clarification on id_token vs access_token
Asked Answered
F

6

60

I'm building a system with OIDC and OAuth 2.0 (using Auth0), and I'm unsure how to properly use the id_token and access_token. Or rather, I'm confused about which roles to assign to the various services in my setup.

I have a fully static frontend-application (single-page app, HTML + JS, no backend) that ensures that the user is authenticated using the implicit flow against Auth0. The frontend-application then fetches data from an API that I am also building.

Now, which is right?

  • The frontend SPA is the OAuth client application
  • My API service is an OAuth resource server

...or:

  • The frontend and my API service are both the client application

If both my frontend and backend API can be considered to be the client, I see no real harm in using the id_token as the bearer token on requests from my frontend to my backend - this is appealing because then I can simply verify the signed token on the backend, and I have all the information about the user that I need. However, if my API is considered a resource server, I should probably use the access_token, but then I have to connect to Auth0's servers on every API request to both verify the token, and get basic user info, won't I?

I've read this which seems to suggest that the access_token is the only valid token for use with my API. But like I said, I'm not sure about the roles of the individual services. And using the id_token is tempting, because it requires no network connections on the backend, and contains information I need to extract the right data.

What is the right way to go about this?

Ferreira answered 11/10, 2017 at 7:7 Comment(6)
I got really solid input on this over at the Auth0 forums: community.auth0.com/questions/10010/…Ferreira
Consider converting that forum response to an answer here, and it would help others of us in the same boat :-)Powerless
The alternative view is also valid, IMO. Imagine you log into your application using your Google account. You get an id_token and an access_token. It's obvious you use the id_token for authentication to your app and the access_token to call Google APIs. The ID token only proves you're logged in; it does not allow your app to call Google APIs on your behalf. On the other hand, API services within "your app" have not been explicitly authorized separately as a resource server - they are equally part of "your app" whether they are accessed over HTTP or local method callsGabo
But the spec explicitly states that the id_token must be verified: (openid.net/specs/openid-connect-implicit-1_0.html#ImplicitFlow) 2.1. Implicit Flow ** 6 Client validates the tokens and retrieves the End-User's Subject Identifier.**Apostolic
So in short: how can this validation of a signed token occur in the frontend?Apostolic
@ChristianJohansen, your I've read this link in your OP is 404'ed. Is there an updated page you know about?Platitudinize
G
16

I like this Medium post about the difference, all cred to this author.

https://medium.com/@nilasini/id-token-vs-access-token-17e7dd622084

If you are using Azure AD B2C like I am you can read more here:

https://learn.microsoft.com/en-us/azure/active-directory-b2c/openid-connect

ID Token

You will get id token if you are using scope as openid. Id token is specific to openid scope. With openid scope you can get both id token and access token.

The primary extension that OpenID Connect makes to OAuth 2.0 to enable End-Users to be Authenticated is the ID Token data structure. The ID Token is a security token that contains Claims(claims are name/value pairs that contain information about a user) about the Authentication of an End-User by an Authorization Server when using a Client, and potentially other requested Claims. The ID Token is represented as a JSON Web Token (JWT)

{
   "iss": "https://server.example.com",
   "sub": "24400320",
   "aud": "s6BhdRkqt3",
   "nonce": "n-0S6_WzA2Mj",
   "exp": 1311281970,
   "iat": 1311280970,
   "auth_time": 1311280969,
   "acr": "urn:mace:incommon:iap:silver"
}

The above is default JWT claims, in addition to that, if you requested claims from service provider then you will get those as well.

An id_token is a JWT, per the OIDC Specification. This means that:

  • identity information about the user is encoded right into the token and
  • the token can be definitively verified to prove that it hasn't been tampered with.

There's a set of rules in the specification for validating an id_token. Among the claims encoded in the id_token is an expiration (exp), which must be honored as part of the validation process. Additionally, the signature section of JWT is used in concert with a key to validate that the entire JWT has not been tampered with in any way.

Access Tokens

Access tokens are used as bearer tokens. A bearer token means that the bearer (who hold the access token) can access authorized resources without further identification. Because of this, it's important that bearer tokens are protected. If I can somehow get ahold of and "bear" your access token, I can pretend as you.

These tokens usually have a short lifespan (dictated by its expiration) for improved security. That is, when the access token expires, the user must authenticate again to get a new access token limiting the exposure of the fact that it's a bearer token.

Although not mandated by the OIDC spec, Okta uses JWTs for access tokens as (among other things) the expiration is built right into the token.

OIDC specifies a /userinfo endpoint that returns identity information and must be protected. Presenting the access token makes the endpoint accessible.

http://openid.net/specs/openid-connect-core-1_0.html https://connect2id.com/learn/openid-connect#cool-id-token-uses https://developer.okta.com/blog/2017/07/25/oidc-primer-part-1

Grade answered 15/10, 2020 at 14:6 Comment(0)
P
5

Your frontent is your OAuth client application, once it stores the token it can take actions on the OAuth flow. And your API service is resource server, because it accepts the access_token issued by your identity server.

Also I would say that your id_token stands for the identification of the logged user and may contain sensitive data for your app. The access_token is standing as your credential to access a resource.

At the end you will use an access_token to request a resource, and then if you need specific data from the logged in user (resource owner), you may request the ID token from the token endpoint.

Peppie answered 22/11, 2017 at 14:5 Comment(0)
N
2

In my opinion, the first approach is correct. Your SPA is the client application and your APIs are resource servers.

I would suggest you limit the use of id_token till your SPA only. You can use the basic information present in the id token (like username and email) to display user information within your UI. If you can generate access tokens as JWTs too then your API can validate the access tokens without going to the Identity provider. You can include roles (or similar) in your access token to get authorization information in your access token.

Nahum answered 16/3, 2018 at 5:49 Comment(0)
T
0

I was also wondering if I need to talk to the IdP on every request if I'm using the tokens received from the IdP. I ended up with the following setup:

  • Only the backend talks to the IdP, the frontend does not.
  • Upon the IdP callback the backend issues a JWT for the frontend.
  • User session and frontend-backend communication is managed entirely by my app using the JWT token.

Check this article: OAuth2 in NestJS for Social Login (Google, Facebook, Twitter, etc)

and this repo: https://github.com/thisismydesign/nestjs-starter

and this question: OAuth2 flow in full-stack NestJS application

Torch answered 18/6, 2021 at 14:51 Comment(0)
C
0

The id_token is an cryptographically encoded token for authentication. The OP (the auth provider) is the one that generates it and the RP (relying party or the resource) will eventually re-present the token to the OP to counter validate when handed over by the client. In short the id_token is tied to authn workflow.

The access_token enables resource access. It does subsume the userinfo i.e., the id_token or any other principal on whose behalf the access is being requested. So this token includes both user claims plus claims to groups that are authorized. In short the access_token is tied to your authz workflow.

Condemn answered 10/1, 2022 at 3:6 Comment(0)
G
0

ID tokens

1. ID token is a signed JSON Web Token given to the client application

2. ID token contains a set of claims about the authentication session

3. identifier for the user (sub)

4. the identifier for the identity provider that issued the token (iss)

5. identifier of the client for which this token was created (aud)

6. information about the token’s own validity time window (with the exp and iat claims)

7. information about the authentication context to be conveyed to the client

8. the token can say how long ago the user was presented with a primary authentication mechanism (auth_time)

9. what kind of primary authentication they used at the IdP (acr).

10.

Reason for ID Token.

1. The two-token approach allows the access token to remain opaque to the client as in regular OAuth while allowing the ID token be parsed.

2. ID token often expiring more quickly, represents a single authentication event and never passed to an external service.

Genethlialogy answered 1/7 at 11:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.