1.0.2 • Published 2 years ago

@immersa/auth0-jwt-validator v1.0.2

Weekly downloads
-
License
ISC
Repository
github
Last release
2 years ago

Auth0 JWT Validator

Authentication tools for Node.js that validates JWT Bearer Access Tokens, scopes and permissions using auth0.

Docs Tests License npm codecov

Install

This package supports Node >= 12

npm install @immersa/auth0-jwt-validator

Getting started

The library is agnostic to any NodeJs framework, so we need to use it within custom middlewares since every framework handles the request, response and next in different ways.

With this basic configuration, your api will require a valid Access Token JWT bearer token for all routes.

API Documentation

Complete documentation can be found here.

  • getToken - Validate and get the token from the header request and will return a 401 if a valid JWT bearer token in the request is not provided or has an invalid format.
  • JwtVerifier - Class that verifies the token and will return a 401 if a valid JWT bearer token is not provided. Internally will use the jwksUri to get the public keys form Auth Server Metadata for the verification.
  • requiredPermissions - Check a token's permissions claim to include 1 or more permissions, raises a 403 insufficient_permission error if the value of the scope claim does not include all the given permissions.
  • requiredScopes - Check a token's scope claim to include a number of given scopes, raises a 403 insufficient_scope error if the value of the scope claim does not include all the given scopes.
  • claimEquals - Check a token's claim to be equal a given JSONPrimitive (string, number, boolean or null) raises a 401 invalid_token error if the value of the claim does not match.
  • claimIncludes - Check a token's claim to include a number of given JSONPrimitives (string, number, boolean or null) raises a 401 invalid_token error if the value of the claim does not include all the given values.
  • claimCheck - Check the token's claims using a custom method(predicate) that receives the JWT Payload and should return true if the token is valid. Raises a 401 invalid_token error if the function returns false.

Examples

ExpressJs

auth-middleware.ts

const { jwtVerifier, getToken } = require('auth0-jwt-validator')

export const auth = (opts: JwtVerifierOptions = {}): Handler => {
  const verifier = new jwtVerifier(opts)

  return async (req: Request, res: Response, next: NextFunction) => {
    try {
      const jwt = getToken(req.headers)
      req.auth = await verifier.verify(jwt)
      next()
    } catch (e) {
      next(e)
    }
  }
}

route config

// Config app to use the AuthMIddleware for all the requests
{
  const {auth} = require('my-middleware-folder/auth-middleware')
  ...
  app.use(
    auth({
      issuer: 'https://YOUR_ISSUER_DOMAIN',
      audience: 'https://my-api.com',
      jwksUri: 'https://issuer.example.com/.well-known/jwks.json',
    })
  )
}

permissions-middleware.ts

const { requiredPermissions as _requiredScopes, JWTPayload, RequiredScopes, Permission } = require('auth0-jwt-validator')

// Create a handler as a High order function to be able to use it as a middleware directly in any route
const toHandler =
  (fn: (payload?: JWTPayload) => void): Handler =>
  (req, res, next) => {
    try {
      fn(req.auth?.payload);
      next();
    } catch (e) {
      next(e);
    }
  };

export const requiredPermissions: RequiredScopes<Handler> = (...args) =>
  toHandler(_requiredScopes(...args));

Handler workaround works for the rest of functions: claimIncludes, claimCheck, claimEquals and requiredScopes

Route config

const {requiredPermissions, Permission} = require('my-middleware-folder/permissions-middleware')
// Use enum for known permissions
{
  app.get('/admin/edit', requiredPermissions(Permission.Enhanced),
     (req, res) => { ... });
}

custom-validation-middleware.ts

const { claimCheck as _claimCheck } = require('auth0-jwt-validator')

// Use the previous Handler function

export const claimCheck: RequiredScopes<Handler> = (...args) =>
  toHandler(_claimCheck(...args));

Route config

const {claimCheck} = require('my-middleware-folder/custom-validation-middleware')
...
app.get(
  '/api/admin/edit',
  claimCheck(({ isAdmin, roles }) => isAdmin && roles.includes('editor')),
  (req, res, next) => {
    // ...
  }
)

AdonisJs

Middleware/AuthRequest.ts

import { getToken, JwtVerifier } from 'auth0-jwt-validator'

export default class AuthRequest {
  public async handle(ctx: HttpContextContract, next: () => Promise<void>) {
    const token = getToken(ctx.request.headers())
    const verifier = new JwtVerifier({
      issuer: 'https://YOUR_ISSUER_DOMAIN',
      audience: 'https://my-api.com',
      jwksUri: 'https://issuer.example.com/.well-known/jwks.json',
    })

    const payload = await verifier.verify(token)
    ctx.auth = { token, payload }

    await next()
  }
}

Don't forget to inform Typescript about the new props in context. Check how to do it here

kernel.ts

Server.middleware.register([() => import('App/Middleware/AuthRequest')])

Middleware/PermissionsRequest.ts

import { requiredPermissions } from 'auth0-jwt-validator'

export default class PermissionsRequest {
  public async handle(
    ctx: HttpContextContract,
    next: () => Promise<void>,
    permissions: string[] | string
  ) {
    const { payload } = ctx.auth || {}
    requiredPermissions(permissions)(payload)

    await next()
  }
}

kernel.ts

Server.middleware.registerNamed({
  permissions: () => import('App/Middleware/PermissionsRequest'),
})

Route

import { Permission } from 'auth0-jwt-validator'
Route.get('dashboard', 'UserController.dashboard').middleware(
  `permissions:${Permission.Enhanced}`
)

Error Handling

This SDK raises errors with err.status and err.headers according to rfc6750. So for error handling consider the following premises:

  • res.statusCode set from err.status
  • res.statusMessage set according to the status code.
  • The body will be the HTML of the status code message when in production environment, otherwise will be err.stack.
  • Any headers specified in an err.headers object.

The error_description in the WWW-Authenticate header will contain useful information about the error, which you may not want to disclose in Production.

What is Auth0?

Auth0 helps you to easily:

  • Implement authentication with multiple identity providers, including social (e.g., Google, Facebook, Microsoft, LinkedIn, GitHub, Twitter, etc), or enterprise (e.g., Windows Azure AD, Google Apps, Active Directory, ADFS, SAML, etc.)
  • Log in users with username/password databases, passwordless, or multi-factor authentication
  • Link multiple user accounts together
  • Generate signed JSON Web Tokens to authorize your API calls and flow the user identity securely
  • Access demographics and analytics detailing how, when, and where users are logging in
  • Enrich user profiles from other data sources using customizable JavaScript rules

Why Auth0?

License

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

Contributing

Commits should follow the next format:

type(scope): message

Example:

test(k2-1234): Add pending tests

Type

Must be one of the following:

build: Changes that affect the build system or external dependencies (example scopes: npm)

ci: Changes to our CI configuration files and scripts (examples: GitHub Actions, Hooks)

docs: Documentation only changes

feat: A new feature

fix: A bug fix

perf: A code change that improves performance

refactor: A code change that neither fixes a bug nor adds a feature

test: Adding missing tests or correcting existing tests

IMPORTANT: feat, fix and perf are types that always trigger a new release.

Scope

Must be the ticket/task Id

Copyright

This package is a custom implementation of:

express-oauth2-jwt-bearer

1.0.2

2 years ago

1.0.1

2 years ago

1.0.0

3 years ago