ID Token and Access Token: What Is the Difference?

“Let’s use a token to secure this API call. Should I use the ID token or the access token? :thinking: The ID token looks nicer to me. After all, if I know who the user is, I can make better authorization decisions, right?”
Read more…

:writing_hand:t2: Brought to you by @andrea.chiarelli

2 Likes

What are you thoughts folks? Did you know the difference between both? Did you use it before?
Share in comments!

Hey, is something still unclear between ID and access tokens? Let me know!

1 Like

This is a really great infographic, and I like how you don’t just explain how to use them, but also how not to use them!

However, I would disagree that “you can’t make any assumption about the user’s identity” from an access token.

The infographic’s example access token shows a token issued by Auth0 with a client ID subject (sub) and client_credentials grant, meaning not only was an app authorized, it was also an app that did the authenticating! If this was a user-based flow, and the user (resource owner) has delegated their access to a particular application, that required a user authentication in order to authorize that app. I point this out to show that there is still very much a sense in which an access token does encode “authentication” information, because a client credentials flow, by OAuth2 definition, has a resource owner, such as you would get from the access_token’s “sub” claim (or, in the case of opaque tokens, somehow determinable by the resource server) because the resource server needs to know whose resources are being accessed. Of course, some APIs are entirely administrative, everything is specified by URL, and you don’t care about resource owners … but that’s not all APIs.

To quote Auth0’s own On The Nature of OAuth2’s Scopes, “a scope cannot allow an application to do more than what the user can do”—meaning knowing the user associated with the access token is (usually) pretty important!

(And in fact, Auth0’s extensibility is also super-helpful here, because we can add extra claims about that user/resource-owner … like an email address or employee identifier—to the access token. :wink: )

1 Like

Hey @emsearcy, thank you so much for your insightful comment. Actually, you’re right. That sentence is not well expressed :slight_smile:. I will change it.
Thanks again!

I am not sure if the sentence “do not send ID tokens to an API” is correct in every case.
What should I do if my resource server needs an authenticated identity (e.g. for logging?). Then I need an ID token … would I have to provide both tokens in this case?

Of course, everyone can do what they think is right :wink:
In a first-party scenario, you can choose to send an ID token to call an API, albeit with some potential risk.
In a third-party or delegated authorization scenario (the one for which OAuth was originally born), this is strongly discouraged for several reasons that I tried to explain in the article. Among these reasons:

  • the ID token does not contain authorization information (scopes) about what the application can do on behalf of the user
  • the user has not given consent to the application to use the ID token for that purpose

If your API needs the user’s information to make authorization decisions, your access token should provide it. For example, if your access token is in JWT format, you can provide additional claims.
After all, this is the reason behind the JWT Profile for OAuth 2.0 Access Tokens specification.

2 Likes

I really appreciate how simple you’ve tried to make this, how careful you’ve been with your words. And yet… it’s still not clear to me, and the problem boils down to the question of what is an API?
Your first diagram that illustrates the scenario for using an id token shows a browser and a “web application”. What if the architecture of the application is browser-centric, whereby all rendering is performed browser-side, using results from API calls? This is a common architecture, right? I don’t understand why, in this case, I should use access tokens to call the API, but if I had a more traditional (old-fashioned) app architecture, where the browser-to-server communication is not adorned with the formality of RESTfulness but instead just does GETs and POSTs in more raw style, identity tokens are the right solution.

Hello @leotohill,
Thank you for joining Auth0 Community and appreciating my article.
Let me try to solve your remaining doubts :slight_smile:

The first diagram is not telling to use ID tokens to call an API when the architecture of your application is a traditional old-fashioned web application.
Sorry if this is what it conveyed to you. Maybe I need to improve its readability.

The two diagrams refer to two different scenarios.
The first one is about authentication; the second one is about authorization.
In the first case, you need an ID token; in the second case, you need an access token.
I hope the reason why you need a certain type of token for each scenario is clear from the article.

Does this help to clarify?

Thanks for your reply. I understand that the first diagram indicates that I should use Id Tokens for a traditional old fashioned web app, and the second indicates that I should use Access Tokens for APIs.

What I don’t understand is why. What is the nature of a traditional web app that makes Id Tokens suitable for it, while APIs do not have that nature? If I refactor my web app so that is now API-centric, why is an identity token now unsuitable?

I understand that the first diagram indicates that I should use Id Tokens for a traditional old fashioned web app, and the second indicates that I should use Access Tokens for APIs.

