JWT (JSON Web Token) Auto Renew

I would like to implement JWT authentication in our new REST API. But since the validity period is set in the token, can it be automatically renewed? I do not want users to have to register every X minutes if they actively used the application during this period. That would be a huge UX crash.

But renewal creates a new token (and the old one remains valid until its expiration). And generating a new token after every request sounds silly to me. Sounds like a security issue when more than one token is used at a time. Of course, I could invalidate the old one using the blacklist, but I would need to store the tokens. And one of the advantages of JWT is not storage.

I found how Auth0 solved this. They use not only the JWT token, but also the update token: https://docs.auth0.com/refresh-token

But then again, to implement this (without Auth0), I will need to store update tokens and maintain their expiration. What is the real use? Why not have only one token (not JWT) and save the expiration date on the server?

Are there any other options? Does the JWT use the wrong one for this scenario?

+403
security authentication api jwt
Nov 04 '14 at 15:41
source share
10 answers

I work in Auth0 and I participated in the development of the update token function.

It all depends on the type of application, and here is our recommended approach.

Web applications

A good template is to update the token before it expires.

Set the token validity period for one week and update the token every time a user opens a web application and every hour. If the user does not open the application for more than a week, they will have to log in again, and this is an acceptable UX web application.

To update the token, your API requires a new endpoint that receives a valid but not expired JWT and returns the same signed JWT with a new expiration field. Then the web application will store the token somewhere.

Mobile / Native apps

Most embedded applications register once and only once.

The idea is that the refresh token never expires and can always be exchanged for a valid JWT.

The problem with a token that never expires is what never means never. What will you do if you lose your phone? Thus, the user must somehow identify the user, and the application must provide a way to revoke access. We decided to use the device name, for example. "Maryo iPad". Then the user can go to the application and revoke access to the "maryo iPad".

Another approach is to cancel the update token for certain events. An interesting event is the change of password.

We believe that JWT is not suitable for these use cases, so we use a random generated string and we save it on our side.

+465
Nov 09 '14 at 23:45
source share
โ€” -

In the case when you handle auth yourself (for example, you are not using a provider such as Auth0), the following may work:

  • Issue a JWT token with a relatively short validity period of, say, 15 minutes.
  • The application checks the expiration date of the token before any transaction that requires a token (the token contains the expiration date). If the token has expired, then it first requests the API to "update" the token (this is done transparently for UX).
  • The API receives a token update request, but first checks the user database to determine if the 'reauth' flag has been set for this user profile (the token may contain a user ID). If the flag is present, the token is updated, otherwise a new token is issued.
  • Repeat

The 'reauth' flag in the database backend will be set if, for example, the user has reset his password. The flag is removed the next time the user logs in.

In addition, let's say you have a policy according to which the user must log in at least once every 72 hours. In this case, the API token update logic will also check the date the user last logged into the user database and prohibit / enable token updating on this basis.

+58
Feb 20 '15 at 2:05
source share

I messed around moving our applications to HTML5 using a RESTful apis in the backend. The solution I came up with was:

  • Upon successful login, the client receives a token with a session time of 30 minutes (or regardless of the normal session time on the server side).
  • A client-side timer is created to call the service to update the token before it expires. The new token will replace future challenges.

As you can see, this reduces the frequency of update token requests. If the user closes the browser / application before the token is resumed, the previous token will expire in time and the user will have to re-enter the system.

A more complex strategy can be implemented to service user inactivity (for example, ignore the open browser tab). In this case, the repeated call of the token should include the expected expiration time, which should not exceed the specified session time. The application will need to monitor the latest user interaction.

I donโ€™t like the idea of โ€‹โ€‹setting a long validity period, so this approach may not work well with native applications that require less frequent authentication.

+11
May 21 '15 at 3:00
source share

An alternative solution to invalidate JWT without additional protected memory on the backend is to implement a new jwt_version integer column in the users table. If the user wants to log out or issue existing tokens, they simply increase the jwt_version field.

When creating a new JWT, encode jwt_version into a JWT payload, optionally increasing the value in advance if the new JWT should replace all the others.

When checking the JWT, the jwt_version field jwt_version compared to user_id , and authorization is granted only if it matches.

+11
May 31 '17 at 9:19 a.m.
source share

Good question- and there is a lot of information in the question itself.

The article " Update tokens: when to use them and how they interact with the JWT" gives a good idea for this scenario. Some moments: -

  • Update tokens contain the information necessary to obtain a new access token.
  • Update tokens may also expire, but they are quite long-lived.
  • For upgrade tokens, strict storage requirements are usually applied so that they do not leak.
  • They can also be blacklisted by the authorization server.

Also take a look at auth0 / angular-jwt angularjs

For web API. Read Enable OAuth Update Tokens in an AngularJS Application Using ASP.NET Web API 2 and Owin

+8
Aug 26 '16 at 17:50
source share

jwt-autorefresh

If you are using node (React / Redux / Universal JS), you can install npm i -S jwt-autorefresh .

