API rest with jwt for authentication. Why do we need a refresh token? - jwt

So, i'm trying nest js for a side project. Reading a lot lately about jwt authentication flow. Conceptually, the flow would be something like:
Client logs in and receives and access token and a refresh token. Access Token will be short lived and will be stored in memory, not in localstorage, to reduce the risks of being stolen.
Refresh token will be used only when the access token is expired to get a new one. The new one will be stored in memory. The refresh token will be stored in an httpOnly cookie, so no javascript access will be allowed hence improving the security.
Everything is cristal clear, but, my question is... why do we need the access token and why don't we always use the refresh token? In the end, if we are trusting the refresh token to generate new access tokens... why don't we simplify the whole thing and use only the long lived, stored in an httpOnly cookie on every request?
I mean I get the whole process, I just don't get why is not "secure" to use the token stored in an httpOnly cookie every time.
Can anyone share some light here?
Thanks!

You use the access token to access the API. It contains the necessary claims to authenticate and authorize the request.
The refresh token is a separate token that you use to renew the access token and you can not use the refresh token to access any API, as it is typically just a random string without any specific meaning (no claims).
The refresh token is never sent to any API and having separate tokens gives a better separation of concerns. By using refresh tokens, we can have short-lived access tokens, so if the access token is stolen, it can only be used for a short time. The refresh token is stored in a more secure way and it is only used between the client and the identity provider, so there is less risk that it will be stolen or intercepted.
Some platforms (like ASP.NET core) stores the token by default in the session cookie) but to secure it it is encrypted using strong encryption. This means that the hacker or browser can't see the actual tokens inside the cookie.

More you travel, more you exposed.
As you know the refresh token is meant to be used in case of short lived access token expiration. The idea for the use of two tokens is very simple. As access token (short lived token) will travel more frequently over the wire, increasing it chances of getting it caught by external parties. Therefore, short life expectency of access token will deny the access to the resouces for longer run in case of compromisation.
If the refresh token is secured, why don't we use just the refresh on
every request?
Nothing can make the refresh token secure. It's totally client responsibility to store it in secure location/storage for later use.

Related

What is the point of refresh token in jwt?

Please don't mark as duplicate I came through a lot of questions like this but still I didn't get the point of refresh token. Some of the reason they said are:
If an attacker gets the access token it will expiry soon
But where I am confused is if the attacker was able to get the access token why they wouldn't be able to get the refresh token (both of them needed to access token by JS to sent request so they needed to store in local storage)
If the attacker gets the refresh token we can block it in server.
But we can also block the access token in server right. (with DB)
Note I am not talking about OAuth refresh token, because as per the answers I read,
The idea of refresh tokens is that if an access token is compromised,
because it is short-lived, the attacker has a limited window in which
to abuse it.
Refresh tokens, if compromised, are useless because the attacker
requires the client id and secret in addition to the refresh token in
order to gain an access token.
So it makes sense here but what about JWT?
Typically the access token gets sent with every request, and to your API.
Typically a refresh token only gets sent once, immediately expires after use and only goes to your authentication server. All these measures generally reduce risk.
JWT and OAuth2 can be used together, and it's highly recommended to use OAuth2 instead of trying to write something from scratch.
I talk a bit more about the pitfalls in my article: https://evertpot.com/jwt-is-a-bad-default/
The refresh token allows the client to make a call and ask for a new access token. For setups where the access token does have a certain expiry, the refresh token will typically have an expiry which is later than the access token itself. Here is a typical workflow using access and refresh tokens:
The client authenticates to the server via 1FA or 2FA
The server responds with an access token having an expiry in 5 minutes, along with a refresh token which expires a minute later
The client then uses the access token as needed.
When authentication fails using the current access token, under the hood the client will take the refresh token and hit the server to get a new access token. We then go to step #2 above and recycle.
Note that for certain instances, the refresh token is not needed. One example would be sites like Stack Overflow, which uses token which never expire. Another example would be certain high security sites such as banking sites. In these cases, the site might force you to reauthorize via 1FA/2FA in order to keep the session going.
One way in which an update of the authentication token can be carried out through another and without exposing it to client applications (avoiding its use in a malicious way), is to store it in a cache system such as REDIS and in the When the request token has expired, check in storage if the user has a refresh token that allows him to regenerate the authentication. This could be implemented within the same middleware that validates the token that accompanies the request or in an endpoint intended for this purpose.

What is the MUST have claims for JWT refresh tokens? Can it be identical to the access token (with a longer exp)?

Im playing around and creating a custom access token system using JWT. I have already created a system for signing and validating JWT access tokens.
However, I find it hard to obtain information about what claims a refresh token should consist of.
Should i create refresh tokens identical to the access token - with a longer expiratiom time so that the same function that validates access tokens can be used to validate the refresh token?
A refresh token is typically an opaque value that is only used by clients to refresh access tokens. The flow works like this:
Web or mobile client implements OpenID Connect to authenticate users and get tokens - prompting the user to consent in some cases
An Authorization Server (AS) issues the tokens and stores details of this 'delegation' in a database - tokens are a pointer to this state
Client sends access tokens to APIs until a 401 expired response is received
Client then tries to refresh the access token by sending the refresh token to the Authorixation Server, which then looks up claim details from the stored state
I would make sure you get these responsibilities right - in particular avoid building your own AS and use a free one provided by experts, such as Curity Community Edition. Many security solutions will then be easier to develop.

JWT access token in-memory?

