JWT refresh token in React+NodeJS - node.js

working on a small project and got some authentication going on with jwt tokens, the whole procedure looks like this:
Generate jwt token on auth/register along with a refreshToken
Make requests with the token
If the token is expired, I query the requesting user and his refreshToken, comparing his current request refreshToken and database token
If tokens match, I generate a new token and a new refresh token.
The whole problem is 5th step, lets say i make a request to "/me/friends" and along the way my token expires, I then make a new one out of my refreshToken, but I do not understand how should I return the token back to front-end on "me/friends" api call as it returns an array of specific fields and token has nothing to do with it. I just cant get my head around on how this is supposed to work, can anyone assist me please?

How are you storing your token on the client side? The easiest method is to just store it in a cookie. In that case, Step 5 just becomes setting an updated cookie with the request.
Another option is to return a 401-Unauthorized from your endpoint, then on the client side you can handle a 401 status code by trying to refresh the token manually and then retrying the request.
But I think option 1 is preferable if you're not using some sort of authentication middleware that doesn't hit the endpoint at all if auth is expired.

Related

Should i logout a user if access token is malformed?

I am creating a Node js / Express js based, login registration system using JWT (i am using JSONWEBTOKEN npm library).
Whenever a user login, that user gets a pair of access and refresh token. Now for accessing resources user need to send access token to backend.
Now when i verify the access token send by user to backend and if it will not get verified then it produces three types of error (as mentioned is JSONWEBTOKEN library in npm):
Token Expired Error: If i get this error, then in that case i will send response to frontend to send the request to refresh token route to get a new pair of access and refresh token.
JsonWebTokenError: If i get this error then it means that access token is malformed. Then in this case what should i do? Should i logout a user or should i will send a response to frontend to send request to refresh token route to get a new pair of access and refresh token. <-- This is the main question should i logout a user?
NotBeforeError: Since i am not using nbf claim and then in that case i dont need to worry about it.
Please provide your useful suggestion. while building backend security plays an important role.
This is useful to read: JWT refresh token flow.
Talking short, you should logout user if refresh token malformed or expired.
According to JWT idea, access token is short-life token. When it doesn't pass validation due to malformed or expired you have to send refresh token to server to get new pair. User continues to work using new access token without interruption.
If JWT is malformed then just block that call by responding with 403. that's fine. The application then takes the decision on it to refresh the token or not.
When a user logs out please revoke the issued token even if it is a JWT.
JWT also needs to be revoked as best practice. Yes, JWTs are self tokens and expirations already part of themselves. But if user logs out and still their JWTs are not expired means someone can use that token to call different APIs. So it is a security breach.
To avoid such things we should maintain JTI claim of that JWT in our backend with the same TTL with the value of JWT "exp". When the user logs out we have to clear those JTIs and notifcy the API callers about this just putting into some event service from their API Gateways should get to be notified and clear their side cached tokens if anything and cross check with identity system (Introspection).
This is we have to design the system to avoid further security related issues.
First thing is that user will be logged out from front end side.
front end will send request to your node server and token will be verified. Server will only send the response that token is expired or malformed and based on that front end will perform the action.
If token is expired then request for new token.
Is token is malformed then based on your requirements you can show results to your end user. You can either logout user or you can show unauthorized page too.
Suppose, you have role based website and some unauthorized user is trying to access root level routes then you can show unauthorized page.

Regenerate auth token

