Step 12: JWT

In the previous step, we provided a route to authenticate users. But now what? After a sucessfull authentication, the user should be able to perform/access resources they are autorized to. Somehow the API server should know an authenticated user when such a user makes a request through the client application.

Token-based authentication is a common practice where the the authentication service, after having confirmed the user's identity, issues a token. A token is like a receipt that the client will keep and hand back to the server for future interactions. Conventionally, tokens have an expiration date! Once the token expires, the client must authenticate with the server again (e.g., sign in again).

The token can be anything! A popular choice is JSON web token (JWT), pronounced "jot," is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object.

Let's install jsonwebtoken dependecy:

yarn add jsonwebtoken

Create a file, token.js, in the src folder, with the following content:

import jsonWebToken from "jsonwebtoken";

export const createToken = ({ user, expiresIn }) => {
  return jsonWebToken.sign(user, process.env.JWT_SECRET, {
    algorithm: "HS256",
    expiresIn: expiresIn || "2d",
  });
};

export const decodeToken = (token) => {
  return jsonWebToken.verify(token, process.env.JWT_SECRET, {
    algorithm: "HS256",
    ignoreNotBefore: true,
  });
};

Notice the expiresIn attribute! If this parameter is not provided, we set the token to expire two days after it was created. If a token is expired (or invalid), the decodeToken will throw an error.

The JWT_SECRET is a string containing the secret for HS256 algorithm. You can choose any string (the longer, the better). Moreover, store this string in the .env file.

Update src/auth.js

We create a token that includes the user's ID and return it to the client:

debug("Prepare the payload..");
const token = createToken({ user: { id: user.id } });
res.status(201).json({
  status: 201,
  message: `Successfully signed in!`,
  data: { name: user.name, email: user.email },
  token,
});

Now run the API server and try to make a Postman request for this new route.

Resources