This library plans to update the user's JWT tokens, calculated a few seconds before the expiration of the access token (based on the exp request encoded in the token). It has an extensive set of tests and checks quite a few conditions so that any strange activity is accompanied by a descriptive message about incorrect configurations from your environment.

Full example implementation

 import autorefresh from 'jwt-autorefresh' /** Events in your app that are triggered when your user becomes authorized or deauthorized. */ import { onAuthorize, onDeauthorize } from './events' /** Your refresh token mechanism, returning a promise that resolves to the new access tokenFunction (library does not care about your method of persisting tokens) */ const refresh = () => { const init = { method: 'POST' , headers: { 'Content-Type': `application/x-www-form-urlencoded` } , body: `refresh_token=${localStorage.refresh_token}&grant_type=refresh_token` } return fetch('/oauth/token', init) .then(res => res.json()) .then(({ token_type, access_token, expires_in, refresh_token }) => { localStorage.access_token = access_token localStorage.refresh_token = refresh_token return access_token }) } /** You supply a leadSeconds number or function that generates a number of seconds that the refresh should occur prior to the access token expiring */ const leadSeconds = () => { /** Generate random additional seconds (up to 30 in this case) to append to the lead time to ensure multiple clients dont schedule simultaneous refresh */ const jitter = Math.floor(Math.random() * 30) /** Schedule autorefresh to occur 60 to 90 seconds prior to token expiration */ return 60 + jitter } let start = autorefresh({ refresh, leadSeconds }) let cancel = () => {} onAuthorize(access_token => { cancel() cancel = start(access_token) }) onDeauthorize(() => cancel()) 

disclaimer: I support

+6
May 27 '16 at 7:43
source share

I really implemented this in PHP using the Guzzle client to create a client library for api, but the concept should work on other platforms.

Basically, I give out two tokens, one short (5 minutes) and one long, which expires in a week. The client library uses middleware to try to update a short token if it receives a 401 response to some request. Then he will again try to fulfill the initial request and, if he can update, will receive the correct answer, transparent to the user. If it fails, it simply sends 401 to the user.

If the short token has expired but is still authentic, and the long token is valid and authentic, it will update the short token using a special service endpoint that checks the long token (this is the only thing that can be used for). He will then use the short token to get a new long token, thereby increasing it by another week every time he updates the short token.

This approach also allows us to revoke access for no more than 5 minutes, which is acceptable for our use without the need to keep a blacklist of tokens.

Later editing: after re-reading these months after it was fresh in my head, I should indicate that you can cancel access when updating a short token, since it gives an opportunity for more expensive calls (for example, a call to the database to see if the user was blocked), without paying for it every time you access your service.

+6
Dec 13 '16 at 21:00
source share

How about this approach:

  • For each client request, the server compares the expirationTime of the token with (currentTime - lastAccessTime)
  • If expirationTime <(currentTime - lastAccessedTime) , it changes the last lastAccessedTime to currentTime.
  • In case of inactivity in the browser for a time longer than the expirationTime period, or in the case of closing the browser window and expirationTime> (currentTime - lastAccessedTime) , and then the server can expire the token and ask the user to log in again.

In this case, we do not need an additional endpoint for updating the token. Would thank any feed.

+2
May 10 '16 at 21:31
source share

I solved this problem by adding a variable to the token data:

 softexp - I set this to 5 mins (300 seconds) 

I set the expiresIn option at the desired time before the user is forced to log in again. The mine is set for 30 minutes. This should be greater than softexp .

When a client-side application sends a request to the server API (where a token is required, such as a client list page), the server checks whether the supplied token remains or not, based on its original expiration value ( expiresIn ). If this is not valid, the server will respond the status defined for this error, for example. INVALID_TOKEN .

If the token is still valid based on the expiredIn value, but it has already exceeded the softexp value, the server will respond with a separate status to this error, for example. EXPIRED_TOKEN :

 (Math.floor(Date.now() / 1000) > decoded.softexp) 

On the client side, if he received an EXPIRED_TOKEN response, he should update the token automatically by sending an update request to the server. This is transparent to the user and automatically takes care of the client application.

The update method on the server should check if the token is valid:

 jwt.verify(token, secret, (err, decoded) => {}) 

The server will refuse to update tokens if it has not completed the above method.

+2
Aug 04 '17 at 21:29
source share

Below are instructions for revoking your JWT access token:

1) When you log in, send 2 tokens (access token, update token) in response to the client.
2) The access token will have less expiration time, and the update will have a long expiration time.
3) The client (Front end) will store the update token in its local storage and access token in cookies.
4) The client will use the access token to call the API. But when it expires, select the update token from the local storage and call the api authentication server to get a new token.
5) An API will be opened on your authentication server, which will accept the update token, check its validity and return a new access token.
6) When the update token expires, the user will be logged out.

Please let me know if you need more information, I can also share the code (Java + Spring boot).

0
Jan 26 '19 at 12:26
source share



All Articles