I’ve been spending hours and hours on this, this is the first time I am using JWT and would really need some of your thougts.
Right now I store my tokens in separate httpOnly cookies (my access token expires after 15 min and refresh token after 7 days).
I have read that the most secure way to store the tokens is actually using a cookie for the refresh token and in-memory (like in a variable) for the access token.
While I understand this is secure, I do not really understand how it would work in practice. Would it mean that we have to create a new access token with our refresh token on each request? Or is there a way we can make it valid and copied to new variables until it is expired?
I am using react and node btw.
I spent days reading about this too.
From what I gathered a solution would be something like this:
User logs in with login and password.
Server generates a refresh token long lived to be stored as an HttpOnly Cookie, preventing XSS attacks as it can not be accessed by Javascript.
Ideally some sort of blacklist can be used server-side to prevent re-use of refresh tokens that have not reached their expiry but have been replaced.
Generate an access token which can either be stored in localStorage or in-memory (in a variable). The access token has a short expiry life of a few minutes.
If stored in localStorage, the token will not disappear on a reload of the page/browser (F5). It will also be visible in the console/storage.
When using localStorage to check if user is authenticated, the code will try to read the token from localStorage, jwt_decode it and set a user variable with the data that is in the token.
As tokens are not encrypted, just base64, their values can be changed in the dev console. A page that is "role: admin" only will be rendered if the permission is changed. The API will be responsible to check for permissions and reject the request if the token has been tampered.
Afaik, if it is stored in a variable it is a little less visible, it also gets wiped when reloading the page/browser.
When using a variable, to avoid refreshing the access token on every request, we can use the Context API, by creating a Component with the authenticated user context that will wrap the App/Router and then on every page that needs to be protected import and use this context and redirect if needed.
When the access token is not valid anymore, because it has reached its expiry, or because it has been wiped, the API call will get rejected. Intercept this call then call the API refresh route to use the refresh token to generate a new access token.
I use axios with axios interceptor to intercept the failed request, call the refresh route, set the renewed access token, then retry the failed request. (needs to be a GET request to avoid CSRF errors apparently).
In addition (not in place of), a setTimeout can be used to automatically refresh the access token every X minutes to prevent letting it expire.
To log out, remove the cookie (eventually blacklist) and wipe the context / localStorage.
Using axios, axios.defaults.withCredentials = true; makes sure that the cookie is sent with the requests and { headers: { 'Authorization': `Bearer ${access_token}` } } makes sure the access "bearer" token is sent with the request. These can either be set as defaults for every request or per request hence these 2 syntaxes.
Github example with Flask and React

Using both access and refresh tokens for refreshing them

Was investigating how to work with JWT and found not obvious thing for me:
Why for refreshing access token are not using both access and refresh tokens but only refresh token?
In this case we will be able to:
Verify access token signature, even if it is expired.
Get from access token information from payload, which may help in finding refresh token in database.
Your question is a bit unclear and is assuming some things that may not be true. Neither access tokens not refresh tokens have to be JWTs and JWTs are not specific to OAuth2 (which defines access and refresh tokens, but doesn't say how they should be implemented).
The audience for access tokens and refresh tokens is also different - access tokens are sent to a (possibly separate) resource server (the issuing authorization server may not even have kept a copy if they are self contained). Refresh tokens are sent to the authorization server.
Locating either type of token in a database (assuming they aren't self-contained tokens like JWTs) should never be a problem because they should be unique tokens which make ideal primary keys for a database table. So there would be no reason to send an expired access token as part of a refresh request.
Welcome to Stack Overflow, by the way :).

What is the difference between a JWT token and a Refresh token?

I'm trying to get my head around refresh tokens and how they work with JWT, so I can use it without auth0 API service.
Why refresh token format is different from JWT?
refresh tokens are just simple tokens store in the db?
How is the flow to use a refresh token to get a JWT token?
Thanks!
UPDATE
As #Florent Morselli suggested. The fundamental question of this post is wrong and confusing. Since JWT and refresh tokens are not really concepts that can be related. A better question can be:
What is the difference between a JWT Token and an opaque token?
What is the difference between a Access Token and a Refresh Token?
I'm not changing the question in the title, since somebody might be looking wrongly for the same thing and it will lead them to this post.
Token can be of two types:
Tokens by Reference
Tokens by Value
With the first type, the tokens are opaque strings (often random strings) that refer to a database index where the values associated to the tokens are stored.
With the second type, the tokens contain the values. To avoid alteration they are digitally signed or hashed. As they also may contain sensitive data, they can be encrypted.
JSON Web Token is a suite of specifications (mainly RFC7515 to RFC7520) that introduces a new format for the second type.
Why Refresh tokens issued by oauth0 are of the first type and not JWT (second type)?
The main benefit of the tokens by value is that they can be stateless i.e. you don't need any kind of database.
This is really helpful when tokens are sent several times to a server as they drastically reduce database calls and thus reduce the response time.
The drawback is that you cannot revoke them. Or if you add a revocation system, then you have to manage and call a database.
Therefore , tokens by value should have a very limited lifetime which is not compatible with refresh tokens.
Refresh token are used in Code flow or Hybrid flow as per OpenID Spec See Image below
Reference: https://openid.net/specs/openid-connect-core-1_0.html#CodeFlowSteps
Why refresh token format is different from JWT?
The format of Refresh token is also as per spec from OpenID
Reference: https://openid.net/specs/openid-connect-core-1_0.html#CodeFlowSteps
refresh tokens are just simple tokens store in the db?
Refresh tokens would be generated from your IDP(Identity Provider dynamically).
How is the flow to use a refresh token to get a JWT token?
Once you have the refresh token as shown in previous step, you can make a request to Token Endpoint with Refresh token to get Access Token
Access token