Shoulder.dev Logo Shoulder.dev

express-jwt - gothinkster/node-express-realworld-example-app

Go to Shoulder Page

Express-jwt is a middleware for Express.js applications that provides functionality for validating JSON Web Tokens (JWTs) using the jsonwebtoken library. The latest version is 8.4.1, published a year ago. To install express-jwt, run npm i express-jwt. There are currently 1088 other projects using this package in the npm registry.

Description

Express-jwt is used to secure routes in Express.js applications by validating incoming JWTs. It decodes the JWT and makes the decoded payload available on the request object.

Installation

To install express-jwt, run the following command in your terminal:

$ npm install express-jwt

Usage

Express-jwt can be used to secure routes by validating incoming JWTs. The middleware function accepts an options object with various parameters.

const express = require("express");
const jwt = require("express-jwt");

const app = express();

app.get(
  "/protected",
  jwt({
    secret: "shhhhhhared-secret",
    algorithms: ["HS256"],
  }),
  function (req, res) {
    if (!req.auth.admin) return res.sendStatus(401);
    res.sendStatus(200);
  }
);

In the example above, the middleware is used to secure the /protected route. The secret and algorithms are specified in the options object. If the JWT is invalid, the middleware will throw an error, and the request will be terminated.

Options

The options object for express-jwt has the following parameters:

  • secret: The secret as a string or a function to retrieve the secret.
  • getToken: A function that receives the express Request and returns the token.
  • isRevoked: A function to verify if a token is revoked.
  • onExpired: A function to handle expired tokens.
  • credentialsRequired: A boolean indicating whether credentials are required.
  • requestProperty: The name of the property in the request object where the payload is set.

Basic Usage

The following example demonstrates basic usage of express-jwt with an HS256 secret:

const express = require("express");
const jwt = require("express-jwt");

const app = express();

app.get(
  "/protected",
  jwt({
    secret: "shhhhhhared-secret",
    algorithms: ["HS256"],
  }),
  function (req, res) {
    if (!req.auth.admin) return res.sendStatus(401);
    res.sendStatus(200);
  }
);

Required Parameters

The algorithms parameter is required to prevent potential downgrade attacks when providing third-party libraries as secrets.

jwt({
  secret: "shhhhhhared-secret",
  algorithms: ["HS256"],
});

Additional Options

You can specify audience and/or issuer as well, which is highly recommended for security purposes:

jwt({
  secret: "shhhhhhared-secret",
  audience: "http://myapi/protected",
  issuer: "http://issuer",
  algorithms: ["HS256"],
});

Customizing Token Location

A custom function for extracting the token from a request can be specified with the getToken option:

app.use(
  jwt({
    secret: "hello world !",
    algorithms: ["HS256"],
    credentialsRequired: false,
    getToken: function fromHeaderOrQuerystring(req) {
      if (
        req.headers.authorization &&
        req.headers.authorization.split(" ")[0] === "Bearer"
      ) {
        return req.headers.authorization.split(" ")[1];
      } else if (req.query && req.query.token) {
        return req.query.token;
      }
      return null;
    },
  })
);

Revoked Tokens

It is possible that some tokens will need to be revoked so they cannot be used any longer. You can provide a function as the isRevoked option:

const jwt = require("express-jwt");
const data = require("./data");

const isRevokedCallback = async (req, token) => {
  const issuer = token.payload.iss;
  const tokenId = token.payload.jti;
  const token = await data.getRevokedToken(issuer, tokenId);
  return token !== "undefined";
};

app.get(
  "/protected",
  jwt({
    secret: "shhhhhhared-secret",
    algorithms: ["HS256"],
    isRevoked: isRevokedCallback,
  }),
  function (req, res) {
    if (!req.auth.admin) return res.sendStatus(401);
    res.sendStatus(200);
  }
);

Handling Expired Tokens

You can handle expired tokens as follows:

jwt({
  secret: "shhhhhhared-secret",
  algorithms: ["HS256"],
  onExpired: async (req, err) => {
    if (new Date() - err.inner.expiredAt < 5000) { return;}
    throw err;
  },
});

Error Handling

The default behavior is to throw an error when the token is invalid, so you can add your custom logic to manage unauthorized access as follows:

app.use(function (err, req, res, next) {
  if (err.name === "UnauthorizedError") {
    res.status(401).send("invalid token...");
  } else {
    next(err);
  }
});

Typescript

A Request type is provided from express-jwt, which extends express.Request with the auth property. It could be aliased, like how JWTRequest is below.

import { expressjwt, Request as JWTRequest } from "express-jwt";

app.get(
  "/protected",
  expressjwt({ secret: "shhhhhhared-secret", algorithms: ["HS256"] }),
  function (req: JWTRequest, res: express.Response) {
    if (!req.auth?.admin) return res.sendStatus(401);
    res.sendStatus(200);
  }
);

Migration from v6

The middleware function is now available as a named import rather than a default one: import { expressjwt } from 'express-jwt'. The decoded JWT payload is now available as req.auth rather than req.user. The secret function had (req, header, payload, cb), now it can return a promise and receives (req, token). The isRevoked function had (req, payload, cb), now it can return a promise and receives (req, token).

Related Modules

Tests

To run tests, install the dependencies and run the tests:

$ npm install
$ npm test

Contributors

Check them out here.

Issue Reporting

If you have found a bug or if you have a feature request, please report them at this repository's issues section. Please do not report security vulnerabilities on the public GitHub issue tracker. The Responsible Disclosure Program details the procedure for disclosing security issues.

Author

Auth0

License

This project is licensed under the MIT license. See the LICENSE file for more info.