Just to point out, the first diagram indicates that you should use Id Tokens for a traditional old-fashioned web app to get user information after authentication.
The second diagram indicates that you should use Access Tokens for being authorized to access APIs.
Two different goals!

The choice of a traditional web application in the first diagram is just for simplicity, to focus on a specific architecture avoiding discussing the different OIDC flows in the presence of different application types. The focus of this article is on the ID and access tokens, not the OIDC/OAuth2 flows.

That said, I hope I’ve caught the confusing point now and will try to clarify in the following.

What I don’t understand is why. What is the nature of a traditional web app that makes Id Tokens suitable for it, while APIs do not have that nature? If I refactor my web app so that is now API-centric, why is an identity token now unsuitable?

Before answering your question, I have to make a small digression.
OAuth2 is for delegated authorization, i.e., authorizing a third-party application to access a resource on behalf of a user. In the context of delegated authorization, you have three actors:

  • Actor 1: the user, the entity that wants to perform an action on an object.
  • Actor 2: the resource, the object that a user wants to use.
  • Actor 3: the application or client, the software that mediates the interaction between the user and the resource.

In this context, the API in the second diagram represents a resource (or a resource wrapper), i.e., Actor 2.
Both the web application in the first diagram and the client app in the second diagram represent the client, i.e., Actor 3.

So, in a delegated authorization scenario, the web application and the API depicted in those diagrams have different roles.

If you refactor a traditional web application into a SPA and an API, your SPA+API bundle doesn’t automatically generate a delegated authorization scenario. You can still consider your SPA+API application like a single application.
This scenario is known as a first-party authorization scenario. In this scenario, you can decide to use the ID token to call your own API, as the article explicitly tells:

In a first-party scenario, i.e. in a scenario where the client and the API are both controlled by you, you may decide that your ID token is good to make authorization decisions: maybe all you need to know is the user identity.

There are still some potential issues, but you can do it until you open your API to third-party clients.

Sorry for the length of the reply. Does it answer your question?

Thanks for the detailed reply. I’m developing some understanding of and appreciation for your points.

I see that the crucial point is that the access token is meant to carry authorization information, while the id token is not. However, applications may have their own authorization mechanisms that were built independently of an OAuth framework, and so have no need of the Oauth scopes and other attributes that could be inserted into the token. All they need is identity. I note your argument that sender constraints are meant to be used with access tokens not identity tokens, though this would not seem to be the case with the MTLS approach, which is entire independent of tokens. I don’t know enough about dpop.

Thanks again.

1 Like

@andrea.chiarelli I understand the role of the id_token in a legacy web application, where it might be used to establish a server side session for the user so that they are “authenticated”. However, in many modern applications, the application is just UI in front of a collection of resources (often ReST based). In this case there is no session; a user is “logged in” if they can expect to make a call to a ReST endpoint and get a valid response. And as you stated, an access token should be used to access resources. What role does the ID token play in this scenario?

Similarly, in the classic OAuth2 scenario (even the example that you used), a resource owner grants one backend application (linked in) access to resources in another backend application (twitter). The OAuth2 client may access resources in the Resource Server even if the Resource Owner is no longer “logged in” to either application. But in the modern application that I describe above, the client may be a SPA and the Resource Server is the ReST API, and both are owned by the same company and part of the same product (unlike your example). In this case, as the developer of the application, if I use Oauth2/OIDC to authenticate and authorize my application, then I don’t expect the authorization to be a long term grant (unlike the linkedin->twitter example). I generally expect the access token to have a lifetime similar to the shorter lifetime of the id token. Is an OAuth2 access token different than an OIDC access token or is this just a matter of different settings for the expiration?

Hi @daniel.l.christensen, welcome to the Auth0 community!

Thank you for reading my article and submitting your doubts.
Let me summarize your first question: “What role does the ID token play in a SPA-based scenario?

It has the same role as in a regular web application: it states that the user has been authenticated.
If requested, you can have the user’s data in the token.
Please, don’t confuse receiving an ID token with creating a session. As the application developer, you have the responsibility to create your own application session (cookie-based or other). The ID token is simply the result of the authentication process, nothing more.
I described the regular web application scenario in the article for simplicity, but the role of the ID token is always the same.

Your second question: “Is an OAuth2 access token different than an OIDC access token or is this just a matter of different settings for the expiration?

