Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React Native + JWT still need refresh token?

When logging in, a JWT access token is sent from the server and saved in AsyncStorage in RN.

Now I want the user to stay logged for 5 years, until they either:

  • log out

  • admin revokes their token

  • they are logged in on 3 devices, change their password on one of the devices, which should log them out from the other 2 devices until they login again on those devices

  • lose their phone, and login from another device to log out from all devices

It looks like I'd have to store JWT tokens in the DB (I know that's not the point of JWT tokens and defeats the purpose they are serving based on my reading) but I would need to know the user's tokens, on their different devices, to be able to revoke them.

One thing that confuses me is reading that the access tokens should be short lived, say 60 mins, and refresh tokens long lived, say 5 years in my case.

What I don't understand is why can't we just use the access tokens to have a 5 year life span (for each device), save them against the user in the DB so we can identify their tokens and revoke their tokens based on the aforementioned points? What would be the point of a refresh token, would it even be needed in this case?

Note: I also read that we can't revoke access tokens, but can only revoke refresh tokens, so I am really confused. Would I have to send both an access token and a refresh token to RN, and only use the refresh token for the Authorization Bearer header and save only the refresh token in the DB? Then what would be the point of the access token if it's not the one in the DB?

I think this should be something simple to implement, but my criteria are the 5 year login and being able to revoke tokens based on the points above.

What's a correct solution for this situation?

like image 764
Wonka Avatar asked Jun 13 '17 06:06

Wonka


People also ask

Is refresh token necessary in JWT?

Since access tokens aren't valid for an extended period because of security reasons, a refresh token helps to re-authenticate a user without login credentials. This Refresh token is never exposed to the client-side Javascript, even if our access token gets compromised it'll be expired in a very short duration.

Is refresh token required?

Refresh tokens help improve the user experience (UX) around authentication. Since access tokens are typically only valid for a few minutes, an expired token can cause a user session to terminate without warning. Once that token expires, the user needs to reauthenticate to receive a new token and a new session.

How do you refresh JWT tokens automatically in react native?

React Refresh Token with JWT overview – A legal JWT must be added to HTTP Header if Client accesses protected resources. – With the help of Axios Interceptors, React App can check if the accessToken (JWT) is expired (401), sends /refreshToken request to receive new accessToken and use it for new resource request.

How do you handle token expiration in react native?

We need to do 2 steps: – Create a component with react-router subscribed to check JWT Token expiry. – Render it in the App component.


1 Answers

Access Tokens are short lived, which is by default 24 hours. But why? Why not 5 years?

  • Anyone with the access token is guaranteed access to whatever the user (to whom it was originally issued) can access. This means the server cannot differentiate between that user and anyone else who has the access token.

  • There is NO logging out. What I mean here is that you can have your front-end redirect to sign-in page to have him enter the credentials, but truly logging out does not happen in the server. Technically, the user can use the same access token to continue getting access (until it expires)

  • Access Tokens canNOT be revoked. Access tokens are invalidated only upon expiry. Anyone can use it until the token expires. For instance, if the expiry is set to 5 years and I happen to get your token by some chance, I can have all access that you have till it expires which in this case would be 5 years. This is exactly what gives more sense to set the expiry time lesser than 24 hours.

Now lets address your queries. "I want to user to be signed in until he"

  1. Logs out

Send refresh token to user after he signs in. Store both access token and refresh token very securely. After his access token has expired, use the refresh token to get a fresh access token. Loop this until he logs out. When he logs out, delete the access token and refresh token on the front-end and revoke the refresh token on the server side. (Again, if he somehow gets the access token, he still can access his account till it expires)

  1. Admin revokes token

The server can't revoke access tokens as I told before, once issued its valid until expiry, no matter what -> But only as long as the user has the access token :P Delete the access token as soon as he opens the app, if he did not last open the app in the past 1 hour or so. Now the front-end is forced to get a new access token using the refresh token it has stored. Now, you want the user to force logout? Revoke his refresh token.

  1. Logout on all devices after password change

Same as 2. After he changes password, revoke all refresh tokens issued (In case you don't want the user to sign in again, revoke all refresh tokens except for the current device). Your app on all devices will be forced to get a new access token using the refresh token, but since you revoked it, the user has no way other than to log in using his credentials.

  1. User-triggered logout from all devices

Same as 3. Changing the password triggers logout on all devices and here you just need to add a "Logout on all devices" button that will send a server request which revokes all refresh tokens except for the current device.

Caveat: Current user session cannot be closed; You need to wait for the user the exit the app, so as to have the current access token deleted. Workaround is to delete the access token as immediately as he closes the app (or even he minimizes the app) or setting the access token expiration to 30 minutes, provided you can tolerate the latency caused by obtaining new access token using the refresh token everytime he does that. You need to tradeoff time for security or vice-versa, depending on the your app specifications.


"That's all fine, but I don't want a refresh token in the first place" (Alternative Solution):

I don't encourage storing tokens as it defeats the very purpose of scaling and preventing easy DDoSes, by increasing the response time which increases due to querying the db. But since Redis is amazingly fast key-value store that runs on memory, some prefer storing access tokens in it. Well how does that work?

Setup: Once the user logs in, issue an access token. store it in Redis, then send it to user.

  1. Check JWT signature && token's integrity, if it fails hurray, no db query. Send back 404 user not found. This will be as quick as how JWTs without Redis function.

  2. If it succeeds, check Redis for the token. IF it exists, grant access. If it doesn't, ask the user to log-in again. Note that this will be a bit slower than granting access using just JWTs, but hey, you aren't storing in it Postgres or Mongo, which might take a few milliseconds to respond; Redis being a key-value store - and for it sits on memory (and not storage) - is considerable faster than those.

Access is granted if and only if both the conditions are satisfied: JWT is valid. JWT is present in Redis

Answering your queries:

Logouts are now possible. When user hits logout, delete from Redis the access token. He can't login even if he has the access token. Access Token is now literally invalid.

  1. Admin forces logout: Delete access tokens for that user from Redis.

After the user is successfully granted access by the server, you shall allow the user to issue a request to delete all other tokens with the same user-id (or uid) which will allow logout

  1. After password change, issue such a request.

  2. On Logout from other devices, issue such a request.

Finally the left out 1. Stay logged in until user logs out: Now that you have authority to invalidate access token which you didn't have when not using Redis, you can have a 5-year valid access token, provided you implement other required security measures to prevent misuse of the access token.

like image 126
Saravanabalagi Ramachandran Avatar answered Sep 27 '22 21:09

Saravanabalagi Ramachandran