On some sites who use jwt and refresh token, I noticed that refresh token is just a random string of 25 or more characters, now I have a question: can a refresh token be generated in the same way as access, that is, through the jwt library? Then it will not be just a random string, but a token with payload, etc., and it will be easier to validate.
You don't need anything beyond a random string for the refresh token. You only need to look it up in the authorization server and there is not need for some more magic feature than that. Keeping it simple. The client receiving the refresh token does not need to validate it either.
Related
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.
On my token authentication, I have two tokens, one is a short term access token and another is a long time refresh token. I want to implement a refresh token rotation. So I'm going to hash the refresh token and then save to the database. When the refresh token is reused each time, I will revoke all refresh tokens on this token family.
I used bcrypt to hash the refresh token and I was using the JWT way to generate a refresh token initial. However, as bcrypt has the max input, 72 bytes, which is smaller than the JWT token length, it will result to different JWT tokens having the same bcrypt salt value if their init 72 bytes are same.
So I'm going to use uuid to generate the token string plus the expire time to replace the JWT way.
I want to know if this uuid random string way is secure to replace the JWT? And I also concern if UUID is unique enough for token authentication.
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
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 :).
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