Securing Authentication in a SPA Using JWT Token — The coolest way

In this post we will explore the right way to use JWT token in a Single Page Application and HOW to manage it in order to avoid security issues. Read on!

Single Page Applications are become the standard of the web development architecture. One of the best methods to authenticate a user is by using JWT web token, so first of all, let’s see a general view of what is it and when you should use it!

What’s JWT token?

JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed. JWTs can be signed using a secret (with the HMAC algorithm) or a public/private key pair using RSA or ECDSA.

It consists of three parts separated by dots (.), which are:

  • Header: A JSON(Base64 encoded) that has info about algorithm used(like HS256, RSA) and so on.
  • Payload: A JSON(Base64 encoded) that has info about the user.
  • Signature: a signed string generated by the header algorithm by joining the encoded header, the encoded payload and a secret.

Therefore, a JWT typically looks like the following:

header.payload.signature

JWT Tokens vs Cookies

As a stateless Single Page Application, after you login (via username/password, OAuth 2, etc), for every future API request, the server must need to know who you are in order to perform authenticated/authorized actions.
The are 2 main ways to identify a client in your REST API:

  • Session Cookie
  • Auth Token

Both of them offer many pros and cons:

Session Cookie

Usage Pros

  • They are stored by the browser with a related expires date and associated domain.
  • If the user closes the browser, the cookie will be deleted and he is no longer logged in.
  • Using the HttpOnly option the browser javascript cannot read it.
  • Using the Secure option the cookie will be stored only if the request has been sent over a secure channel (HTTPS).
  • Using the SameSite option it will not send with cross-site requests. This protect your API from CSRF attack.

Usage Cons

  • The SameSite option is not supported by all browsers, so you cannot completely trust it.
  • If the cookie is not created by HttpOnly option it is vulnerable to the XSS attack, so an attacker could steal user session cookie.
  • The cookie will be sent over cross-site requests and to avoid CSRF attack you should use the CSRF token for each request.
  • It store a session inside the server.

JWT Token

Usage Pros

  • Server has just to verify the token validity in order to authenticate a user, it doesn’t need to ask to a database.
  • It works the same for both native mobile apps and browser clients.
  • If you store the token inside the local storage you don’t worry about CSRF attack.
  • Browser javascript has the full control over it.

Usage Cons

  • Browser javascript has the full controll over it 😆 you have to store your token anywhere (local storage, cookies, memory, …) but if your application is vulnerable to XSS an attacker could steal the user token and impersonate him.
  • If you store the token into cookies it is also vulnerable to CSRF attack.

At this point the main issue using JWT is where to store it in order to avoid the XSS and CSRF attacks.

Storing JWT Token: The Cookie and Local Storage Approach

I was inspired by Peter Locke post https://medium.com/lightrail/getting-token-authentication-right-in-a-stateless-single-page-application-57d0c6474e3 where he explains how to store token into 2 cookies but mine approach is a little bit different.

The main idea is to split the JWT token into 2 parts, but instead of using 2 cookies and after that use CSRF token for each request I store Header and Payload into the local storage and the Signature into a Session Cookie with HttpOnly option set to true.

The server has to rebuild the token before validate it, so the approach became the following:

In this way the CSRF attack is prevented by the part of token saved into the Local Storage, and XSS attack is limited by the Session Cookie which is not accessible via browser javascript.

This solution solves all security issues, avoid to create a CSRF token for each request and maintain a stateless application.

If you liked this post feel free to leave a comment about it and don’t forget to clap!

Full-stack Developer & Security Enthusiast