@passflow/node 0.0.0-bootstrap.0 → 0.0.0-stage
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -179
- package/package.json +4 -104
- package/LICENSE +0 -21
- package/dist/claims-BHJhnzch.d.cts +0 -51
- package/dist/claims-BHJhnzch.d.mts +0 -51
- package/dist/evaluate-BTuol-Oa.mjs +0 -348
- package/dist/evaluate-C20MecTf.cjs +0 -491
- package/dist/express.cjs +0 -52
- package/dist/express.d.cts +0 -29
- package/dist/express.d.mts +0 -29
- package/dist/express.mjs +0 -49
- package/dist/fastify.cjs +0 -67
- package/dist/fastify.d.cts +0 -40
- package/dist/fastify.d.mts +0 -40
- package/dist/fastify.mjs +0 -63
- package/dist/hono.cjs +0 -51
- package/dist/hono.d.cts +0 -24
- package/dist/hono.d.mts +0 -24
- package/dist/hono.mjs +0 -48
- package/dist/index.cjs +0 -558
- package/dist/index.d.cts +0 -141
- package/dist/index.d.mts +0 -141
- package/dist/index.mjs +0 -539
|
@@ -1,348 +0,0 @@
|
|
|
1
|
-
// src/acr.ts
|
|
2
|
-
const ACR_NONE = "0";
|
|
3
|
-
const AAL1 = "1";
|
|
4
|
-
const AAL2 = "2";
|
|
5
|
-
const AAL3 = "3";
|
|
6
|
-
const ACR_LEXICAL = /^[+-]?[0-9]+$/;
|
|
7
|
-
const INT64_MAX = 9223372036854775807n;
|
|
8
|
-
/**
|
|
9
|
-
* The ordinal level of an `acr` value, by the rule the server's `strconv.Atoi` applies on a 64-bit
|
|
10
|
-
* platform (`server_level` in the corpus): optional sign and any number of ASCII digits, the value
|
|
11
|
-
* must fit a signed 64-bit integer; a lexical failure, an out-of-range value, a negative value or a
|
|
12
|
-
* non-string is level 0.
|
|
13
|
-
*
|
|
14
|
-
* Internal. It returns `bigint` so that nothing on the decision path goes through a `Number`.
|
|
15
|
-
*/
|
|
16
|
-
function parseACRLevel(acr) {
|
|
17
|
-
if (typeof acr !== "string" || !ACR_LEXICAL.test(acr)) return 0n;
|
|
18
|
-
const level = BigInt(acr);
|
|
19
|
-
return level < 0n || level > INT64_MAX ? 0n : level;
|
|
20
|
-
}
|
|
21
|
-
/**
|
|
22
|
-
* Whether a token's `acr` meets the required level. Both sides are compared as exact 64-bit integers,
|
|
23
|
-
* and a required side that parses to level 0 is never satisfied: a wrong configuration string fails
|
|
24
|
-
* closed here as well as at `requireACR` construction.
|
|
25
|
-
*/
|
|
26
|
-
function acrSatisfies(acr, min) {
|
|
27
|
-
const required = parseACRLevel(min);
|
|
28
|
-
return required !== 0n && parseACRLevel(acr) >= required;
|
|
29
|
-
}
|
|
30
|
-
/**
|
|
31
|
-
* The level as a `number`, for display and logging. It is exact only up to 2^53, and nothing in this
|
|
32
|
-
* library decides with it: use {@link acrSatisfies} to compare.
|
|
33
|
-
*/
|
|
34
|
-
function acrLevel(acr) {
|
|
35
|
-
return Number(parseACRLevel(acr));
|
|
36
|
-
}
|
|
37
|
-
// src/bearer.ts
|
|
38
|
-
const BEARER_PREFIX = /^bearer(?:[ \t]+|$)/i;
|
|
39
|
-
/**
|
|
40
|
-
* The token from an `Authorization` header. The scheme is matched case-insensitively (RFC 9110). Any
|
|
41
|
-
* other scheme, an absent header, and a `Bearer` with an empty or whitespace-only remainder all give
|
|
42
|
-
* `undefined`.
|
|
43
|
-
*/
|
|
44
|
-
function extractBearer(authorization) {
|
|
45
|
-
if (typeof authorization !== "string") return;
|
|
46
|
-
const header = authorization.trim();
|
|
47
|
-
const prefix = BEARER_PREFIX.exec(header);
|
|
48
|
-
if (prefix === null) return;
|
|
49
|
-
const token = header.slice(prefix[0].length);
|
|
50
|
-
return token === "" ? void 0 : token;
|
|
51
|
-
}
|
|
52
|
-
// src/challenge.ts
|
|
53
|
-
const MAX_AGE_ERROR = "[passflow] maxAgeSeconds must be a finite integer between 1 and Number.MAX_SAFE_INTEGER";
|
|
54
|
-
const FORMAT_MAX_AGE_ERROR = "[passflow] maxAge must be undefined or a finite number no greater than Number.MAX_SAFE_INTEGER";
|
|
55
|
-
const FORMAT_ACR_ERROR = "[passflow] acrValues must be undefined or a string";
|
|
56
|
-
/**
|
|
57
|
-
* The constructor rule for a freshness limit (`freshness.json#max_age_input`): a finite number,
|
|
58
|
-
* truncated toward zero, at least 1 and a safe integer, or a `TypeError`. The bound means `String()`
|
|
59
|
-
* always yields plain decimal, so a challenge can never carry `max_age=1e+21`, which the browser
|
|
60
|
-
* SDK's `Number.parseInt` reads as 1. The returned value is both what is enforced and what the
|
|
61
|
-
* challenge carries.
|
|
62
|
-
*/
|
|
63
|
-
function assertMaxAge(value) {
|
|
64
|
-
if (typeof value !== "number" || !Number.isFinite(value)) throw new TypeError(MAX_AGE_ERROR);
|
|
65
|
-
const seconds = Math.trunc(value);
|
|
66
|
-
if (seconds < 1 || !Number.isSafeInteger(seconds)) throw new TypeError(MAX_AGE_ERROR);
|
|
67
|
-
return seconds;
|
|
68
|
-
}
|
|
69
|
-
/**
|
|
70
|
-
* The exact RFC 9470 `WWW-Authenticate` bytes the server's `SetInsufficientAuthChallenge` emits. This
|
|
71
|
-
* is a formatter, not a constructor: a `maxAge` that truncates to zero or below is omitted, as the
|
|
72
|
-
* server omits it, and it does not run {@link assertMaxAge}. A non-finite number, a non-number, or a
|
|
73
|
-
* positive value above `Number.MAX_SAFE_INTEGER` is a `TypeError`.
|
|
74
|
-
*
|
|
75
|
-
* `acrValues` is a space-separated list of acr tokens, inserted unescaped exactly as the server does.
|
|
76
|
-
*/
|
|
77
|
-
function formatChallenge(c) {
|
|
78
|
-
let header = "Bearer error=\"insufficient_user_authentication\"";
|
|
79
|
-
if (c.acrValues !== void 0) {
|
|
80
|
-
if (typeof c.acrValues !== "string") throw new TypeError(FORMAT_ACR_ERROR);
|
|
81
|
-
if (c.acrValues !== "") header += `, acr_values="${c.acrValues}"`;
|
|
82
|
-
}
|
|
83
|
-
if (c.maxAge !== void 0) {
|
|
84
|
-
if (typeof c.maxAge !== "number" || !Number.isFinite(c.maxAge)) throw new TypeError(FORMAT_MAX_AGE_ERROR);
|
|
85
|
-
const seconds = Math.trunc(c.maxAge);
|
|
86
|
-
if (seconds > 0) {
|
|
87
|
-
if (!Number.isSafeInteger(seconds)) throw new TypeError(FORMAT_MAX_AGE_ERROR);
|
|
88
|
-
header += `, max_age=${String(seconds)}`;
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
return header;
|
|
92
|
-
}
|
|
93
|
-
// src/claims.ts
|
|
94
|
-
const MAX_EXACT_SECONDS = 2 ** 53;
|
|
95
|
-
const provenance = /* @__PURE__ */ new WeakMap();
|
|
96
|
-
/** Internal: records that `verifier.verify` produced exactly this object. */
|
|
97
|
-
function recordProvenance(claims, verifier) {
|
|
98
|
-
provenance.set(claims, verifier);
|
|
99
|
-
}
|
|
100
|
-
/**
|
|
101
|
-
* True only for the exact object `verifier.verify` returned. A spread or clone loses provenance, which
|
|
102
|
-
* costs one more verification and never a bypass. So does any wrapper or decorator object that delegates
|
|
103
|
-
* to `verifier.verify`: it is a different identity, and this verifier's adapter re-verifies claims it
|
|
104
|
-
* returns. Two verifiers built from the same configuration are different identities too.
|
|
105
|
-
*/
|
|
106
|
-
function verifiedBy(claims, verifier) {
|
|
107
|
-
return provenance.get(claims) === verifier && verifier !== void 0;
|
|
108
|
-
}
|
|
109
|
-
/**
|
|
110
|
-
* Internal: a numeric date within ±2^53, the rule Go's `numericDate` applies. Beyond it a JSON number is no
|
|
111
|
-
* longer an exact count of seconds, so the claim reads as absent.
|
|
112
|
-
*/
|
|
113
|
-
function isExactSeconds(value) {
|
|
114
|
-
return typeof value === "number" && Math.abs(value) <= MAX_EXACT_SECONDS;
|
|
115
|
-
}
|
|
116
|
-
function isPlainObject(value) {
|
|
117
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
118
|
-
}
|
|
119
|
-
function isStringArray(value) {
|
|
120
|
-
return Array.isArray(value) && value.every((entry) => typeof entry === "string");
|
|
121
|
-
}
|
|
122
|
-
function stringsOf(value) {
|
|
123
|
-
return Array.isArray(value) ? value.filter((entry) => typeof entry === "string") : [];
|
|
124
|
-
}
|
|
125
|
-
/** A wrong JSON type means the membership cannot be read. `null` reads as absent, as Go's decoder does. */
|
|
126
|
-
function decodeMembership(value) {
|
|
127
|
-
if (!isPlainObject(value)) return;
|
|
128
|
-
const { tenant_id, tenant_name, tenant_roles, root_group_id, groups, group_names } = value;
|
|
129
|
-
const membership = { tenantId: "" };
|
|
130
|
-
if (tenant_id !== void 0 && tenant_id !== null) {
|
|
131
|
-
if (typeof tenant_id !== "string") return void 0;
|
|
132
|
-
membership.tenantId = tenant_id;
|
|
133
|
-
}
|
|
134
|
-
if (tenant_name !== void 0 && tenant_name !== null) {
|
|
135
|
-
if (typeof tenant_name !== "string") return void 0;
|
|
136
|
-
membership.tenantName = tenant_name;
|
|
137
|
-
}
|
|
138
|
-
if (tenant_roles !== void 0 && tenant_roles !== null) {
|
|
139
|
-
if (!isStringArray(tenant_roles)) return void 0;
|
|
140
|
-
membership.tenantRoles = tenant_roles;
|
|
141
|
-
}
|
|
142
|
-
if (root_group_id !== void 0 && root_group_id !== null) {
|
|
143
|
-
if (typeof root_group_id !== "string") return void 0;
|
|
144
|
-
membership.rootGroupId = root_group_id;
|
|
145
|
-
}
|
|
146
|
-
if (groups !== void 0 && groups !== null) {
|
|
147
|
-
if (!isPlainObject(groups)) return void 0;
|
|
148
|
-
const entries = Object.entries(groups).filter(([, roles]) => roles !== null);
|
|
149
|
-
if (!entries.every(([, roles]) => isStringArray(roles))) return void 0;
|
|
150
|
-
membership.groups = Object.fromEntries(entries);
|
|
151
|
-
}
|
|
152
|
-
if (group_names !== void 0 && group_names !== null) {
|
|
153
|
-
if (!isPlainObject(group_names)) return void 0;
|
|
154
|
-
const entries = Object.entries(group_names).filter(([, name]) => name !== null);
|
|
155
|
-
if (!entries.every(([, name]) => typeof name === "string")) return void 0;
|
|
156
|
-
membership.groupNames = Object.fromEntries(entries);
|
|
157
|
-
}
|
|
158
|
-
return membership;
|
|
159
|
-
}
|
|
160
|
-
/** A membership that fails to decode drops that tenant only: the shape is informational, the token stays valid. */
|
|
161
|
-
function decodeTenants(value) {
|
|
162
|
-
if (!isPlainObject(value)) return {};
|
|
163
|
-
const tenants = [];
|
|
164
|
-
for (const [tenantId, raw] of Object.entries(value)) {
|
|
165
|
-
const membership = decodeMembership(raw);
|
|
166
|
-
if (membership !== void 0) tenants.push([tenantId, membership]);
|
|
167
|
-
}
|
|
168
|
-
return Object.fromEntries(tenants);
|
|
169
|
-
}
|
|
170
|
-
/** Fail-closed claim extraction from a payload whose signature and registered claims already passed. */
|
|
171
|
-
function extractClaims(payload, verifiedAt) {
|
|
172
|
-
const { sub, iss, aud, exp, iat, auth_time: authTime, acr, amr, scopes, sid, type, passflow_tm: tenants } = payload;
|
|
173
|
-
const claims = {
|
|
174
|
-
sub: typeof sub === "string" ? sub : "",
|
|
175
|
-
iss: typeof iss === "string" ? iss : "",
|
|
176
|
-
aud: typeof aud === "string" ? [aud] : stringsOf(aud),
|
|
177
|
-
exp,
|
|
178
|
-
acr: typeof acr === "string" ? acr : "0",
|
|
179
|
-
amr: stringsOf(amr),
|
|
180
|
-
scopes: stringsOf(scopes),
|
|
181
|
-
type: typeof type === "string" ? type : "",
|
|
182
|
-
tenants: decodeTenants(tenants),
|
|
183
|
-
verifiedAt,
|
|
184
|
-
raw: payload
|
|
185
|
-
};
|
|
186
|
-
if (isExactSeconds(iat)) claims.iat = iat;
|
|
187
|
-
if (isExactSeconds(authTime)) claims.authTime = Math.trunc(authTime);
|
|
188
|
-
if (typeof sid === "string") claims.sid = sid;
|
|
189
|
-
return claims;
|
|
190
|
-
}
|
|
191
|
-
/**
|
|
192
|
-
* The roles a user holds in a tenant: `groups[rootGroupId]`, the rule the server's `CalcTenantRoles` and
|
|
193
|
-
* `@passflow/core`'s `parseMembership` apply. A missing tenant, root group or map gives an empty list.
|
|
194
|
-
* So does an empty `rootGroupId`, unlike the server: no role is granted from a group keyed by "".
|
|
195
|
-
* `tenantRoles` is a copy the server derives from the same root group, and is not consulted.
|
|
196
|
-
*/
|
|
197
|
-
function rolesOf(claims, tenantId) {
|
|
198
|
-
const { tenants } = claims;
|
|
199
|
-
if (!isPlainObject(tenants) || !Object.hasOwn(tenants, tenantId)) return [];
|
|
200
|
-
const { groups, rootGroupId } = tenants[tenantId];
|
|
201
|
-
if (!isPlainObject(groups) || !rootGroupId || !Object.hasOwn(groups, rootGroupId)) return [];
|
|
202
|
-
return [...groups[rootGroupId]];
|
|
203
|
-
}
|
|
204
|
-
// src/cors.ts
|
|
205
|
-
const CHALLENGE_HEADER = "WWW-Authenticate";
|
|
206
|
-
const CORS_EXPOSED_HEADERS = Object.freeze([CHALLENGE_HEADER]);
|
|
207
|
-
/**
|
|
208
|
-
* Appends `WWW-Authenticate` to an expose list unless it is already there, compared case-insensitively.
|
|
209
|
-
* Everything else is kept as given, `*` and duplicates included: `*` is not a wildcard on a
|
|
210
|
-
* credentialed request, so the explicit entry is what matters. This guarantees exactly one thing, that
|
|
211
|
-
* the header appears as an explicit entry.
|
|
212
|
-
*
|
|
213
|
-
* Internal. Each adapter wraps it under the option name its CORS middleware uses.
|
|
214
|
-
*/
|
|
215
|
-
function withChallengeHeader(existing) {
|
|
216
|
-
const entries = typeof existing === "string" ? existing.split(",").map((entry) => entry.trim()).filter((entry) => entry !== "") : [...existing ?? []];
|
|
217
|
-
return entries.some((entry) => entry.toLowerCase() === "WWW-Authenticate".toLowerCase()) ? entries : [...entries, CHALLENGE_HEADER];
|
|
218
|
-
}
|
|
219
|
-
// src/errors.ts
|
|
220
|
-
const MESSAGES = {
|
|
221
|
-
missing_token: "[passflow] no bearer token presented",
|
|
222
|
-
invalid_token: "[passflow] invalid token",
|
|
223
|
-
jwks_unavailable: "[passflow] key set unavailable"
|
|
224
|
-
};
|
|
225
|
-
/**
|
|
226
|
-
* An authentication failure. The message is fixed per code and carries nothing from the token, the
|
|
227
|
-
* request or the JWKS URL. A jose error is never attached as `cause`: jose's claim errors keep the
|
|
228
|
-
* whole payload on `.payload`.
|
|
229
|
-
*/
|
|
230
|
-
var PassflowAuthError = class extends Error {
|
|
231
|
-
code;
|
|
232
|
-
reason;
|
|
233
|
-
status;
|
|
234
|
-
constructor(code, reason, options) {
|
|
235
|
-
super(reason === void 0 ? MESSAGES[code] : `${MESSAGES[code]}: ${reason}`, options);
|
|
236
|
-
this.name = "PassflowAuthError";
|
|
237
|
-
this.code = code;
|
|
238
|
-
this.status = code === "jwks_unavailable" ? 503 : 401;
|
|
239
|
-
if (reason !== void 0) this.reason = reason;
|
|
240
|
-
}
|
|
241
|
-
};
|
|
242
|
-
/**
|
|
243
|
-
* A programming error, such as reading the claims before any middleware ran. It is deliberately not
|
|
244
|
-
* a `PassflowAuthError`: those mean 401/503, which the browser SDK acts on, and this must reach the
|
|
245
|
-
* framework's error handling as a 500.
|
|
246
|
-
*/
|
|
247
|
-
var PassflowUsageError = class extends Error {
|
|
248
|
-
constructor(message) {
|
|
249
|
-
super(message);
|
|
250
|
-
this.name = "PassflowUsageError";
|
|
251
|
-
}
|
|
252
|
-
};
|
|
253
|
-
/**
|
|
254
|
-
* True for a `PassflowAuthError`, including one from the other copy of this package when the ESM
|
|
255
|
-
* and CJS builds are both loaded, where `instanceof` alone would say no.
|
|
256
|
-
*/
|
|
257
|
-
function isPassflowAuthError(e) {
|
|
258
|
-
if (e instanceof PassflowAuthError) return true;
|
|
259
|
-
if (!(e instanceof Error) || e.name !== "PassflowAuthError") return false;
|
|
260
|
-
const { code } = e;
|
|
261
|
-
return code === "missing_token" || code === "invalid_token" || code === "jwks_unavailable";
|
|
262
|
-
}
|
|
263
|
-
// src/evaluate.ts
|
|
264
|
-
const CACHE_CONTROL = "Cache-Control";
|
|
265
|
-
const NO_STORE = "no-store";
|
|
266
|
-
const reject = (status, wwwAuthenticate) => ({
|
|
267
|
-
kind: "reject",
|
|
268
|
-
status,
|
|
269
|
-
headers: wwwAuthenticate === void 0 ? { [CACHE_CONTROL]: NO_STORE } : {
|
|
270
|
-
[CHALLENGE_HEADER]: wwwAuthenticate,
|
|
271
|
-
[CACHE_CONTROL]: NO_STORE
|
|
272
|
-
}
|
|
273
|
-
});
|
|
274
|
-
/**
|
|
275
|
-
* Authentication failures never carry the step-up error: the browser SDK acts only on the step-up challenge,
|
|
276
|
-
* and every other response, a plain 401 or a 503 included, reaches the caller's code unchanged.
|
|
277
|
-
*/
|
|
278
|
-
function rejectAuthentication(code) {
|
|
279
|
-
switch (code) {
|
|
280
|
-
case "missing_token": return reject(401, "Bearer");
|
|
281
|
-
case "invalid_token": return reject(401, "Bearer error=\"invalid_token\"");
|
|
282
|
-
case "jwks_unavailable": return reject(503);
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
/**
|
|
286
|
-
* Validates a requirement and returns it with the effective freshness limit. Throws `TypeError`: this is a
|
|
287
|
-
* programming error that should stop the process at route registration, not become a `Decision`.
|
|
288
|
-
*
|
|
289
|
-
* Internal: `requireACR` and `requireFresh` call it at construction.
|
|
290
|
-
*/
|
|
291
|
-
function assertRequirement(requirement) {
|
|
292
|
-
if (typeof requirement === "object" && requirement !== null) {
|
|
293
|
-
if (requirement.kind === "acr") {
|
|
294
|
-
if (parseACRLevel(requirement.min) === 0n) throw new TypeError("[passflow] the required ACR must parse to a level above 0");
|
|
295
|
-
return requirement;
|
|
296
|
-
}
|
|
297
|
-
if (requirement.kind === "fresh") return {
|
|
298
|
-
kind: "fresh",
|
|
299
|
-
maxAgeSeconds: assertMaxAge(requirement.maxAgeSeconds)
|
|
300
|
-
};
|
|
301
|
-
}
|
|
302
|
-
throw new TypeError("[passflow] a requirement is { kind: \"acr\", min } or { kind: \"fresh\", maxAgeSeconds }");
|
|
303
|
-
}
|
|
304
|
-
function isFresh(claims, maxAgeSeconds) {
|
|
305
|
-
const { authTime, verifiedAt } = claims;
|
|
306
|
-
if (!isExactSeconds(authTime)) return false;
|
|
307
|
-
return (typeof verifiedAt === "number" && Number.isFinite(verifiedAt) && verifiedAt > 0 ? Math.floor(verifiedAt) : Math.floor(Date.now() / 1e3)) - Math.trunc(authTime) <= maxAgeSeconds;
|
|
308
|
-
}
|
|
309
|
-
/**
|
|
310
|
-
* Decides one requirement against claims. No claims means the middleware was composed wrongly, so the answer
|
|
311
|
-
* is a 500 with no challenge: never a step-up, which the SDK would try to satisfy, and never a 401, because a
|
|
312
|
-
* wiring bug must not be reported as a bad token. Throws `TypeError` on an invalid requirement.
|
|
313
|
-
*/
|
|
314
|
-
function evaluate(claims, requirement) {
|
|
315
|
-
const checked = assertRequirement(requirement);
|
|
316
|
-
if (claims === void 0 || claims === null) return reject(500);
|
|
317
|
-
if (checked.kind === "acr") return acrSatisfies(claims.acr, checked.min) ? { kind: "allow" } : reject(401, formatChallenge({ acrValues: checked.min }));
|
|
318
|
-
return isFresh(claims, checked.maxAgeSeconds) ? { kind: "allow" } : reject(401, formatChallenge({ maxAge: checked.maxAgeSeconds }));
|
|
319
|
-
}
|
|
320
|
-
/**
|
|
321
|
-
* Authenticates a request. `existing` claims are reused only when `verifier` produced that exact object;
|
|
322
|
-
* otherwise the presented header is verified with `verifier`, so a token outside this verifier's trust policy
|
|
323
|
-
* is rejected as not valid here, never as insufficient. Never rejects: a failure is a `{ reject }` value.
|
|
324
|
-
*/
|
|
325
|
-
async function authenticate(verifier, authorization, existing) {
|
|
326
|
-
if (existing !== void 0 && existing !== null && verifiedBy(existing, verifier)) return { claims: existing };
|
|
327
|
-
const token = extractBearer(authorization);
|
|
328
|
-
if (token === void 0) return { reject: rejectAuthentication("missing_token") };
|
|
329
|
-
try {
|
|
330
|
-
return { claims: await verifier.verify(token) };
|
|
331
|
-
} catch (error) {
|
|
332
|
-
return { reject: isPassflowAuthError(error) ? rejectAuthentication(error.code) : reject(500) };
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
/**
|
|
336
|
-
* Internal: one adapter step. Authenticates, then applies the requirement if there is one.
|
|
337
|
-
*/
|
|
338
|
-
async function guard(verifier, authorization, existing, requirement) {
|
|
339
|
-
const result = await authenticate(verifier, authorization, existing);
|
|
340
|
-
if ("reject" in result || requirement === void 0) return result;
|
|
341
|
-
const decision = evaluate(result.claims, requirement);
|
|
342
|
-
return decision.kind === "reject" ? { reject: decision } : result;
|
|
343
|
-
}
|
|
344
|
-
/** Internal: the adapters fail at construction when handed something that cannot verify. */
|
|
345
|
-
function assertVerifier(verifier) {
|
|
346
|
-
if (typeof verifier !== "object" || verifier === null || typeof verifier.verify !== "function") throw new TypeError("[passflow] an adapter needs a verifier from createVerifier");
|
|
347
|
-
}
|
|
348
|
-
export { acrLevel as C, ACR_NONE as S, formatChallenge as _, guard as a, AAL2 as b, isPassflowAuthError as c, withChallengeHeader as d, extractClaims as f, assertMaxAge as g, verifiedBy as h, evaluate as i, CHALLENGE_HEADER as l, rolesOf as m, assertVerifier as n, PassflowAuthError as o, recordProvenance as p, authenticate as r, PassflowUsageError as s, assertRequirement as t, CORS_EXPOSED_HEADERS as u, extractBearer as v, acrSatisfies as w, AAL3 as x, AAL1 as y };
|