What the article actually seems to be asserting is that permission checking should be done via calls to an IAM and not via claims in the JWT (if I'm understanding it right).
I don't buy this either. Tokens can cache permissions, albeit with the same staleness issues that JWTs have for authentication. It's not much different than how a driving license is both evidence of identity and evidence of a permission.
The claims might be stale, but we have the same problem for revoking JWTs.
I think you're talking about delegation now.
> JWT tokens don't tell you what the user is allow to do, they tell you what the service/client is allowed to do on behalf of the user.
This is delegation, not authorization.
> There still needs to be a seperate check to see if the user themselves are even allowed to perform a particular action to begin with, to have even allowed something else to do it on their behalf, and thats what solves some of the stateness issue, in that,
Services which are acting on the user's behalf (delegated) can pass the user's claims through too; can pass the whole JWT through. That services act on the user's behalf with delegated authority is a red herring, as far as I can see.
You can still cache permissions (e.g. role) in the JWT. You don't need to do a separate check using the user's identity, as long as you either have mechanisms to deal with the staleness of the cache, or you're happy that the cache lifetime isn't long enough for it to be a problem (nothing happens instantaneously in distributed systems, after all).
> if you have for example an admin, who gets fired, even if they still have a valid JWT token that says the client is allowed to perform certain actions on their behalf, there is still a check to see if the user can perform those actions, so as soon as they are fired or demoted, the backend will instantly stop performing actions on their behalf regardless of what the JWT token says they can do.
This is why you have things like the Refresh and Access tokens pattern. In the absence of revocation blacklists, claims shouldn't be put into long-lived tokens.
Friend, I've read your comments throughout this thread and it is this point where your misunderstanding starts.
From the OAuth 2.0 RFC:
"Instead of using the resource owner's credentials to access protected resources, the client obtains an access token -- a string denoting a specific scope, lifetime, and other access attributes. Access tokens are issued to third-party clients by an authorization server with the approval of the resource owner. The client uses the access token to access the protected resources hosted by the resource server."
https://tools.ietf.org/html/rfc6749
There is no situation permissable under OAuth 2.0 where an Authorization Server issues access tokens to access resources held by the resource owner, except where the resource owner has given their explicit approval.
Nor is there a scenario where a user can even be requested to give permission to a client to have greater access than that client should otherwise have.
Scopes allow a resource owner to be granular about what they approve access to.
Strictly speaking JWTs don't have to be used for authentication at all. They are just signed tokens containing JSON. You could have a shopping list in there if you wanted to be sure it was definitely your wife telling you to pick up milk on the way home.
A user token tells you (the relying party) that the user has been authenticated to the satisfaction of the issuer (often Google, Microsoft, Facebook but it can be anyone inclusing your own authority). You can be sure the token has been issued by the issuer due to the signature. If you trust the issuer then you can trust the time-limited token.
As far as how the issuer has confirmed the user's identity and whether it represents a person, service, etc. can vary.
There 's obviously way more to federated authentication that I want to post in a comment, but there you go. I believe the OP was getting slightly confused between some OAuth2 implementations and proper security implementations like OpenId Connect.
quite common in mine, especially when dealing with service oriented architecture. the public api is given a token, and it should use that token to authorize itself to use other services, or a cron job that performs actions on behalf of users.
> A user token tells you (the relying party) that the user has been authenticated to the satisfaction of the issuer (often Google, Microsoft, Facebook but it can be anyone inclusing your own authority). You can be sure the token has been issued by the issuer due to the signature. If you trust the issuer then you can trust the time-limited token.
But my point is (and the point of the article) is thats not what the token tells you. The token tells you (and the reason its called a bearer token) that whoever holds this token, can perform the list of actions defined within the scopes array. Which is completely different to saying we are 100% sure the user is who they say they are. If the token told you the user is who they say they are, then why do you even need scopes? You could just assume the user is allowed to do anything they wanted to to their own resources.
Some conflation between authorisation and authentication here too — the description of JWTs here describes authorisation, not authentication, I think ‘authorizing the client’ vs ‘authorizing the user’ would typically just be ‘authorization’ and ‘authentication’ respectively.
For example, a user signs in and gets a JWT token that has the permission Delete.Everything which in this example is the permission required to delete all a users resources, the client takes this and passes it to the backed. On the backend however, the user might not even be allowed to delete everything. Maybe they're under investigation, or maybe this particular service just doesn't allow it. But its not the role of the JWT to tell you whether or not this particular user is allowed to perform that action, all the JWT token tells you is that this user has allowed the bearer of the JWT token to perform that action on their behalf. But, doesn't mean the user is allowed to perform that action to begin with, so the user has given the client permission to perform an action they themselves aren't allowed to perform.
In the case of OIDC, the ID Token is the contract of authentication. So when I login via Google, both the consumption of my username / password to produce the ID Token JWT, and the consumption of the ID Token by the third-party are authentication.
> For example, a user signs in and gets a JWT token that has the permission Delete.Everything which in this example is the permission required to delete all a users resources, the client takes this and passes it to the backed.
This is again confusing a common use case of JWT with what it actually is. A JWT is just a signed token. The concept of a 'permission' used here is an abstraction upon what JWT really defines, which are 'claims' (i.e. signed information).
> On the backend however, the user might not even be allowed to delete everything. Maybe they're under investigation, or maybe this particular service just doesn't allow it. But its not the role of the JWT to tell you whether or not this particular user is allowed to perform that action, all the JWT token tells you is that this user has allowed the bearer of the JWT token to perform that action on their behalf.
This is a usage detail for which there are several valid approaches. It's not uncommon to see a JWT used as an authentication token be the source of truth, with only invalidation based on unique id (jti).
The concept of the JWT being correlated with a user authorization is an entirely synthetic one. It's a common use case. Check the original RFC.
> But, doesn't mean the user is allowed to perform that action to begin with, so the user has given the client permission to perform an action they themselves aren't allowed to perform.
Consider this counterpoint: if the JWT itself is not itself a statement of authorization, what's the point in signing it at all? We could just be sending a unique id corresponding to this token (like a circa 200x OAuth token) and get the same effect. JWT is used for a common pattern, but it's important to understand why that pattern is chosen.
Making another call over the network for auth is by definition vastly less efficient by several orders vs having been handed the information in the first place. The bottleneck of a centralized permission service is actually what pushed us to JWT in the first place.
Using JWTs to authenticate the user allows actual decentralization of your endpoints. We have services that speak directly to nothing else in the ecosystem and it’s a major win.
The security argument is valid to a small extent, but I’ll trust a well salted SHA256 with my life until I’m told otherwise.
From https://news.ycombinator.com/showhn.html Edit: The title has removed show hn now
> JWT tokens authenticate the client, not the user
I think it's both. It just doesn't authorize the user for anything special.
The fact that RFC specifies a subject claim (for the authenticated principal), but not claim for clients or scopes, shows quite clearly that delegation was not the immediate goal behind JWT [1].
JWT and JOSE annoy cryptographers and security researchers so much precisely because they're trying to be a generic cryptographic format that's supposed to solve everything under the sun. The tragedy of JOSE is that instead of trying to solve a small set of problems well, it is basically failing at solving any kind of problem in a satisfactory manner.
JWT can be used in the way described above, but it doesn't seem like particularly a good fit for this purpose. If we can't trust the clients not to lie about their users and their delegated claims, we need to make calls to some mutually trusted STS (or a Token Exchange) anyway. But if we already call an STS, we can just let the STS produce any type of opaque tokens for any type of server and let the backend verify the tokens (delegated or not) with the STS.
[1] Yes, these claims appear in the draft for OAuth 2.0 Token Exchange, but they came a few years later, and that draft is still not standardized.
It fails to really do this, as it notes some IAM systems can be used to transmit user authz information in it, and it provides no substantive reason to reject that use, it just asserts that it's wrong and that there are (unspecified) better alternatives (which it also fails to explain how they are better concretely.)
Waving a hand at more efficient and secure is nice, but show me a concrete security concern or evidence that another way is more efficient given that I'm already paying the cost to decode and parse the JWT and maybe I'll believe you.