how to do authorization (nodejs, express) with two tokens (access/refresh) - node.js

Good evening, I ran into a problem that I need to make authorization more secure and without re-logging. I read on the Internet that you need to use two tokens (access and refresh), but how to properly do authorization with them. You can advise a resource where competent authorization with two tokens is made.
My Tech Stack:
MongoDB
ExpressJS
ReactJS
NodeJS

If you request authentication with offline_access scope, you'll geta refresh token in addition to an access token. Save this refresh token to the database and whenever you need to make another call on behalf of the user you can
Make the call using your existing access token. If you don't get a 401, then you're good.
If you did get a 401, your token is probably expired and then you can call the token end point on the authorization server with the refresh token and grant_type=refresh_token to get a new access token and try your call again.
Might make the most sense to always request a new access token using your refresh token before you make another call.

To my knowledge you only deal with access tokens for authorization. The refresh token is only there to refresh an expired access token. The refresh token is exchanged for a new access token - without needing to present authentication credentials again. The call also (typically) takes a fraction of the time than re-authenticating.

as soon as the user log-in, give it two tokens refresh and access, store the refresh token in the database, give access token a expire time (5-10 min approx or less depending on your requirement).
for each request user will use the access token and for each request backend should check for the expired access token.
if the access token is expired, user will get a new access token by sending the stored refresh token to the backend(using a dedicated endpoint), backend will than check whether the refresh token is present in the database or not, if yes a new access token with new expire time will be sent in the response.
the cycle will continue until the user logs-out, in that case the refresh token will be deleted from the database and after some time access token will also get expire.

Related

How to regenerate Refresh Token and Access Token on Resource Request?

I am trying implementing JWT Tokens(Access tokens and Refresh tokens), but I come to an issue on requesting a protected resource with an expired access token, while the refresh token is still valid.
I know that I should not use refresh tokens to request resources, refresh tokens should be used against authorization validators to revalidate/regenerate access tokens.
In my app, the User can log in by POST request with a valid credential to get Access token(exp. in 1min) and Refresh token(exp. in 10min.). Say now User making a request 30 sec later of login and sends both tokens, then tokens get checked and resource comes back. If now user makes a request after 2min and sends tokens, his access token is Invalid, in this scenario how can I proceed with the request and revalidate tokens.
I can think of middleware to validate and provide tokens and send that with the response, but is this the right approach?
Then I need to handle and restore tokens on the client-side for every response. Don't I?
Also, I do not want to prompt users to re-login. I am using Node and Express for Server and React on Client.
Here are your steps:
Try to login
Receive 401 from server when token is invalid
Request a new access token by making a new refresh request.
Set the new access token and refresh token
Retry original request
This has to be done on the client side because it is the audience that gets validated for authorization.
Usually we don't set the access token to expire every minute because the described process would add too much latency to the process.
Edit from #MComment:
5 min for access tokens and 30 min up to a few hours is what is generally recommended for respectively access and refresh tokens. Usually Authorization Servers offer "rolling refresh" - refresh token's expiration is renewed whenever you use it. This way a user stays logged in as long as they are actively using the website
You can update expired date of access token in every request, no need to regenerate token.
I think session time you set is not normal and recommended.
If you dont want user must re-login, make a forever refresh token, create a function in reactjs for re-generate access token by refresh token if it expired.
Revoke refresh token only when u want to logout from this client.

Do I use a refresh token?

I have an application that doesn't have user accounts so doesn't need a login. I'm currently authenticating using JWT via a /get-token endpoint in my api that's called as soon as the UI starts and returns a bearer token that's used for the calls for the calls moving forwards/
When that token expires, i'm a little confused at how to handle that. I was thinking using a refresh token but all the tutorials i've seen are passing the refresh token back to the UI, isn't that unsafe? I was always under the idea that the refresh token was internal and is only used on the server to refresh expired tokens.
What's the best way to handle this?
Refresh tokens carry the information necessary to get a new access token. In other words, whenever an access token is required to access a specific resource, a client may use a refresh token to get a new access token issued by the authentication server. Common use cases include getting new access tokens after old ones have expired, or getting access to a new resource for the first time. Refresh tokens can also expire but are rather long-lived. Refresh tokens are usually subject to strict storage requirements to ensure they are not leaked. They can also be blacklisted by the authorization server.

