#100DaysOfMERN - Day 42

#100DaysOfMERN - Day 42

·

4 min read

✏ Secure Authorisation

Three posts ago, I thought authorisation is mainly a backend task.

LITTLE DID I KNOW.

The implementation on the frontend is just as important, and often it's done wrong, especially in tutorial videos. Many use localStorage, which is the most insecure way to authorise a user.

Frontend authorisation with cookies or local storage is perfectly fine for an application where you only store something meaningless like a nickname and a highscore. But whenever actual data like email addresses and passwords are involved, you really want to make sure that you don't expose your users to attacks.

If your app allows that evilCoder9 can easily get access to a user's personal data, you're making them vulnerable to harmful attacks - just because they were unlucky enough to sign up to your fun Game app with their real email address.

I've read a lot about this topic in the past days, and here's what I think is one of the best strategies to keep your app and users safe:


✏ Authorisation with JWT and httpOnly Cookies

One way to make your App less vulnerable for attacks is to set a JWT (JSON Web Token) with an httpOnly cookie, because those are not accessible by the browser and client-side JavaScript.

You'll have two types of tokens:

  • an access JWT that expires after ~ 10-15 minutes (sent in the response body)

  • a refresh JWT that expires after ~ 3 days (sent as httpOnly cookie)

The access token is the one that gives access to protected routes. The refresh token is used to request a new access token.

Login and Registration

If a user signs up or logs in to your application, the server responds with a signed request token in an httpOnly cookie, and a signed access token in the response body. The client-side JavaScript/React has no way of reading the refresh token, but it can grab the access token.

Do not save this token to local storage, instead save it in memory (in a variable) and use that variable to set the request authorization headers in subsequent requests, to access protected routes.

Even if evilCoder9 manages to steal that token, it'll expire very fast. Your frontend obviously has the same problem, the user will be automatically logged out after 10-15 minutes (and immediately if they refresh the page), which is not exactly a great UI.

Handling auto-logout

To solve the first problem, the frontend will periodically make a silent refresh, right before the access token expires. The user won't even notice. But your app will send a request to a refresh route in the background, which will

  • check the presence and validity of a refresh cookie/token (if none is present, the user is redirected to the login view)

  • respond with a new access token to keep the user logged in while they navigate on the site

Handling page reload

The solution is very similar in this case. Whenever the app mounts, it'll send a request to the refresh route. Since the cookie is still there, the server can send a new access token. If the user hasn't visited your page in a few days, the refresh token will have expired, too, and they'll have to log in again. However, that's an acceptable price to pay.

Logging out

If the user logs out, the frontend will delete the data/access token it has stored in state, and with a GET request to/logout, the server will remove the refresh cookie.


That's the principle in a nutshell. In the next blog, I'll continue with part 4/4 of my "How to add a Login Function to your App" mini series, demonstrating how to implement all of the above in a real React application.


✏ Resources

The Ultimate guide to handling JWTs on Frontend Clients (GraphQL)

Secure, HttpOnly, SameSite HTTP Cookies Attributes and Set-Cookie Explained


✏ Recap

This post covered:

  • never use local storage

  • principles of secure authorisation (short-lived access JWT and httpOnly cookie refresh JWT)


✏ Thanks for reading!

I do my best to thoroughly research the things I learn, but if you find any errors or have additions, please leave a comment below, or @ me on Twitter. If you liked this post, I invite you to subscribe to my newsletter. Until next time 👋


✏ Previous Posts

You can find an overview of all previous posts with tags and tag search here:

#100DaysOfMERN - The App