OIDC access tokens are OAuth2 access tokens. OIDC is built on top of OAuth2. You can consider it a sort of OAuth2 extension.
The length of your access token lifetime depends on its potential exposure to the risk of being stolen.
In a scenario where a backend application (e.g., LinkedIn) calls another backend application (e.g., Twitter API) on behalf of the user, the risk of access token theft is lower than in a scenario where a public client (e.g., a SPA or a mobile app) calls an API.
While you have control over the environment where a backend application runs, you have no control over the environment where a public client runs. So, to minimize the risk that a valid access token is stolen on a public client, you reduce the token lifetime as a security measure.
In summary, an OIDC access token is nothing but an OAuth2 access token. Setting the length of its lifetime is just a security measure depending on the scenario in which the OAuth2 client runs.

I hope I have answered your questions.

Hi, when adding custom claims to a user, the claims will be included in the access token only. I could not find a way to add these claims to the ID token. In that case, I think the client should inspect the access token instead the id token to get user’s info. Am I missing anything?

Hi @thai,
Welcome to the Auth0 Community! :wave:

Auth0 allows you to add custom claims to ID tokens as well as access tokens.
Check out this document and this blog post to learn more.

1 Like

Good explanation but…
As a developer that uses UI to login my users to my web app I don’t see how this article helps me to define a relying party that checks both authentication and authorization in case I have API’s in my web app.
Also do I must to protect each resource in my IDP side? must the IDP know every API I uses?
We understand that developrs are confsed but do you offer as a solution?

Hi @yaron.relevy,
Thank you for joining the Auth0 Community and asking your question.

If I correctly understand, your question is about calling your own API, not a third-party one, right?

In my opinion, you have two options:

  • stick with the standards (OIDC and OAuth) and deal with your first-party API as if it were a third-party API.
  • Implement your own authorization mechanism.

Actually, you may be tempted by a third option, which mixes the previous two, i.e., attempting to use the standards in a not proper way.
The point is that if you want to use a standard framework like OIDC and OAuth, you should stick with it and with its prescriptions. But OAuth was designed for accessing third-party APIs. If you want to use it in a first-party scenario, you may feel things redundant (access tokens? scopes?) and you may attempt to change the initial meaning and scope of an artifact (e.g., using an ID token for authorization purposes). Actually, you are customizing the standard for your own needs, so you have to take care of the many aspects that may arise from the not proper use of the standard, security in the first place.

Regarding the other questions, “do I must to protect each resource in my IDP side? must the IDP know every API I uses?”, again, it depends on your needs.
You are not obligated to protect each resource with an IDP if you don’t want. You may use just OIDC for authentication and build your own authorization mechanism. In the end, it’s a matter of convenience in terms of the infrastructure you need to set up, the code you need to write, the time you want to invest in building what you need.

I hope this helps.

I am still really confused as to why most tutorials say the ID JWT is used for authorisation? At the last two companies I worked for, after a client app (react) authenticated a user the JWT was then passed back as the bearer token to all API calls to authorise the user requests.

After reading the article it seems this is incorrect? If the API is still owned by the intended audience is this OK?

Both solutions used a corporate identity provider for single sign on.

Hi @paulalex,
Welcome to the Auth0 Community! :wave:

Before replying to your questions, I want to clarify one thing: the article is about using ID and access tokens in the OpenID Connect and OAuth2 context.

You mentioned an “ID JWT”. I don’t know if you mean a generic JWT, that is, a generic token in JWT format, or an ID token issued by an OIDC provider.

In the first case, you can use it as you prefer. It’s your own artifact, and maybe you have your own flow to grant security.

In the second case, i.e., you are using an ID token issued by an OIDC/OAuth authorization server, you should stick with the standard, and hence, with the purpose those artifacts are meant for.

You are free to ignore the standard’s recommendations, of course :slightly_smiling_face:
There are companies that use ID tokens to call their own API (first-party scenario).

This is actually a sort of customization of the standards for their own needs. That means that some of the standard’s recommendations to grant security might not be valid.
In the case of using an ID token to call an API instead of an access token, the article outlines some of the problems that can arise.

To summarize it with a funny image, stairs were not invented to be used with skates.
Sure, you can try to go down the stairs with skates, but don’t be mad at them if you fall down. :slightly_smiling_face:
To go down the stairs with skates, you may have to modify them a little. But at that point, they are no longer "standard" stairs.

I hope this clarifies a bit.