UNPKG

@sap/xssec

Version:

XS Advanced Container Security API for node.js

52 lines (45 loc) 2.59 kB
const Token = require('../token/Token'); const MissingJwtError = require("../error/validation/MissingJwtError"); const SecurityContext = require('./SecurityContext'); const { WrongAudienceError } = require('../error'); module.exports = createSecurityContext; /** * @typedef {import("../service/Service")} Service * @typedef {import("../util/Types").SecurityContextConfig} SecurityContextConfig */ /** * Tries to create a new security context by authenticating the user via the given service(s) based on a jwt token. * If the jwt is missing or cannot be validated, an error will be thrown. * The contextConfig must either contain a jwt token directly or a req object from whose Authorization header the jwt can be extracted as Bearer token. * @template {Service} T - The type of the service from which the security context is created * @param {T|T[]} services - The service or array of services to authenticate the user * @param {SecurityContextConfig} contextConfig - The configuration object containing the jwt token or req object * @returns {ReturnType<T['createSecurityContext']>} - A promise that resolves to the security context created by the target service * @throws {import('../error/XssecError')} - Error with a descriptive message and a suggested statusCode for the application response. The cause of the error can be checked via instanceof against the various XssecError subclasses. */ async function createSecurityContext(services, contextConfig) { contextConfig = { ...contextConfig }; SecurityContext.buildContextConfig(contextConfig); if (contextConfig.jwt == null) { throw new MissingJwtError(); } const token = new Token(contextConfig.jwt); // find service for token services = Array.isArray(services) ? services : services != null ? [services] : []; const targetService = findServiceForToken(services, token); if (targetService == null) { throw new WrongAudienceError(token, services, `The audiences of the token fit none of the supplied services.`); } // create context return targetService.createSecurityContext(token, contextConfig); } /** * Tries to find a service from the list for which the given token was issued based on logic implemented by individual subclasses of {@link Service}. * @param {Service[]} services * @param {Token} token * @returns {Service|undefined} */ function findServiceForToken(services, token) { // TODO: extend with heuristic to filter on XSUAA/IAS services to prevent false positive? return services.find(s => s.acceptsTokenAudience(token)); }