UNPKG

@dvsa/appdev-api-common

Version:

Utils library for common API functionality

63 lines (62 loc) 3.04 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.JWTAuthChecker = void 0; const http_status_codes_1 = require("../api/http-status-codes"); const auth_errors_1 = require("./auth-errors"); const verify_jwt_1 = require("./verify-jwt"); class JWTAuthChecker { clientId; tenantId; /** * Create a new instance of the JWTAuthChecker class * @param clientId - the client id(s) to validate the token against * @param tenantId - the tenant id to validate the token against */ constructor(clientId = null, tenantId = null) { this.clientId = clientId; this.tenantId = tenantId; } /** * Perform a JWT token verification and role check * @param {RoutingControllersRequest} request * @param {string | string[]} roles * @returns {Promise<boolean>} */ execute = async ({ request }, roles = []) => { // if running locally, skip the token auth and role check if (process.env.IS_OFFLINE === "true" && process.env.FORCE_LOCAL_AUTH !== "true") return true; // extract the token from the request headers const headers = request?.apiGateway.event .headers; const token = headers?.Authorization || headers?.authorization; // if no token is found, then deny access to resource if (!token || token.trim()?.length === 0) { throw new auth_errors_1.AuthError(http_status_codes_1.HttpStatus.UNAUTHORIZED, "Missing Authorization header"); } // create an instance of the JwtAuthoriser class, passing in clientId & tenantId const authoriser = new verify_jwt_1.JwtAuthoriser(this.clientId, this.tenantId); // Validate the token and extract the roles from it const { roles: tokenRoles } = await authoriser.verify(token); // check if a singular or list of roles were passed into the @Authorized decorator & remove nullish values const requiredRoles = (Array.isArray(roles) ? roles : [roles]).filter((role) => !!role); // if there are no requiredRoles, then any valid token can access the resource, so return true if (requiredRoles.length === 0) return true; // if there are no roles in JWT token but roles are required, then deny access if (!tokenRoles || !Array.isArray(tokenRoles) || tokenRoles.length === 0) { throw new auth_errors_1.AuthError(http_status_codes_1.HttpStatus.UNAUTHORIZED, "No roles found in token", "MISSING_ROLES"); } // check if one of the required roles is present in JWT token const success = requiredRoles.some((role) => tokenRoles.includes(role)); if (!success) { throw new auth_errors_1.AuthError(http_status_codes_1.HttpStatus.UNAUTHORIZED, "Insufficient permissions", "UNAUTHORIZED", { required: requiredRoles, actual: tokenRoles, }); } return true; }; } exports.JWTAuthChecker = JWTAuthChecker;