UNPKG

@sap/xssec

Version:

XS Advanced Container Security API for node.js

84 lines (71 loc) 3.15 kB
const createSecurityContext = require("../context/createSecurityContext"); const ConfigurationError = require("../error/configuration/ConfigurationError"); const ValidationError = require("../error/validation/ValidationError"); const { getLogger } = require("../util/logging"); /** * @typedef {import("../service/Service")} Service * @typedef {import("../token/Token")} Token */ const LOG = getLogger("XssecPassportStrategy.js"); class XssecPassportStrategy { /** @type {Service|Service[]} service(s) against which incoming JWTs are authenticated */ services; /** @type {string|Symbol} the property on the req object where the SecurityContext is placed after authentication. */ reqProperty; /** * Creates a new XssecPassportStrategy that uses the provided service(s) to create security contexts for incoming requests. * @param {Service|Service[]} services * @param {string|Symbol} [reqProperty="securityContext"] the property (Default: "securityContext") on the req object where the SecurityContext is placed after authentication. */ constructor(services, reqProperty = "securityContext") { this.name = "JWT"; this.services = services; this.reqProperty = reqProperty; } async authenticate(req, passportOptions = {}) { try { const securityContext = await createSecurityContext(this.services, {req}); if (passportOptions.scope) { if (!(typeof securityContext.checkScope === "function")) { return this.error(new ConfigurationError("XssecPassportStrategy was configured with scope but the authentication was performed via a Service whose SecurityContext does not support checkLocalScope.")); } const hasScope = [passportOptions.scope] .flatMap(s => s) .some(s => securityContext.checkLocalScope(s)); if (!hasScope) { return this.fail("Token is missing required scope.", 403); } } const passportUser = XssecPassportStrategy.#buildPassportUser(securityContext.token); req[this.reqProperty] = securityContext; req.tokenInfo = securityContext.token; return this.success(passportUser, securityContext); // passport will set these in req.user & req.authInfo respectively } catch (error) { req.xssecError = error; if (error instanceof ValidationError) { LOG.debug("ValidationError:", error); return this.fail(401); } else { return this.error(error); } } } /** * @param {Token} token */ static #buildPassportUser(token) { return { id: token.logonName || token.userName, name: { givenName: token.givenName, familyName: token.familyName }, emails: [ { value: token.email } ] } } } module.exports = XssecPassportStrategy;