UNPKG

@dvsa/appdev-api-common

Version:

Utils library for common API functionality

79 lines (78 loc) 3.14 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.JwtAuthoriser = void 0; const jose_1 = require("jose"); const http_status_codes_1 = require("../api/http-status-codes"); const auth_errors_1 = require("./auth-errors"); class JwtAuthoriser { clientIds; tenantId; static ENV = process.env.environment?.toUpperCase() ?? ""; static tokenExpiryEnvExclusionList = [ "DEVELOPMENT", "NON-PROD", ]; static DEFAULT_TENANT = "common"; static MICROSOFT_LOGIN_BASE_URL = "https://login.microsoftonline.com"; static jwksByTenant = new Map(); /** * Create a new instance of the JwtAuthoriser class * @param clientIds - the client id(s) to validate the token against - can take a single string value or a comma-separated list in a string * @param tenantId - the tenant id to validate the token against */ constructor(clientIds = null, tenantId = null) { this.clientIds = clientIds; this.tenantId = tenantId; } static getTenantSegment(tenantId) { return tenantId?.trim() || JwtAuthoriser.DEFAULT_TENANT; } static getJwks(tenantId) { const tenantSegment = JwtAuthoriser.getTenantSegment(tenantId); const cachedJwks = JwtAuthoriser.jwksByTenant.get(tenantSegment); if (cachedJwks) { return cachedJwks; } const jwks = (0, jose_1.createRemoteJWKSet)(new URL(`${JwtAuthoriser.MICROSOFT_LOGIN_BASE_URL}/${tenantSegment}/discovery/keys`)); JwtAuthoriser.jwksByTenant.set(tenantSegment, jwks); return jwks; } /** * Validate a JWT and return the decoded payload * @param {string} token - the JWT token to validate * @returns {Promise<JWTPayload>} */ async verify(token) { try { const opts = { clockTolerance: 10, algorithms: ["RS256"], }; // audience validation is handled automatically if present in token if (this.clientIds?.length) { opts.audience = this.clientIds .split(",") .map((id) => id.trim()) .filter(Boolean); } // issuer validation is handled automatically if present in token if (this.tenantId) { opts.issuer = [ `https://sts.windows.net/${this.tenantId}/`, `https://login.microsoftonline.com/${this.tenantId}/v2.0`, ]; } if (JwtAuthoriser.tokenExpiryEnvExclusionList.includes(JwtAuthoriser.ENV)) { opts.maxTokenAge = Number.POSITIVE_INFINITY; } const { payload } = await (0, jose_1.jwtVerify)(token, JwtAuthoriser.getJwks(this.tenantId), opts); return payload; } catch (err) { const error = err; const code = "code" in error ? error.code : ""; throw new auth_errors_1.AuthError(http_status_codes_1.HttpStatus.UNAUTHORIZED, err.message, code); } } } exports.JwtAuthoriser = JwtAuthoriser;