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.
Related
I have a refresh token in hand, a client_id and a client_secret.
I'd like to determine which end-user the refresh token corresponds to, and/or which scopes.
Is that possible, and, if so, what's the best way to go about that?
Most commonly refresh tokens are opaque unreadable values that map to state stored in the Authorization Server.
Some providers may issue refresh tokens as JWTs, in which case you can read the values. Your code will not be portable though, so this is not advised.
CLIENT
Usually an OAuth client gets a refresh token from the Authorization Server (AS) after user authentication. Later on the client can try to renew access tokens with it.
AUTHORIZATION SERVER
This is the standard component for issuing and renewing refresh tokens and the typical behaviour is like this:
When a user authenticates, record details of the 'delegation' in a database row
Typical fields stored are a SHA256 hash of the refresh token, the user and client IDs, and the issued / expiry times of the grant
This information enables the AS to receive and validate token refresh requests.
ISSUING YOUR OWN REFRESH TOKENS
This should only need to be done if you don't have an AS. In this case follow the AS pattern above. It is recommended instead to use an AS to do it for you though - eg the free edition of Curity from the above link.
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).
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?
I am building a (set of) web application; the backend has REST-like API, the frontend will be some REST JS app, android apps etc; and I'm trying to come up with an SSO functionality.
Looking at Oauth2/OIDC it seems the best way would be to use Implicit flow; however, the access tokens in implicit flow (in oidc) have a set expiration. The refresh token is not part of implicit flow.
How do I ensure that the user will stay logged in? I.e. when the access token expires, the frontend application will try to obtain a new one from an auth server; that is supposed to ask for username/password. Alternatively, it can build a session with the frontend (using cookies), but how is that different from a refresh token?
It seems to me that getting the access token e.g. from the android app means at least opening the web browser; depending on the expiry length, that could be quite often. Is that the correct flow or am I missing something?
You are right, the issuance of a refresh token is not allowed with the Implicit grant type.
However, the refresh token and the access token are not needed to know if the user is logged in or not (the access token only allows you to access on protected resources). You have to use the ID Token which is issued in the authorization response.
You can verify if the user is still logged in by sending an authorization request with the query parameter prompt=none (see section 3.1.2.1. Authentication Request). I recommend you to send the current ID Token using the id_token_hint query parameter as mentioned in the same section:
ID Token previously issued by the Authorization Server being passed as a hint about the End-User's current or past authenticated session with the Client. If the End-User identified by the ID Token is logged in or is logged in by the request, then the Authorization Server returns a positive response; otherwise, it SHOULD return an error, such as login_required. When possible, an id_token_hint SHOULD be present when prompt=none is used
If you receive an error (login_required or interaction_required) then the user may be logged out.
Another way could be to use the Session Management feature. But as this specification is not yet approved (draft 27), it may be subject to changes and may not be available. However it is a very simple way to know the status of the user.
I'm reading through the OAuth2 RFC 6749 specs before implementing an Authorization/Resource server for the Resource Owner Password Credentials Grant.
I understand that the Client application uses the refresh_token (along with its credentials) to obtain a new access token for an End User (Resource Owner) rather than storing the End User's username/password and sending them every time an access_token expires.
However, to me this sounds like the refresh_token is as good as an access_token, it's pretty much just an extra server call, so why not use it directly i.e. if the refresh token is valid grant access?
Am I also correct to assume there is one refresh token per End User's session?
However, to me this sounds like the refresh_token is as good as an
access_token, it's pretty much just an extra server call, so why not
use it directly i.e. if the refresh token is valid grant access?
Because that extra server call to the Authorisation Server is important in ensuring access is still allowed to the client app. The resource server would not be able to verify that the refresh token is still good without talking to the Authorisation Server. But this is not the concern of the resource server.
A valid access token is a bearer token. It is used directly on the resource server to get data - no questions asked. If it's not expired, and it has the right scopes - here's the data, whoever you are!
A refresh token on the other hand has to be presented to the Authorisation Server along with client credentials. The Authorisation Server may choose to verify that the resource owner hasn't revoked access to that client, or that the client app itself is still valid. If OK the authorisation server can mint a new, short-lived bearer access token, which is as good as data to anyone who has it!