Bruno Quaresma Blog

Quick Introduction to JWT using Javascript

June 20, 2019

JWT(JSON Web Token) is being used a lot to authenticate SPAs(Single Page Applications) but before we get started, we should know what a JWT is. I’ve put a short summary below, but if you need more information, visit the official JWT website.

JSON Web Token (JWT) is an open standard 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 or a public/private key…

The process of authentication and validation is very simple, let’s see how it happens:

JWT Flow

  1. The SPA sends a login request with the user credentials
  2. The backend verifies that the credentials are valid
  3. If the credentials are valid, the backend will generate a new token using a payload containing some user identifier(such as id, or email) and a secret.
  4. The backend sends the token to the SPA.
  5. The SPA stores the token.
  6. The SPA uses the token as an authorization header in an HTTP request.
  7. The backend checks the token.
  8. If the token is valid, the backend returns the requested data.

Now that we are understanding the process we can turn it into code.

Code sample

Backend - Logging in and generating the token

const jwt = require('jsonwebtoken');

const signIn = async (req, res) => {
  const { email, password } = req.params

  try {
    const user = await doLogin(email, password);
    const token = jwt.sign({ userId: user.id }, 'your-secret');
    return res.json({
      token
    })
  } catch(error) {
    ...
  }
}

SPA - Sending the sign in request and getting the token

import axios from 'axios'
import Cookies from 'js-cookie'

const signIn = async (email, password) => {
  try {
    const credentials = await axios.post('/signIn', { email, password })
    Cookies.set('credentials', credentials)  } catch(error) {
    ...
  }
}

SPA - Sending a request to get some private data

import axios from 'axios'
import Cookies from 'js-cookie'

const getBooks = (email, password) => {
  try {
    const credentials = Cookies.getJSON('credentials')
    if(!credentials) {...}

    return axios.post('/books', null, {
      headers: {
        authorization: credentials.token      }
    })
  } catch(error) {
    ...
  }
}

Backend - Checking the request

const jwt = require('jsonwebtoken');

const books = async (req, res) => {
  try {
    const token = req.headers.authorization    const { userId } = jwt.verify(token, 'your-secret');
    return res.json(
      Books
        .where({
          user_id: userId
        })
        .all()
    )
  } catch(error) {
    ...
  }
}

Security concerns

  • Use your jwt secret as an env variable like process.env.JWT_SECRET.
  • Use the expiration time on tokens and cookies. You do not want to have a leaked token living forever.
  • Do not put sensitive data inside the payload because the token can be easily decoded but no one is able to create a valid token without the secret.
  • Use a strong secret. You can use some app for this like https://randomkeygen.com/.

Example with 1 day expiration:

  // Backend
  jwt.sign(
    { userId: user.id },
    'your-secret',
    { expiresIn: '1d' }  );

  // SPA
  Cookies.set(
    'credentials',
    credentials,
    { expires: 1 }  )

I hope you have enjoyed this article and it has been useful to you. Thanks for reading!


Bruno Quaresma

Written by Bruno Quaresma
Sr. Front-end Developer at Fauna
Twitter