Are refresh tokens necessary with reference tokens? - oauth-2.0

We have a Web API secured with IdentityServer4 using local API authentication. We are currently using both Reference Tokens and Refresh Tokens. Since we have the ability to revoke a reference token at any time is it even necessary for us to use refresh tokens? Couldn't we just set a long expiry for the reference token? Is there any security implications to this approach?

From the documentation:
When using reference tokens - IdentityServer will store the contents
of the token in a data store and will only issue a unique identifier
for this token back to the client. The API receiving this reference
must then open a back-channel communication to IdentityServer to
validate the token.
In other words, the client doesn't have to provide an access token to the api, only pass the reference.
This is a big difference between the JWT token and the reference token. The client sends the API the JWT token that has to be trusted by the API without consulting the provider, while the reference token forces the API to contact the provider, not having to rely on the client.
From the Refresh Tokens documentation:
Since access tokens have finite lifetimes, refresh tokens allow
requesting new access tokens without user interaction.
The question now is, can a reference token expire? Not from itself, as it contains no logic, unlike the JWT token. But there may be a server side setting that triggers some kind of expiration, or actually cause the reference to be revoked.
Either way, there is no use for a refresh token in this scenario. As you can't refresh the reference token. The reference token either exists or not (is invalid or was revoked).

Related

What JWT Tokens should be stored for use later?

I am looking at implemented Cognito for user login and would like to understand the process of validating JWT's a little better.
The application in question is on asp.net 4.5 MVC and not related to .NET Core. The only information on AWS Cognito I can find online relates to .NET core.
I understand the meaning of each token type as documented here:
https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-with-identity-providers.html#amazon-cognito-user-pools-using-the-id-token
I also understand the required steps in validating a JWT:
https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-verifying-a-jwt.html
My question is which JWT needs to be validated and at what stage?
Example 1.
A user logs in, once logged in they are returned with an Access, ID and Refresh token.
Do all of the tokens need to be validated at this point or just the Access token?
Is the refresh token only validated before trying to use it (in order to gain new access and ID tokens)?
OR should all tokens be validated on any authorised content request?
What tokens should be stored in the FormsAuthentication Cookie for use later? We are using the standard [Authorize] pattern in asp.net.
Question: Do all of the tokens need to be validated at this point or just the Access token?
Answer:
Validation is always done on Access token only.
Refresh token itself need not be validated. It is merely used for the purpose of obtaining fresh set of ID token and Access token.
Question: What tokens should be stored in the FormsAuthentication Cookie for use later?
Answer: This is specific to implementation. There is no rule on what token must be saved.
If the requirement is to just know the user's email or phone number, then just the ID token can be saved.
If the requirement is to allow one-time access for up an hour for the user,
then storing just the access token is sufficient.
If the requirement is to allow user to access the resource for up to 30 days, without being prompted for password, then refresh token must be saved.
The recommended approach is to validate the access token as it includes both authentication and authorization. You should be validating access token prior to providing access to protected resources.
The id token contains claims (information) of the authenticated user. It can be used for verification as well but there is more power in using access tokens as you can create scopes to define permissions and roles. Access token is also the input to many of Cognito APIs user operations.
AWS Cognito follows OpenID Connect Protocol which is built on top of Oauth2 for which these terminologies originate from.
The refresh token is a long lived token to retrieve newer short lived tokens (id token, access token). Currently with Cognito's implementation, shorter lived tokens expire every 1 hour and refresh tokens are configurable in the user pool. In the case where a refresh token becomes invalid/expired, attempts to retrieve newer short lived tokens will fail therefore you do not need to validate refresh token yourself.
You can store the refresh token (in some sort of session) to assist with the retrieval of new access, id tokens without re-authentication. You can also store the access token so that the refresh token is used only once per hour (when the access token expires) to prevent issuance of unnecessary tokens and round-trips to Cognito. The id token storage is really up to your use case, if you were interested in keeping the user claims (user information stored in the JWT of id token).

Why use openid connect ID token if the access token had all the claims and can be revoked?

