JWT tokens flow - log out case - node.js

I am creating node.js/express project. Authentication is done based on JWT. Details:
When user log in, in response there is access token (validation: 15 minutes) and refresh token (validation: 24 hours). In payload of each token there are user's most neccessary data and unique identifier which is used to make these token kind of pairs. These tokens are "bond". On logout this identifier is put on blacklist - for more read below.
In each request I check access token: a) if token is real token (not faked one), b) if it is expired or c) token contains in its payload an unique identifier which was put on the blacklist. In case access token expired check out no 3 below.
When access token expired, there sie /refreshToken endpoint where user can refresh both access token and refresh tokens. In case unique identifier is in the blacklist token will not be refreshed and user should re-authenticate.
And finally, there is /logout endpoint where user pass access token in request. And again, if unique identifier is in blacklist there is error in response. However if access token is valid, unique identifier is put on the blacklist and user is logged out.
What I need to mention here is I do not store refresh tokens in database as in many other solutions. All is based on unique identifier.
Basically, my goal was to be sure that when user logged out (access token in request), no one will use refresh token to regain access token. In this solution both tokens should be useless.
What do you think of this flow. What do you think of unique identifier which pairs both access and refresh token?
Would you improve that in any way?

Related

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.

Check/ Decode auth0 Access Token

I need to know the time remaining in the Access Token and not the ID token or the token for browser flows. Checking the expiry of the token on http://www.jwt.io always returns 24 hours. However, the Access Token for the API should be longer than that. How can I check the expiring date?
If the authorization server provides an endpoint to get information about the token (the ideal would be to have an Introspection endpoint as per the RFC7662), then it is easy to have this information.
Otherwise, if no endpoint is available, you have to keep in you memory the value in the expires_in parameter of your access token response (see RFC6749 section 4.1.4) and add the current timestamp to this value to get the exiration timestamp.
Please note that the access tokens you receive may be revoked by the authorization server thus the token will be invalid before that expiration time.
Another possibility if the access token is a signed Json Web Token (JWS - see RFC7515), you could parse the token and check the exp claim (optional, but usually present in such context).

Revoking Bearer Token and Refresh Token - ServiceStack

I want to enforce a single user session feature for my Angular app because my customers share a single account with their coworkers.
The issue currently, with my implementation. is revoking a valid token stored a client's local storage, particularly a valid Refresh token.
The scenario is:
User 1 logs in with valid username and password, the bearer token will expire in an hour, the refresh token will expire in two weeks
User 2, uses the same username and password two hours later. User 2 is prompted that they are logged in on another device and asked the question of they would like to expire that session and start a new session.
User 2 says yes and the now User 1's session in invalid.
The problem is that User 1 still has a valid Refresh token.
I have no way revoke this refresh token. My Auth API will accept is valid and I will not know whether it is User 1 or User 2's refresh token.
Do I need to start storing refresh token values in my database to resolve this issue? I also thought I could use a different JwtAuthKeyBase64 for User1 and User2, as a way to invalidate User1's token but this doesn't seem like a good way to be using the ServiceStack JwtAuthProvider.
The JWT RefreshToken is used to contact the Auth Server to fetch a new JWT Bearer Token. It will only return a BearerToken if the User still has Access so you can lock the User Account by populating UserAuth.LockedDate which will prevent the user from retrieving a new JWT Bearer Token.
If you want more custom validation you can implement IUserSessionSource and throw an Exception in GetUserSession() to return an Error Response instead of the JWT Bearer Token.

What is the workflow for validating a refresh token and issuing a new bearer token?

This is not a coding question, but a conceptual question for the correct handling and processing of a refresh token.
I have a single page app which issues a jwt token when logging in. The token works just fine. Now, I want to set the expiration to a low value, and use a refresh token to refresh the bearer token.
The question is, what claims should be stored in the refresh token? And what steps are supposed to be done to validate the refresh token before issuing a new token?
For example, right now my refresh token is a jwt which stores an expiration, so the client knows when the refresh token expires, and a username claim so that I know what user the refresh token is associated with.
So then when the refresh token is recieved:
Check that it is not expired.
Check that it has not been revoked.
Use the UserName in the refresh token to issue a new short-lived bearer token.
Is this the correct workflow for this? I just want to make sure I am not missing any security checks.
If your application is a single page application, you should not use long lived refresh tokens as you have no way of securely storing them.
OAuth2 defines a number of grant flows for different types of clients (which I've described here). Refresh tokens are only meant for confidential clients (like web applications living on a secured server).
Your refresh token is just as vulnerable to theft as your access token, since both are bearer tokens stored on the client.
Some OAuth libraries allow SPA or other non-confidential clients to get a new access token by talking to the token endpoint of the authorization server using a session token in a cookie. As long as the cookie is valid, the user can get a new access token. After that, the user will need to re-authenticate. Of course cookies can be marked secure and http only, making them harder to steal.
If you issue the JWT tokens from the same service endpoint that consumes the access tokens, you could have the client include a nonce in the token request that you hash and include as a claim in the token. The client can send the JWT in the Authorization header and the nonce in a custom header. Your token verification would hash the nonce again and compare it to the claim in the JWT. That way, if your token is stolen is harder to use without the nonce value. Of course, in a targeted attack, your nonce could also be stolen.

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