Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 27x 27x 27x 27x 27x 27x 27x 14x 14x 27x 13x 27x 17x 17x 2x 2x 17x 16x 16x 1x 1x 1x 16x 5x 5x 5x 16x 15x 17x 6x 6x 17x 9x 9x 9x 9x 9x 17x 10x 10x 10x 10x 17x 9x 27x 1x 1x 27x 1x 1x 1x 1x 1x 27x 2x 2x 2x 2x 2x 2x 27x | "use strict";
/**
* Resolve the effective OpenAPI security requirement of an operation into
* concrete credentials, honouring operation overrides and alternatives, and
* never silently downgrading to unauthenticated access.
*
* @module upstream/security
*/
import type { SecurityRequirement, SecuritySchemeInfo } from "../types.js";
import { UpstreamAuthError } from "./credentials.js";
import type {
AppliedCredential,
CredentialContext,
CredentialProvider,
} from "./types.js";
/** Result of credential resolution. */
export interface ResolvedSecurity extends AppliedCredential {
/** Scheme names applied; empty when the call is unauthenticated. */
schemes: string[];
/** Index of the alternative used, -1 when none was required. */
alternative: number;
}
/**
* Choose and apply the first satisfiable security alternative.
*
* Alternatives are tried in document order, skipping the empty alternative
* (`{}`, meaning "no authentication"), which is used only when no
* authenticated alternative is configured. If the operation requires
* authentication and no alternative is satisfiable, an error is raised.
*
* @param {Array} security - effective requirement alternatives
* @param {Object} schemes - security scheme info
* @param {Object} provider - credential provider
* @param {Object} ctx - credential context
* @return {Promise} resolved security
*/
export async function resolveSecurity(
security: SecurityRequirement[],
schemes: Record<string, SecuritySchemeInfo>,
provider: CredentialProvider,
ctx: CredentialContext,
): Promise<ResolvedSecurity> {
if (security.length === 0) {
return { headers: {}, query: {}, schemes: [], alternative: -1 };
}
const unsupported = new Set<string>();
const unconfigured = new Set<string>();
for (let i = 0; i < security.length; i++) {
const names = Object.keys(security[i]);
if (names.length === 0) {
continue;
}
const usable = names.every((n) => {
const s = schemes[n];
if (!s || !s.supported) {
unsupported.add(n);
return false;
}
if (!provider.has(n)) {
unconfigured.add(n);
return false;
}
return true;
});
if (!usable) {
continue;
}
const out: ResolvedSecurity = {
headers: {},
query: {},
schemes: names,
alternative: i,
};
for (const n of names) {
const applied = await provider.apply(schemes[n], security[i][n], ctx);
Object.assign(out.headers, applied.headers);
Object.assign(out.query, applied.query);
}
return out;
}
if (security.some((r) => Object.keys(r).length === 0)) {
return { headers: {}, query: {}, schemes: [], alternative: -1 };
}
if (unconfigured.size === 0 && unsupported.size > 0) {
throw new UpstreamAuthError(
"unsupported_scheme",
`This operation requires security schemes oag-mcp cannot satisfy: ${[...unsupported].join(", ")}`,
);
}
throw new UpstreamAuthError(
"credential_not_configured",
`No upstream credentials are configured for this operation; configure one of: ${security
.map((r) => Object.keys(r).join(" + "))
.filter(Boolean)
.join(" | ")} under upstreamAuth.schemes`,
);
}
|