Javascript

Auto Sign Out on Client Expire JWT Angular

You’re using JWT for Authentication with your API. You have Angular on the frontend, speaking to an Express backend API. You sign your JWT to expire within a certain timeframe. How do we expire JWT? To prevent “401 Unauthorized” attempts, how do you log out the user on the client automatically when the expiry time on the server is about to expire or expires?

Here’s how I approached mine. You might find it useful.

The steps involved are:

  1. I sign a JWT with an expiry, say 7 days (should it be that long?)
  2. When the JWT is saved on the client browser to append to future Auth requests, a timestamp is added as to when it should expire
  3. We check the timestamp whenever our AppComponentcomponent is loaded, and see if not more than timestamp.
  4. If more, redirect to login, otherwise, that’s fine.

Enough talking. Shall we see some code?

Yes! Code

Our response from authentication (login) can look something like this with the signed token:

router.post('/login', function(req, res) {
    // Login logic here bla bla
    // If all success
    return res.json({
        'state': true,
        'token': "JWT" + " " + jwt.sign({
            'email': user.email,
            'username': user.username,
            '_id': user._id
        }, config.secret, { expiresIn: 60 * 60 * 24 * 7 }) // one week
    })
})

We sign with an expiry.

On the client, we consume and localStoragethis token like so:

  login(email_username: string, password: string) {
    const params = {
      email_username: email_username,
      password: password
    };

    return this.http.post(AppSettings.API_ENDPOINT + '/auth/login', JSON.stringify(params), {headers: this.headers})
      .map((res) => {
        localStorage.setItem('token', res.json().token);
        const time_to_login = Date.now() + 604800000; // one week
        localStorage.setItem('timer', JSON.stringify(time_to_login));
        return res;
      });
  }

We save a localStorage item as token with value of res.json().token.

As we do, we initiate a timer timestamp of the current time plus 1 week more, all in milliseconds.

Date.now()method returns the number of milliseconds elapsed since 1 January 1970 00:00:00 UTC.

This means our time_to_loginconstant is now 1 week ahead of current time.

What if the browser’s clock is wrong? That might be a downside of this approach of generating the Date.now() on the client, rather than sending in the data from the server.

Whichever way you do it, works. I’m doing it on the client side, trusting anyone using the site is doing so with proper dates. Heck, if your date is 3 months wrong, the site won’t be accessible since I use LetsEncrypt, and the certificates are 3-months-issued

Then eventually, in our AppComponentwhich has something like the <router-outlet></router-outlet> from which the entire application in injected through, I can have this:

  ngOnInit() {
    const timer = JSON.parse(localStorage.getItem('timer'));
    if (timer && (Date.now() > timer)) {
      this.auth.logout();
      this.router.navigate(['/login']);
    }
  }

Tadaaa! Again, trusting client’s time is correct.

In any case, the worst thing that could happen is user logging in every single time app is reloaded. Which is, I think enough punishment, for living a timeless life online.

Conclusion

I hope you found this useful. Will see you in the next one.

 

Related Articles

Back to top button