Generating refresh tokens and access tokens in node server

I'm building mobile and a web app. Both apps will be talking to a node server. I am using JWT for authentications.
Currently, I have the following code to generate an access token:
const token = jwt.sign({ user: body }, "top_secret");
I have some questions about access and refresh tokens:
How to create a refresh token?
What do refresh token look like?
Can I create a refresh token - similar to the way I'm creating an access token?
Is the refresh token only used to generate a new access token?
Can the refresh token be used as an access token?
How do you invalidate an access token
How do you invalidate a refresh token? Examples I've seen used databases to store refresh tokens. The refresh tokens are deleted when you want to invalidate an access token. If the refresh token would be stored in the database on the user model for access, correct? It seems like it should be encrypted in this case
When the user logs into my application, do I send both access token and refresh token? I read somewhere (can't remember where) that it's not good practice to send an access token and refresh token.
If its bad practice to send both access and refresh tokens, when do you send a refresh to the client? Should there be an endpoint where the clients request an access token?
What's a good expiry time for access tokens and refresh tokens?
Please note that in typical OAuth2 scenarios, the server issuing tokens (authorization server) and the API server consuming access tokens (resource server) are not the same. See also: Oauth2 roles.
To answer your questions:
How to create a refresh token?
You generate a string of sufficient entropy on the server and use it as a primary key to a database record in the authorization server. See refresh token syntax.
What do refresh token look like?
From https://www.rfc-editor.org/rfc/rfc6749#section-1.5,
A refresh token is a string representing the authorization granted to the client
by the resource owner.
The string is usually opaque to the client.
Can I create a refresh token - similar to the way I'm creating an access token?
You can, but refresh tokens are typically not structured tokens (like JWT) since they're consumed by the same server that issued them.
Is the refresh token only used to generate a new access token?
yes
Can the refresh token be used as an access token?
no
How do you invalidate an access token
Unless you're using introspection tokens, there's not a good way to invalidate them. Just keep their lifetime short.
How do you invalidate a refresh token? Examples I've seen used databases to store refresh tokens. The refresh tokens are deleted when you want to invalidate an access token. If the refresh token would be stored in the database on the user model for access, correct? It seems like it should be encrypted in this case
Delete if from the authorization server store. If the refresh token cannot be found on the server, it cannot be used to refresh an access token. A refresh token is typically just a primary key to a database record holding data about the client, user and expiration of the refresh token. While you don't want to leak your refresh token, it typically does require the client using them to present client credentials to use it.
When the user logs into my application, do I send both access token and refresh token? I read somewhere (can't remember where) that it's not good practice to send an access token and refresh token.
The user signs in at the authorization server. It returns an access token and refresh token (if your client is confidential) to the client. The client uses the access token alone to access your data on the resource server.
If its bad practice to send both access and refresh tokens, when do you send a refresh to the client? Should there be an endpoint where the clients request an access token?
Your client uses the refresh token in a call to the authorization server to get a new access token. So your client sends only the access token to the resource server and only the refresh token to the authorization server.
Whats a good expiry time for access tokens and refresh tokens?
That depends on your threat model. When your refresh token expires, the user is forced to authenticate again. Some products use refresh tokens that never expire, others use refresh tokens that are only valid for hours or days.

Access Token and Refresh Token flow

I have read about JWT and access token and refresh token. I understand that you have to set access token expiration in a very short time (minutes) and use refresh tokens to obtain a new access token whenever is expired.
Three things are not clear to me:
Who checks access token for expiration? Is client checking that and requesting a new access code by sending expired access token along with refresh?
Who checks refresh token for expiration? (obviously refresh token needs expiration as well although it takes longer to expire).
From my point of view if a refresh token is expired, the user must be prompted to re-login. This is something that needs to be avoided in some scenarios (mobile apps). How can it be avoided?
Answer your question:
The API use access token will return error when access token expired.
The API use refresh token to get a new access token will return specific refresh token related error.
About refreshing of the refresh token, please see the below answer.
Generally you need do some error handing for each API calling.
About refreshing of the refresh token
I investigate more, and this is what I found:
first time login and authorized to get access token and refresh token(optional), if access token never expire refresh token is not necessary. => https://www.oauth.com/oauth2-servers/access-tokens/access-token-response/, recently(2019/11/16), I found this really depend on the implementation of the API providers, for example, PayPal, They provide access token with expired time but without refresh token, so when the access token expired, you have to get a new access token again.
when access token expired, use the refresh token to get a new access token and refresh token(optional) => https://www.oauth.com/oauth2-servers/access-tokens/refreshing-access-tokens/. this time you have a new refresh token, which means you have a new refresh token every time you refresh a access token. if the response don't have a new fresh token, you only have the old refresh token from the first step.
If user don't use the app for a long time, then user don't have chance to refresh the access token and refresh token, then user need to re login again after long time when refresh token expired.
like #jwilleke said, even user do not use the apps, the server side or the apps can do it for the user automatically, then it will always have the new access token and refresh token.

Using Refesh Token in Token-based Authentication is secured?

I am building a token based authentication (Node.js using passport/JWT with an angular client).
After the user enter his credentials he gets an access token, which he sends in every request inside the header (header: bearer TOKEN).
I don't want to prompt a login request everytime his access token expires (about everyday I guess),
I've heard about the Refresh Tokens. The refresh token never expires (or rarely expires) and able to renew tokens indefinitely.When the access token is about to expire, the client can send a renew request to get a new access token by sending his refresh token.
I don't understand few things, I might be missing something:
How a long-living/never expiring refresh tokens don't ruin the security of having short-living
access tokens.
Cookies can be stole and be used until they expire. Tokens are short living so they more secured,
but if I provide a long-living refresh token I lose the advantage of using tokens.
NOTE: I am aware that the refresh tokens are sent at the initial login, so cann't be spoofed in every request, but if they are spoofed at the initial request they are vulnerable.
The refresh token is presented on a different path than the access token: the access token is only ever presented to the Resource Server, the refresh token is only ever presented to the Authorization Server. The access token can be self-contained so that it does not need costly calls to the Authorization Server to check its validity, but to mitigate loss and to increase accuracy (it cannot be revoked in case something goes wrong) it is short-lived. The refresh token is long lived and gets validated on each call to the Authorization Server and as such it can be revoked. The combination of the two makes the system secure.
I use the following approach:
Tables/indexes:
User table (just has the user ids and all the user related meta-data)
JWT table (three fields : user_id, access_token, refresh_token)
Authentication Flow
1.When a previously unauthenticated user signs in, issue a JWT which contains an access token, and a refresh token. Update the refresh token in the JWT table, together with the user_id, and the access token.
2.Make sure that the JWT has an expiration time that is something small/comfortable for your users. Usually less than an hour.
4.When a client makes a request with a JWT
a. Check expiry of the access token. If the token has not expired -> continue without hitting any db tables.
b. If the access token has expired, lookup the user_id in the JWT table, and check if the refresh token and access tokens match, whatever the client has provided,
If yes, issue a new JWT with the response and update the new refresh token,access token into the JWT table.
if no, return 401. The client is forced to ask the user to then sign in.
END.
To summarize,
1.DB calls are required only to check if the refresh token is valid.
2.This system allows for a user to sign in from any number of devices, with any number of JWT's
3.All JWT's related to a user can be invalidated, by wiping the refresh tokens related to that user from the JWT table, this can be done, for eg: when a user changes his/her password. This, in effect, narrows down the window of compromise to the expiration time of the access token/JWT.
I believe this is the intention behind JWT's. The percentage of DB calls/user depends on your expiration time, the duration a user is usually on your website, etc.

Resources