Why doesn't Access Token have the identity of user?

Viewed 160

I am struggling with the concept of access tokens in regards to them not having the identity of the person making the request.

And i think i may be using access tokens incorrectly in my project.

The thing I don't understand is access tokens are often explained as a hotel card key to get into a room, but this analogy just doesn't make sense to me when it comes to the vast majority of requests.

For example say i have a resource for your private messages and scope read:privateMessages

If you want to do some action like read private messages, and you send me an access token I have to know who it is, as in I can't send you back someone else's private messages or all private messages.

A hotel key in this case doesn't work here, a hotel card that has scope read:gymroom write:gymroom

Then yeah you can access the room, but in any applications i have worked on I really need to know who is making the request.

To go back to private messages if you post to private messages, maybe this takes a Message and Destination, I need to know who is sending the private message and I need that from the access token...

The analogy here also breaks a bit as the sub of the access token (if access token is jwt) is usually the user id and I look that up or call the user info endpoint.

But isn't it simpler to just put the user principal name or email in the access token and save the backend from doing the lookup request on each user request?

There is no security benefit that i can see from having the email / username removed from the token, if the same token can be used to call the user info endpoint

Can I get some help with understanding this concept better as I feel maybe I am doing things incorrectly or have some kind of large misunderstanding on this concept.

I do know there are questions on this on stack overflow but I haven't found anything specifically to clear this up.

3 Answers

The analogy here also breaks a bit as the sub of the access token (if access token is jwt) is usually the user id and I look that up or call the user info endpoint.

But isn't it simpler to just put the user principal name or email in the access token and save the backend from doing the lookup request on each user request?

Yes, you can. If I talk about specific to JWT access token then the primary intent behind using it for stateless authentication which mean token should contain sufficient information for the resource server to authenticate the request without datastore lookup. Oauth access token are merely random keys and resource server does need authroization server for veriyfing the same. However, you can extends oauth authroization server with JWT support to issue the JWT token.

The hotel card key is a good analogy for the access token because it deals with delegation. Whoever presents the hotel card key can get in to the room. If needed there can be identity information of the original user (Resource Owner) in the access token, but in that case it does not represent the "presenter"'s identity, merely the "owner"s identity.

When you actually want to know who is entering the room (or, presenting the token), you'll need to revert to a different token and protocol such as the Identity Token in OpenID Connect.

I think, the hotel analogy helps to understand the concept of Bearer tokens. Anyone with a valid hotel card key can enter the room. This also means that if an attacker manages to steal a Bearer token (the hotel card key), the attacker can gain access to the API (the hotel room), as long as the token is valid.

In general, the API should use the claims from a JWT for authorization, then you can skip the call to the UserEndpoint. Consequently, this means that the JWT should contain all the claims that the API needs for proper authorization. However, be careful when designing the token. If the access tokens are JWTs then a malicious client (e.g. from an attacker) may still try to parse the JWT and access its claims even though the client is not intended to. Or an attacker may come across the token by other means and parse it. In such cases, the application leaks data to an unauthorized party (an attacker). Data leaks can imply a violation of data protection laws or other regulations and cause troubles depending on what data the token contained. Username and email may not be a big issue regarding compliance but they can still cause security issues. For example, username and email may both be used by an attacker for personalized attacks (think of phishing emails).

Note, that it doesn't matter if the token is valid or not - the data is still there.

At Curity, we often recommend using the Phantom Token Pattern. It places an API Gateway in front of the API. The Authorization Server only issues by-reference tokens to the client (i.e. some id). When the client calls the API via the API Gateway, the latter exchanges the by-reference token for a by-value token, i.e. a JWT. In this way, no data will be leaked to the client and the API can still benefit from the JWT and its claims.

Related