Looking at the Oauth2 specification, it says in section 6:
... the refresh token is bound to the client to which it was issued.
However, I can't find anything in the specification the explicitly states that the token should be bound to the requesting client also. I am assuming this to be the case, and the Introspection Extension seems to support that assumption, but I want to know if that is correct.
As an example, say I am using two applications that use Google as the Oauth2 Authorization Server. I'm assuming that Google will issue two different tokens, one to each application, and that the tokens can only be used by the client to which they were issued because they are bound to that client.
An access token can have various implementations. The one that is most widely adopted today is the "Bearer" token, in RFC 6750 https://www.rfc-editor.org/rfc/rfc6750. A Bearer token is not bound to the Client on purpose: it makes it easy to implement, lowers the barrier for adoption and caters for a wide range of use cases.
Assuming that a Bearer token cannot be easily stolen, it is acceptable to avoid binding it to a specific Client: the intended Client could indeed share the access token with another Client but it could just as well share the data that the access token permits access to if the token was bound.
In environments that demand higher security one could use a token that is bound to the Client as defined in RFC 7800 https://www.rfc-editor.org/rfc/rfc7800.
Yes, I think it is implicit in the specification that the access token should only be used by the application that the user authorized. Putting it differently - having something other than the authorized application use the token to access user data is pretty much the definition of a privacy failure, and is what authorization protocols are explicitly designed to prevent in the first place.
Now, in practice, I think that having one application use the access token from another would work fine in many OAuth 2.0 implementations. I don't thing the Token Introspection extension is widely used, and most access tokens are designed to be self-validating. Indeed, that's the reason why token stealing is a security risk. By contrast, the refresh token should only be useful when combined with the client secret, so it's "bound" to the client technically as well as philosophically.
Related
Currently building up a microservice for handling auth-related stuff using OIDC.
Now, we think about access control and how to be as future-proof as possible. This auth server is only used for first-party applications (3x SPA, 2x native mobile App). On mobile, we use the authorization_code grant. Each resource server validates the supplied token (access token as JWT) itself. But what happens when (in future), we add a service which needs its own scope to check (e.g. notifications:read)? As mobile app users are not used to logging in and out everytime (when we would update the requested scopes via an app update -> bad solution) is there any sweet solution to manage this scenario?
Per specification, it's possible to change the required scopes when refreshing a token but this is limited to require less scopes than originally requested and not more so that's not an option.
For example, Facebook is providing only four scopes for Instagram e.g. instagram_basic or instagram_content_publish. Zalando for example includes only a scope NORMAL_USER in their tokens whereas Wolt includes the users roles as a claim.
I think there is some confusion as this scenario is not covered directly by OAuth2 or OIDC. What are your thoughts about this?
There is one standard for doing OAuth 2.0 Incremental Authorization, but your challenge is to find a token provider that supports it or similar standards.
In a micro service architecture, the question is if you should use the access token from the authorization code flow everywhere, or if for service-to-service communication, you should use client credentials flow instead.
See also https://www.gmass.co/blog/oauth-incremental-authorization-is-useless/
It seems like you could use Token Exchange for that.
For example it could work like that - whenever your resource server gets a token without the notifications:read scope, issued before date x (so before you were issuing that scope) it performs an exchange with the authorization server and (if the server decides that it can perform the exchange) it gets a new access token that contains that scope. If the token was issued after date x you can safely assume that the token was not granted this scope.
Another solution would be to use claims for authorization decisions instead of scopes. The authorization server can issue e.g. a claim notifications_read: true, or something like that. Whenever you refresh tokens you can issue more claims in the new access token, the spec does not prevent that. Then your resource servers should check claims in the access token, they can ignore scopes. The resource server would just check whether the token contains the notifications_read claim with value true, or not. This solution gets a bit more complicated if you require your users to give consent to scopes, but as you said you're using this only for 1st-party, so I assume you're not using consent screens.
You can have a look at this free course - this topic of using claims in authorization is covered in part 4.
I can find plenty of example of single page apps (which can't manage a client secret) and plenty of examples of old-school server-side apps (which can manage a client secret) using OAuth.
But for us and, I suspect, the majority of enterprisey systems, a system is both server-based and client-based.
We can easily (and securely) identify the client server-side, and we could then make the resulting (user) access_token available browser-side.
The question is, does doing this introduce a risk?
The client-server (the server-side component of the client) cannot guarantee that the browser is running its code - but it can guarantee that all access to the resource owner's data on the client has been approved by the resource owner.
Thanks.
The principle itself does not introduce a risk but of course you need to take care of the method used to expose the access token to the browser. One such approach is documented here: https://hanszandbelt.wordpress.com/2017/02/24/openid-connect-for-single-page-applications/
It suggests to expose a server-side endpoint that can be called with a cookie which will then return session information that may include the access token.
Every article I've read vouching for the advantages of JWT state that one of these advantages is its ability for an auth system to be distributed across multiple servers. i.e . You aren't relying on a central repository of user auth details to do a lookup on every request.
However when it comes to implementation, I've read in many places that for added security you shouldn't just rely on the JWT signature verification itself, and that you should maintain a list of black or white list tokens generated by the server.
Doesn't this defeat the advantage I've listed above, as this list of tokens would need to be stored centrally where all servers can access it and it would require a lookup on each request?
How have people implemented this on their end?
You are making very good points in your question. Actually it would make sense to store an OAuth token at a central location in order to make it easier to implement signout/revoke functionality. If you just relied on the token signature you couldn't have possibly implemented such feature. Suppose that a user wanted to revoke an access token. In this case if you didn't have a central location/datastore for those tokens where you would have invalidated it and only relied on token signature, then the token would still have been valid.
So indeed, when you want to build more advanced systems that are dependent on OAuth tokens, a central store for those tokens is more than a must.
From what I can tell, the OAuth 2.0 specification is extremely vague in terms of what form an access token should take:
The token may denote an identifier used to retrieve the authorization
information or may self-contain the authorization information in a verifiable manner (i.e., a token string consisting of some data and a signature). Additional authentication credentials, which are beyond the scope of this specification, may be required in order for the client to use a token.
The access token provides an abstraction layer, replacing different authorization constructs (e.g., username and password) with a single token understood by the resource server. This abstraction enables issuing access tokens more restrictive than the authorization grant used to obtain them, as well as removing the resource server's need to understand a wide range of authentication methods.
Access tokens can have different formats, structures, and methods of utilization (e.g., cryptographic properties) based on the resource server security requirements. Access token attributes and the methods used to access protected resources are beyond the scope of this specification and are defined by companion specifications such as RFC6750.
(emphasis added)
The linked RFC6750 doesn't offer much further specificity. There is an example HTTP response body that shows:
{
"access_token":"mF_9.B5f-4.1JqM",
"token_type":"Bearer",
"expires_in":3600,
"refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA"
}
This seems to indicate that the access_token can be opaque ASCII text such as an encoded JSON Web Token (JWT)
From my perspective, it seems like JWT-as-access_token has some desirable properties:
It's a known specification, with fairly wide adoption and client libraries available in many languages.
It allows for easy signing and verification using vetted cryptographic libraries.
Because it can be decoded to JSON, it would allow us to include metadata and information about the token within the token itself.
My questions are: First, is it permissible for the access token to be a JWT? Second, if it is permissible according to the spec, are there any additional considerations that would make using a JWT as an access token a bad idea?
A1: Using a JWT as an access token is certainly permissible by spec exactly because the spec does not restrict its format.
A2: The idea behind using a JWT as an access token is that it can then be self-contained so that the target can verify the access token and use the associated content without having to go back to the Authorization Server. That is a great property but makes revocation harder. So if your system requires a capability for immediate revocation of access, a JWT is probably not the right choice for an access token (though you can get pretty far by reducing the lifetime of the JWT).
As long as the Authorization Server and the Resource Server agree on what the access token means, it doesn't matter what their content is. So the only reason you could have a problem would be if you were using different libraries or frameworks when implementing those two servers.
Currently the OAuth Working Group is working on a JWT profile for OAuth 2.0 access tokens: JSON Web Token (JWT) Profile for OAuth 2.0 Access Tokens
I am learning oAuth2 for the first time. I am going to use it to provide authentication for some simple web services using a two-legged approach.
According to what I have read, the flow should go like this: the web service client supplies some kind of credential to the oAuth server (I'm thinking of using JWT). If the credentials are valid, the oAuth server returns an access token. The web service client then supplies the access token when attempting to use the web service end point.
Here is my question, why not just supply the JWT when making a request to the end point? Why is oAuth's flow conceived this way. Why not just supply to JTW to the end point and use that for authentication? What is the advantage of having the extra step of getting an access token?
Thanks!
You can certainly supply the JWT directly to the web service. The questions is how do you generate it in a way that the service trusts.
A JWT is and access_token, but not all access_tokens are JWTs.
Your client can issue a JWT, sign it with a key (or a cert) and then send it to the API. The advantage of having a 3rd party (an Issuer) is that you can separate authentication from issuing tokens. Clients can authenticate in multiple ways (e.g. usr/pwd, certs, keys, whatever) and then use the JWT to call your API.
The additional abstraction gives you more flexibility and management scalability. For example: if you have 1 consumer of your API, then you are probably ok with a single credential (or JWT, or whatever). If you plan your APIs to be consumed by many clients, then handing that responsibility to a specialized component (e.g. the the issuer) makes more sense.
OAuth BTW, was designed for a specific use case: delegate access to an API to another system on your behalf. You grant access to system-A to access resources on system-B on your behalf with a permission scope.