@dvsa/appdev-api-common
Version:
Utils library for common API functionality
79 lines (78 loc) • 3.14 kB
JavaScript
;
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;