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:
- I sign a JWT with an expiry, say 7 days (should it be that long?)
- 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
- We check the timestamp whenever our
AppComponent
component is loaded, and see if not more than timestamp. - 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 localStorage
this 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_login
constant 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 AppComponent
which 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.