UNPKG

koas-security

Version:

Koas security checks if a request matches the security requirement of an operation. For example, given the following partial OpenAPI document:

75 lines (74 loc) 3.24 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.security = void 0; const apiKey_1 = require("./apiKey"); const http_1 = require("./http"); const oauth2_1 = require("./oauth2"); /** * Authenticate users based on OpenAPI security schemes and security requirements. * * @param options - A mapping of OpenAPI security definition keys to user getter functions. * @returns A Koas plugn for authenticating users. */ function security(options) { return ({ document, resolveRef }) => { const securityChecks = {}; // Work around the fact that the unaugmented options have no keys. const opts = options; for (const [key, schemeOrRef] of Object.entries(document.components.securitySchemes || [])) { if (!opts[key]) { throw new Error(`No user getter was defined for security scheme: ${key}`); } const scheme = resolveRef(schemeOrRef); switch (scheme.type) { case 'apiKey': securityChecks[key] = (0, apiKey_1.apiKeySecurityCheck)(scheme, opts[key]); break; case 'http': securityChecks[key] = (0, http_1.httpSecurityCheck)(scheme, opts[key]); break; case 'oauth2': case 'openIdConnect': securityChecks[key] = (0, oauth2_1.oauth2SecurityCheck)(scheme, opts[key]); break; default: throw new Error(`Unknown security scheme: ${JSON.stringify(scheme)}`); } } return async (ctx, next) => { const { operationObject } = ctx.openApi; if (!operationObject || !operationObject.security) { return next(); } for (const securityRequirementObject of operationObject.security) { const users = {}; const clients = {}; try { await Promise.all(Object.entries(securityRequirementObject).map(async ([key, requiredScopes]) => { const pair = await securityChecks[key](ctx, requiredScopes); if (!pair || !pair[0]) { throw new Error(`Unauthorized using security requirement: ${key}`); } [users[key]] = pair; if (pair[1]) { [, clients[key]] = pair; } })); } catch { continue; } ctx.users = users; ctx.clients = clients; // @ts-expect-error The type of ctx.user is never, because it’s not augmented yet. [ctx.user] = Object.values(users); // @ts-expect-error The type of ctx.client is never, because it’s not augmented yet. [ctx.client] = Object.values(clients); ctx.openApi.securityRequirementObject = securityRequirementObject; return next(); } return ctx.throw(401); }; }; } exports.security = security;