ID Token and Access Token: What Is the Difference?

I get this

there is no mechanism that ties the ID token to the client-API channel

But is there any such mechanism in the Access Token that allows me to use it to when sending requests from my frontend (React Web App) to my backend? Or should Access Tokens only be used between backends? If so, how will my backend ever know that I successfully sign in with (e.g.) Auth0/Google/Github or other IdP?

Hey @Wik,
Welcome to the Auth0 Community! :wave:

Let me try to answer your questions and clarify a bit.

is there any such mechanism in the Access Token that allows me to use it to when sending requests from my frontend (React Web App) to my backend?

If you are referring to mechanisms that bind an access token to the client-API channel, they do exist. They are mentioned in the article and are known as sender constraint.

Or should Access Tokens only be used between backends?

Absolutely no! Access tokens can be used by a frontend to call a backend.

If so, how will my backend ever know that I successfully sign in with (e.g.) Auth0/Google/Github or other IdP?

Not sure I understand correctly.
If your need is for your backend to know if the user is still logged in, you can do that with traditional cookies.
If you need to know which specific IdP the user has authenticated with, the frontend can send this information to the backend by extracting it from the ID token (issuer claim).

I hope I helped clear up your doubts.

1 Like

@andrea.chiarelli,

Thanks for this awesome and clear article. The video clarifies a lot too! :pray:

I noticed in this comment section you and @daniel.l.christensen talking about “OIDC access tokens”. I would be careful using names like that. The spec does not contains “OIDC access token”.

It is ID token for OIDC
and access token for OAuth, correct?

It’s even in your infographic. IMHO “OIDC access token” doesn’t make sense.

Hi @runforrestrun,
Welcome to the Auth0 Community and thank you for your note.

You are right: the OIDC specs don’t include a definition of OIDC access token.
Actually, that term came from the reader I was replying to.
I used their own term to conclude that what they called “an OIDC access token is nothing but an OAuth2 access token”.

It’s even in your infographic. IMHO “OIDC access token” doesn’t make sense.

Where do you see this reference in the infographic? :thinking:
I can’t see it. It explicitly references to OIDC for the ID token and OAuth2 for the access token, as far as I can see.

1 Like

@andrea.chiarelli

Thank you for your quick reply and conformation. Much appreciated. :pray:

The previous statement had to be written like:

It’s even in your infographic: It is ID token for OIDC and access token for OAuth, correct?

My bad by messing up the sentence.

1 Like

ok if i use azure ad, azure bdc.

i have a angular application with a spring boot backend.

If i want user can modify only his information to the backend?

If user is 1234
if it’s call /users/{userId}
with 4567.

On the backend side, we need to check if 4567 is really the id of the user. So id token need to be pass to the backend?

If you do your authentication on the backend with Spring Boot, you’ll have the user’s information available. In fact, you can inject this information into a method using the following parameter:

@AuthenticationPrincipal OAuth2User user

See Build a Beautiful CRUD App with Spring Boot and Angular for more information on this architecture.

1 Like

Generally speaking, regardless of the specific technology, the authorization decisions of your application should be based on the information defined by your authorization model.
This information can come from a variety of sources (access token, database, runtime environment, etc.)
If you rely on the access token, it should allow you to retrieve the information you need (the user ID, in your case). For example, JWT access tokens issued by Auth0 include the user ID (sub claim).
More in general, if you need other information to make your authorization decisions, you can enrich the access token with custom claims by using Auth0 Actions.

1 Like

