Node.js Express: Access token refresh: how to ensure user's request is not interrupted?

68 views Asked by At

I cannot for the life of me figure out how to refresh a user's auth tokens without interrupting their original request...

I have one solution, but there's a problem.

Let's say a user logs in, my server generates an accessToken and a refreshToken using JWT:

  • The accessToken is saved in a cookie, it's short-lived, say 15 minutes, its expiration date is sent directly to the user

  • The refreshToken is sent directly to the user and saved in localStorage, it's long-lived, say 30 days

For every request that involves accessing resources, the server checks the accessToken cookie for validity. So let's say a user wants to edit their profile: /profile/edit, and the body data is as follows: {name: "My New Name"}

  • If the accessToken is invalid (e.g. expires), then the user's request is denied and they are redirected back to the login page.

  • To ensure an accessToken does not become invalid, the user's web browser will check the expiration date of the accessToken (localStorage.getItem("accessTokenExpirationDate"), say every 1 second

  • If the accessToken is about to expire, the user will send a /refresh GET request with data: {refreshToken: localStorage.getItem("refreshToken")

  • The server then refreshes the access/refresh token and sets them accordingly

This works. But the problem is if the user closes their browser, comes back in say 30 minutes, and they go back on the website, they will be redirected to the login page, despite still having a valid refresh token. Because the timer was not running to actively check the access token expiration, a /refresh request was never sent...

Is there another solution to ensure a user does not get redirected to the login page? How do I refresh the token on the same request?

Or is there an update for my current solution so if the user closes their browser and then returns, they will be able to continue using the website resources normally without having to re-login?

1

There are 1 answers

4
Oo_x_oO On

Discount, no need to use a login page when a user is already logged in.

If you want to use it then it is necessary to disconnect.

When redirected to the login page, a request is made to receive an access token if the refresh token is valid. If the request was successful You are returned to the previous page that "threw" the user who was not logged in.

From your question I understand that you store the refresh token in local storage. Warning! please find alternatives to store refresh-token like http-cookie. You are exposed to an XSS attack

function isAlreadyLoggedin(){
    // load refresh-token exp with convert to Date
    const refreshTokenExpirationDate = new Date(localStorage.getItem("refreshTokenExpirationDate"));

    // case: Refresh-token exp,  User must re-login!
    if (Date.now() > refreshTokenExpirationDate) {
        return;
    }

    // load access-token exp with convert to Date
    const accessTokenExpirationDate = new Date(localStorage.getItem("accessTokenExpirationDate"));

    if (Date.now() > accessTokenExpirationDate) {
        if (renewAccessToken() === true) {
            // browser automatic back to http://your-url/profile/edit
            window.history.back();
        }
    }
}
isAlreadyLoggedin();