I'm using oauth2 authorization code flow with the ASP.NET core 2.2 AddJwtBearer. My token end point returns JWT access toke with all the claims needed for checking the user's permissions.
I can send this token as the bearer for any Web API call and the standard .net code can use those claims to check permissions eg [Authorize(Policy="somePolicy")].
One of the claims points at an internal session key that we can revoke.
So my question is why would I need an ID token or even a refresh token?
The claims and other details are in the access token so what would an ID token add to this?
Having to use a further call to a userinfo end points send to be a waste if the info is in the Auth token?
If I can revoke the session that Auth token points at, surely I don't need a refresh token and can have longer life Auth tokens?
I've read lots of examples and comparisons but most computations between just oauth2 and enhanced with openid connect seem to be with very basic oauth2 not using JWT etc and so written to exaggerate the differences.
So I'm unclear when both are using the same authorization code flow and JWT tokens, what the team advantages are in using the id token in my situation??
Given your context, it seems that OpenId Connect is not necessary for your situation. It really adds value when you are implementing single sign-on (SSO). In that case the Identity token can also be used on SSO logout.
Having additional claims about the identity in the access token is also a waste. Having to send all this information on each call. Especially when you need the information only once (a Spa may persist the information in memory). It's better to have some api (endpoint) expose the information when requested.
About the access token, you can't revoke it. You may be able to revoke authorization, but the access token remains valid until it expires. You want invalid access tokens to short-circuit as soon as possible in the pipeline, before policies are evaluated.
Please note that it's not a common scenario where the api can revoke access by using an internal session key. Most api's are 'session-less' and fully rely on the access token. Because that's the purpose of a JWT, being self-contained, not having to contact the authority to verify the token.
Perhaps you can use a long-lived access token because in your situation the authorization is determined at another level. But are you capable of detecting when the token is compromised? And where are you going to check it? In every api and client? Or would you rather let the authority take care of it (single responsibility)?
When implementing security you should look at the design, the responsibilities, where to do what. Let the authority, that issues the tokens, take care of authentication and client/resource authorization. The Api, being the resource where the business rules (policies) are implemented, can take care of (user) authorization.
The problem with a long-lived token is that when it falls into the wrong hands, it allows access until it expires or, in your case, until you detect something is wrong. Where a short-lived token always allows access for a short time, making it almost not worthwhile for a hacker to obtain a token for the time it can be used.
With short-lived access tokens you'll have to use refresh tokens. The authority can verify on each call whether a new access token should be issued. Of course here counts the same, this only applies to the situation where you are actually verifying the request. Tokens in itself are not safe. You'll have to add some level of security, e.g. check the ip address. But having the authority to take care of it and using one-time-use refresh tokens already does add security.
In my experience with oidc/oauth2, the access token is mainly used to grant client applications access to a resource (on behalf of a user). Where scope claims define the accessible functionality and the sub claim identifies the user.
Authorization can be implemented on different levels and doesn't have to be part of the access token. In fact, permissions should not be part of the access token at all.
So your setup may be fine. But I wouldn't use long-lived access tokens for the reasons already mentioned. Plus they are not managable. You can't update the access token when someting changes in the flow, e.g. when a scope is added.

How to implement OAuth2 Code flow with automatic refresh token grant

We have just started out with ASP.NET Web API 2 and implemented OAuth2 client credential token grant, resource owner token grant (for internal apps) as well as code flow token Grant for third party Vendors.
For code flow, when the refresh token is exchanged for a new access token and refresh token the original token is removed from the token store and as such invalidated. The resource owner can also at any time revoke an access token and its associated refresh token.
One of our vendors will follow the code flow grant as there is a requirement that the resource owner or representative authorizes the access to the resource server.
The vendor subsequently requested that instead of the normal flow to redeem the refresh token for a new access token and refresh token, that the host server automatically provide a new access token and refresh token for each request.
The idea that over and above servicing the request, the host API calls back to a pre-determined endpoint on the client domain that will provide a new access token and refresh token.
It goes without saying that such an arrangement introduces complexity within the host API and it would defeat the whole point of short lived tokens and longer lived refresh tokens and we would probably implement other measures to prevent token hi-jacking and other types of attacks.
Currently our authorization server and resource server is one and the same. We would however want to keep the option open to separate the authorization server from the resource in future.
The questions from this then:
Should we consider this arrangement at all?
Would it make sense to adjust to a never expiring access token and not issue a refresh token with the token request?

Oauth 2: why refresh tokens must be stateful?