Hi,
thanks for the article. I still find one thing pretty confusing (and I hope it hasn’t been addressed earlier, I tried to scan all posts in this thread :wink:

I keep getting confused what scopes in the access token express. You wrote in the last diagram, “Access Token DOs: check if the client is allowed to access something”

Isn’t that actually wrong?

Shouldn’t it rather be: “First, check if the scope of the access token actually allows access to that resource, and only if it does, you need to do the real check if the user on whose behalf you are accessing the resource actually has the right”?

Otherwise, users could let the auth server issue tokens that allow access to any data of any user, but that shouldn’t let the resource server return this data, right?

Like, if in the access token only has the scope “email:read”, then accessing a resource to write e-mails would already fail because the scope “email:write” is not included, but trying to read an e-mail would not fail immediately because the scope is right, but then you would still have to figure out (without the token) if the user actually has access to that specific mail (e.g. is this mail one of theirs or does it belong to a different user, or has the right to read their own mails been revoked from this account for whatever reason)

And this is where I’m getting to an architectural question, if I manage roles in auth0, I would like them to be included in the access token so I can make those decisions without doing other API calls, would it mean that I have a token that has both a roles section (that I can trust to be valid) and a scope section that limits which permissions attached to the roles I can use?

So I would first read out the scopes to see if the call is valid at all, and then rely on the roles in the token to decide if the permission is there or not?

Hey @BernhardBln,
Welcome to the Auth0 Community!

There’s a lot of stuff here. Let’s go through them one at a time.

The diagram summarizes what is explained in the article and, as you can imagine, summarizing things is hard. Actually, the article barely mentions scopes. This is a more detailed article on scopes and related concepts.
You are right about the process of first checking the application’s scopes and then checking the user’s permissions (or better, privileges). The diagram’s summary focuses only on the final effect, not the process: determining whether or not the client is allowed to access a resource.

Related to the role question, you can add roles and even permissions to your access token using Actions. See this for more info. If your application is an API, you can configure it to include permissions in the access token.
In other words, you can have the following in your access token:

  • application’s scopes (what the application wants to do)
  • user permissions (what the user can do)
  • user roles (collection of permissions or other criteria)

Your access control component can use all this information to make its authorization decisions.

Note: If in your authorization model “role” == “collection of permissions”, having roles in the access token will probably not add any more info. You can just rely on permissions, but that is another story.

1 Like

First, thank you for your excellent article @andrea.chiarelli and for taking the time to answer people in the comment section. This section is really a gold mine.
So my question is why you use the term “JWT access token” while your colleague Randall Degges spent almost an hour taking shots at this practice ( which by the way was very convincing)?
After reading a lot of materials, I can’t find out the benefits of JWT’s beside ( quoted from your article) :

Your application can personalize the user’s experience by using the claims about the user that are included in the ID token

Even if it proves to the client app that the user is authenticated, it is really the access token that’s the most important whether we are in a First party scenario or a delegation one, because most of the time the main purpose is to access protected resources.

Cool, so it would actually be considered a good practise to include both scopes and permissions in the same token and check them against each other.

Nice, thank you for your time to reply to all the questions :heart:

1 Like

Just one last caveat, @BernhardBln: a good practice also depends on the context.
If in your case it’s acceptable to have the user’s permissions in the access token (e.g. in your context, user permissions don’t change frequently), this can be considered a good practice. But if in your context user permissions change very frequently or you absolutely don’t want to risk that a user has a permission revoked but the access token has not expired, then that’s not a good practice.

1 Like

Hey @farouk.a.ellouze,
Welcome to the Auth0 Community!

Thank you so much for appreciating my article and for reaching out to me with your feedback.
My take on technology controversies is that there is no perfect technology. You can choose one or the other based on many criteria: from personal preference to reasoned argument. But the most important criterion is the context.

A technology may be appropriate in some contexts but not in others, of course. It depends on your requirements and in the trade-offs you are willing to make in building your app (again, there is no perfect technology).

JWT is a standard format. Just a data format. In the context of OIDC, the standard chose this format to communicate that a user has been authenticated. If you want to use OIDC in your applications, you need to use JWT.

For access tokens, JWT is an optional format. If you implement your own authorization server, you don’t have to choose it.
If you use JWT for your access tokens, you should be aware of its benefits and drawbacks, as it happens with any technology.

That said, I think that there are contexts where it makes sense to use JWT access tokens. For example, applications where the authorization criteria are pretty simple and don’t change often. By using JWT instead of an opaque token, your application does not have to make additional requests to find out what permissions, roles a user has, or other info you might need to make your authorization decisions.
Of course, this doesn’t apply to every scenario.
IMO, the pros and cons of the JWT format for access tokens are pretty similar to those for data caching. Whether they fit your application needs is up to you.
Does it make sense?

Hi @andrea.chiarelli
Thanks for the article, it was very entertaining to read. On the other hand, I have a certain doubt that I hope you can help me clarify.

Let me put you in context, I have created my own authorization server and resource server (both in Spring Boot) and my client is being developed in Angular. Users have their roles (SUPER_ADMIN, ADMIN, USER, etc.) my question is how do I determine in my Angular application the html views to show according to the user role, because in your article you mention that “the access token should not be inspected by the client application. It is destined to the resource server” and precisely my access token contains the roles in a custom way or should I place those roles in the identification token, but according to your article “the identification token will not have scopes granted, those scopes are associated with the access token”, so how could I work in that case, that is my doubt, I hope I have been able to explain. I would be very grateful if you could clarify the doubt. Thank you very much. :blush:

Hi @magadiflo,
Welcome to the Auth0 Community!

Glad that you appreciated my article, and I hope I can clear up your doubts.

In an SPA + API scenario, the user’s resources (the resources that you must protect) live on the API side. Your authorization decisions need to be made on that side. Therefore, your access token should contain the relevant info for your authorization decisions.

On the SPA side, you do not make real authorization decisions. You just manage the UI of your application to provide a good user experience. You can decide to show certain views to specific categories of users based on roles or other information. In this case, you can put this info in your ID token. In Auth0, you can add roles to your ID token through Actions, for example.
But keep in mind that anyone can bypass the checks you make on the client side. The client-side controls are there for UI management reasons. These checks also need to be be mirrored on the server side, where the real access control happens.

In summary, any extra info you add to the ID token (such as roles) has the purpose to improve the user experience, not to make real access control to the user’s resources.

1 Like

I am glad to have received your reply, now the picture is clearer. Thank you very much for your time. Greetings from Peru.

1 Like

ok but it’s done on the frond end?

Hey, thanks for the article. I have a question about ID vs. access token in the context of token exchange. I have a SSO scenario where a client SPA web app is going through the OIDC Authorization Code flow with a 3rd party provider, such as auth0, getting back access and ID tokens. I need to take those tokens and on my backend exchange them for an access token generated for the client to access another API. To do this securely I need to verify the user has a valid token from the expected issuer to the expected client, and to identify the user.

I can get all of this from the ID token by verifying the signature, iat, exp, iss, aud, and sub claims. So for this token exchange scenario is it sufficient to rely solely on the ID token?

Hi @dieseldjango,
The architecture you describe seems to have some unclear points.

First, as explained in the article, formally the token ID is intended for the SPA client and should not be sent to the backend.

Second, it is not clear to me if you are implementing the token exchange in your backend (i.e., your backend issues the token for the the external API) or if the backend is connecting to a second authorization server to exchange the access token.

In the first case, if your backend implements token exchange, it is not clear to me why. It seems that your backend acts as an authorization server for another API (“To do this securely I need to verify the user has a valid token from the expected issuer to the expected client, and to identify the user.”)

In the second case, as far as I know about token exchange, the entity requesting the token exchange should be the entity receiving the token. From your message it seems that the backend receives the token that will be provided to the SPA client, which doesn’t seem to be in accordance with the specification (“I need to take those tokens and on my backend exchange them for an access token generated for the client to access another API.”)
In this second case, I think you should implement the Backend For Frontend pattern to let your backend handle all the tokens.