@digitalbazaar/authorize-access-token-middleware

General express middleware to protect API endpoints via OAuth 2.0 access tokens.

Usage no npm install needed!

<script type="module">
  import digitalbazaarAuthorizeAccessTokenMiddleware from 'https://cdn.skypack.dev/@digitalbazaar/authorize-access-token-middleware';
</script>

README

JWT Access Token Authorization Middleware (@digitalbazaar/authorize-access-token-middleware)

Node.js CI

An opinionated Express-like middleware to protect API endpoints via OAuth 2.0 access tokens.

Table of Contents

Background

This is primarily intended for app authorization (for applications using the client_credentials OAuth 2 grant type), rather than for user (subject) authentication (for that, Passport is more useful).

Assumptions:

  • Access tokens will be passed via HTTP headers, using Bearer <token> scheme.

Not supported in v1.0:

  • Optional authorization (that is, if you use this middleware, an access token is required).
  • Automatically decrypting access tokens (although you can decrypt them in the verify callback).
  • DPoP / proof of possession header functionality.

Security

TBD

Install

  • Node.js 12+ is required.

To install locally (for development):

git clone https://github.com/digitalbazaar/authorize-access-token-middleware.git
cd authorize-access-token-middleware
npm install

Usage

Importing

import {authorizeAccessToken} from '@digitalbazaar/authorize-access-token-middleware';
// or
const {authorizeAccessToken} = require('@digitalbazaar/authorize-access-token-middleware');

Adding authorization to an api route

app.post('/example/api/endpoint',
  authorizeAccessToken({
    // OAuth2 scope required for this endpoint
    requiredScope: 'my.custom.scope',
    
    // Optional list of allowed issuers of tokens.
    // If missing, issuer validation must be performed manually
    // in validateClaims() callback.
    validIssuers: ['https://issuer.example.com'],

    verify: async ({token}) => {
      // REQUIRED verify callback must:
      // 1. Decode the claims (decrypting the token, if encrypted) 
      // 2. Verify key id, algorithm and signature (using a remote KMS or similar)
      // 3. Return the token payload (claims)
    },

    validateClaims: async ({claims}) => {
      // Optional custom claim validation callback (for example, you can
      // validate the `aud`ience claim). Expected to throw errors as appropriate.
    },

    decorateError: async ({errorResponse}) => {
      // Optional callback to decorate/add to the error response.
      // By default, error responses follow the OAuth 2.0 error response format 
      // @see https://datatracker.ietf.org/doc/html/rfc6749#section-5.2
      // This is typically used to add other application-specific fields to the JSON error response
      errorResponse.appSpecificErrorCode = '1234';
      return errorResponse;
    },
    
    // Optional advanced override (an lru-memoize instance)
    claimsCache: new LruCache({max: 100, maxAge: 5000}),

    // Optional logger object (such as console, pino, winston, and so on)
    logger: console
  }),
  (req, res, next) => {
    // ... continue with your route handling as usual
    // `req.clientMetadata` will be set with
    // the decoded and validated claims from the token
  }
)

Contribute

See the contribute file!

PRs accepted.

If editing the Readme, please conform to the standard-readme specification.

Commercial Support

Commercial support for this library is available upon request from Digital Bazaar: support@digitalbazaar.com

License

New BSD License (3-clause) © Digital Bazaar