I'm working on a SPA app based on Node, with token-based authentication using JWT. Right now, the jwt token never expires, which is not good.
I want it to expire for more security, but I don't want my users to be forced to re-log. That's why I need a refresh token.
So i'm reading about OAuth2.
I have a hard-time to understand why refresh-tokens must be stored in a database, whereas access-token are generated on the fly using a secret key.
Why refresh tokens can't be generated the same way as access tokens ?
Thank you guys !
Refresh tokens usually are generated the same way as access tokens.
An authorization server will often return a refresh and access token if requested (and you're not using the implicit grant type).
The difference is how they are used.
An access-token is usually a bearer token: whoever has it can use it against the resource server, but it is only valid for a short period of time. In which case, storing them in a database is often pointless as they are worthless once expired.
A refresh token however is like having access to a "forge" which allows you to mint a new token.
If you present the refresh token to the authorisation server (not the resource server) you will get back a new access token and possibly a new refresh token.
Providing of course that the user has not revoked/changed access permissions to your application and that the user is still a valid user.
So you would keep them in a database perhaps because your user logs in infrequently. So you may need the refresh token weeks after you got it.
Alternative to the refresh token.
If you are using the implicit grant (which is common with SPAs but not recommended). You can try and keep your end user logged in to the identity provider used by the authorisation server. This way you can keep requesting new access tokens from the auth server without the user being prompted by the auth server for credentials as a session will be persisted between the identity provider and the user's browser.

Is function of authorization code and refresh token duplicated in design of oauth2?

there's two ways to fetch access token.
use authorization code to exchange it
use refresh token to refresh it
think about it!!
though the word of exchange and refresh is different,what they do are the same.
both action need to parse client id & client secret(Or signature) and token
we can just save the authorization code in our system,and again use auth code to
refresh access token just like refresh token do.
Except that authorization code is expired too soon.
so I wonder
why the designers of oauth2 designed these two concepts while not used just one single concept or say just design the authorization code and give it a long expired-time.
I am afraid that you have not understood the concepts of oauth2 too well. There aren't just two ways of getting the access token, there are more. Each is basically called a 'grant type'. I'm describing the use cases of the ones which I have deployed below :
1- Authorization code :
This is similar to the flow of "Login with Facebook" etc buttons which you see on different websites, which allow you to register/login using your facebook etc accounts. Here, on clicking this button, control is directed to Facebook, where the user enters his login credentials. If successful, an authorization code is sent to whatever redirecturl you entered while registering as a developer with Facebook. You then use this authorization code to request the access token service to get the access token which you then use whenever accessing any Facebook webservices to get the user's details.
2- Client credentials :
If you are running your own webservices and you want to allow access only to valid clients, then this is the grant type you would use. For example, you are running your webservices and now you want to consume it in your own native mobile app which you distribute through any app store. This will ensure that only those who installed your app will be able to access your webservice.
3- User credentials :
Same as above, only in this case this would allow you to authenticate a registered user as well and then give access to user restricted services like my account etc.
4- Refresh token :
By design, the access token service gives an access token as well as a refresh token. You would use the refresh token obtained from it here to refresh an expired access token. Essentially, this does not generate a new access token, it only "refreshes" an existing token. It will give you a new access token and refresh token and extend the expiry time. When this access token expires, you again call refresh token using the refresh token obtained last time, and keep repeating the process every time the token expires.
According to RFC 6749 10.5 The authorization codes are short lived and single-use. Therefore, you cannot use them again and again to get new authorization tokens.
Authorization codes MUST be short lived and single-use. If the
authorization server observes multiple attempts to exchange an
authorization code for an access token, the authorization server
SHOULD attempt to revoke all access tokens already granted based on
the compromised authorization code.
There are some additional misconceptions that seem to be presented here, so I wanted to help clear them up.
The differences between an access token and a refresh token can be summarised as follows:
An access token is used to provide access to restricted resources to an authorized client after authentication has taken place.
A refresh token, on the other hand, is used by a client in order to retrieve new access tokens with identical or narrower scopes.
The different between the Authorization Code Grant and the Implicit Grant (as well as their usages) help to illustrate how both should be used.
In general, the Authorization Code Grant should be preferred over the Implicit Grant unless a resource is being accessed directly via a publicly implemented client (e.g., browser-run code) or there is a specific reason that the Authorization Code Grant cannot be used (e.g., feasibility or performance). This is explained in the RFC definition for the Implicit flow.
During an Implicit Grant, access tokens are exposed to the user-agent which could lead to them being compromised since they are no longer under the control of a server app (confidential client) that could otherwise be requesting the protected resources. This is why refresh tokens are not issued during Implicit Grants. Though access tokens might be exposed, they are short-lived. Resource tokens, on the other hand, are long-lived and can be used to retrieve new access tokens.
The Authorization Code Grant, on the other hand, prevents the potential for refresh tokens to be exposed. During this grant, the authorisation server issues a code instead of tokens. The code is then passed by the user-agent to the client application which exchanges the code with the authorization server to retrieve access and refresh tokens. Since the code exchange is performed directly between the client application and a trusted authorization server, a refresh token can be securely issued.
The RFC spec cautions that the security implications of implementing the Authorization Code Grant in a public client versus a confidential (e.g., server-side) client should be seriously considered. "More OAuth 2.0 Surprises: The Refresh Token" clears up a few misconceptions and furthers the idea that auth codes should not be sent directly by the user-agent to the auth server in order to retrieve refresh tokens, though the OAuth 2.0 spec does not technically dictate this.
Answer from #ComfortableDust has the answer to original question. Just quoting the exact text from his reply
The Authorization Code Grant, on the other hand, prevents the potential for refresh tokens to be exposed. During this grant, the authorisation server issues a code instead of tokens. The code is then passed by the user-agent to the client application which exchanges the code with the authorization server to retrieve access and refresh tokens. Since the code exchange is performed directly between the client application and a trusted authorization server, a refresh token can be securely issued.

Resources