Search code examples
javaauthenticationoauth-2.0jwtrefresh-token

How and why handle jwt token expiration with refresh_token, is there another alternative?


I have two wars: app.war(struts web app) and rest.war(classic rest api).

app.war access rest.war by jwt token which is generated once user login app.war successful.

When user use a.war, some data need to be got from rest.war by sending ajax calls from jsp of a.war with jwt token.

The expired time of jwt token is 15 mins, while session timeout of app.war is 1 hour.

However, if jwt token is expired, there is pop up ask for user login again even and user still can access app.war.

There is one alternative: use access_token and refresh_token, if access_token expired, then use refresh_token to get new access_token and refresh_token.

For this approach, I have some questions:

First, Why use two tokens? because i think they are the same, just refresh_token live longer than access_token and use refresh_token to get new access_token, so why not just access_token and set its expired time longer?

Second, is it same algorithms to generate access_token and refresh_token, just their expired is different?

Third, if client perform several api invocations (sync & async) using the token, how handle if one of that invocations return the 401 (token expired) ?


Solution

  • As you said, refresh_token is the recommended alternative to deal with jwt expiration.

    why use two tokens?

    Because the use of two tokens (access_token and refresh_token) is a verified strategy used by world class companies (google, azure, amazon, etc) which trust in The OAuth 2.0 Authorization Framework

    Which is a product of the Internet Engineering Task Force (IETF) which in turn is : The Internet Engineering Task Force (IETF) is an open standards organization, which develops and promotes voluntary Internet standards, in particular the standards that comprise the Internet protocol suite.

    You can use the oauth2 framework rigidly complying its specification, create and hybrid focus on your custom requirements or develop a new framework with new concepts

    so why not just access_token and set its expired time longer?

    Oauth2 spec does not recommend a non-expirable token. Token word itself mean a expirable thing. If it doesn't expire, we could use a password.

    For example let's imagine a mobile app which needs a token to download some user information. If token does not expire, a thief could steal the mobile app, enter and access to the user info. But as token means expiration, the thief could have a time limited access. Also token could be revoked by the user at the steal time, so the thief could not has access.

    Commonly when token expire, a login is forced. But there some requirements in which user doesn't want to login and login again every 3600 ms. So refresh_token helps to don't disturb to our user and get a new access_token without human login. Now, what happen if refresh_token didn't expire? Can we create access-tokens from months or years? That is why refresh_token must expire too

    is it same algorithms to generate access_token and refresh_token, just their expired is different?

    I implemented a kind of security server and I used the same algorithm with different expiration. But I added a extra claim to to differentiate them:

    Several invocations needs the access_token

    In this case, if token is renewed at every user login, you will have an access_token ready to use with 3600ms of life.

    After that your user is kind of robot ( or is a feature/requirement of your web ) and start to use multiple forms which perform several invocations to your rest api attaching the access_token.

    If we are in the 3601ms, in the next api invocation from web, the api must return a 403 error and show a classic popup: Session expired, click here to login again...

    If your requirement is avoid this popup, you could choice one of these approaches:

    • Renew token using the refresh token on 403 error. In this case you could use axios-retry to deal with retry on error.
    • After login, start an async task to renew the token at intervals less than token expiration. 3400ms in our example. So api invocations from your web never fail

    Advice

    Perform access_token and refresh_token exchange in your backend layer, not in frontend (ajax) layer.

    So the attackers will never know your endpoint to get tokens or refresh them.