I have a flutter app with a node.js backend api. I'm using firebase Auth for authentication. The way it works now (which I don't know is standard,) is the user sends a request to firebase auth to login/signup. The jwt gets stored in the flutter app, then it sends that firebase jwt to my API, which verifies it's a valid token firebase.auth().verifyIdToken(), and my API sends over a new jwt created with firebase firebase.auth().createCustomToken(...) with custom info.
Before every response my API sends over, it checks if the custom jwt was created after 15 min. If it was, it recreates a new custom jwt. If it passed 7 days since it's original creation, it logs out the user.
The problem is, I don't see a way to regenerate a firebase auth token on the server. Which means every hour the user will have to re-login.
I feel I'm overcomplicating things, but I'm not sure of a better design of doing this. Is there a standard? How can I make this better and how can I make it that the user doesn't have to re-login after just 60 min?
The custom tokens created by createCustomToken() are used when you have a third party auth system but you want to login your users with Firebase auth.
The problem is, I don't see a way to regenerate a firebase auth token on the server. Which means every hour the user will have to re-login.
You don't have to do anything on the server. Every time you need to call your API, you can use getIdToken() to get user's ID token.
var token = await FirebaseAuth.instance.currentUser().getIdToken();
This will return user's current token and if it has expired then it'll a refreshed token. You can then pass the result to your API. There's no need to explicitly store the token anywhere yourself.
Whenever you are making an API request, the flow could be as simple as:
Get user's ID Token using getIdToken()
Pass this token in your API request
Verify it using verifyIdToken() and return the response.

how to do authorization (nodejs, express) with two tokens (access/refresh)

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.

JWT refreshing with refresh token

I am building SPA app with its rest API and I cannot find information when I should refresh JWT using refresh token. Should I do this when I will receive 401 HTTP status from server (JWT expired) or for example every 15 minutes if possible (before JWT will expire)?
I'm not a security expert, but as far we know, we
1- login and save the received token
2- we put one interceptor that check every response (in angular it's easy, in react we usually use axios ...etc)
3- we check every response in the interceptor, if the response was 401 and the expiration date from the token has passed, we send a refresh token request and save the new token
to check expiration date you can use a library that decode the token like: jwt-decode on npm, (don't forget to wrap the process in try...catch in case somebody screw with the token) and you even can paste the token in https://jwt.io/ and see for your self the decoded token and check the expiration date.
4- repeat the last request with the new token should succeed.
5- if for example even the refresh token request failed, simply redirect the user to the login page
If the server is sending a proper error code in case of access_token expired then you can intercept the error code on the client-side and use the refresh_token you got earlier during authentication to get a new access token. You can repeat this process again and again until your refresh token gets expired. On that occasion, you should redirect the user to perform the authentication to get both the tokens.

Refreshing JWT and securing sessions on client side app

I have a react app with a node/express back end. I am currently using JWT to make calls to protected routes on the back end. This all works fine. But I want to keep the user logged in for more than just 30 min or so.
What is the best way to handle securing sessions or refreshing an access token when it expires on a client side application?
My Solutions:
-One:
Create a refresh and an access token. Have the access token be short lived. And sign the refresh token with a unique id given to the user in the database. Then check verify the token with this id. Then when the access token expires send a 401 back and then get the refresh token from local storage to create new tokens and then try the call again.
Problem with this: there is a lot of back and forth going on and it seems slow.
-Two
Send both the refresh token and the access token on each call and if the access token is expired use the refresh token to create new tokens then proceed.
Problem with this: I don't see why I would then need to send 2 tokens I could just send one and get the job done with that. But then if one or both tokens become compromised they could regenerate forever.
-Three
Send the access token expiration to the front end and if the token is expired send the refresh token and verify it with the unique identifier in the database. Then generate new tokens and continue.
Problem with this: Not sure how secure this would be. But for now this seems like the best solution.
So I am wondering what is the best way to handle refreshing an access token when it expires so the user can keep using the platform?
I'm saying this from experience not a source but the whole idea of JWT s that it's sessionless. there's another solution for handling sessions.
With jwt, you don't need to save it in your database as you sign that JWT with a secret key and you can just verify that JWT has been issued using your secret key. and you can issue that JWT to be valid for more than 30 minutes. It's totally fine. I myself have set it to 180 days. and because it's so long, a user will log in again in this time so you don't have to worry about expiration. but if you want to handle that too, you can parse it in your front end and check it's expiration timestamp and get another JWT before it expires.

Resources