@_mustachio/openauth 0.10.0 → 0.12.0
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/dist/esm/adapters/d1/index.js +18 -9
- package/dist/esm/adapters/d1/migrations.js +7 -2
- package/dist/esm/adapters/d1/session-store.js +39 -0
- package/dist/esm/adapters/d1/session.js +2 -2
- package/dist/esm/adapters/durable-object/index.js +4 -0
- package/dist/esm/adapters/durable-object/session-store.js +42 -0
- package/dist/esm/adapters/dynamo/index.js +24 -7
- package/dist/esm/adapters/dynamo/session-store.js +49 -0
- package/dist/esm/adapters/kms/index.js +6 -2
- package/dist/esm/adapters/kv/index.js +6 -2
- package/dist/esm/adapters/memory/index.js +24 -7
- package/dist/esm/adapters/memory/session-store.js +45 -0
- package/dist/esm/adapters/memory/token-store.js +13 -0
- package/dist/esm/adapters/postgres/executor.js +2 -2
- package/dist/esm/adapters/postgres/index.js +33 -10
- package/dist/esm/adapters/postgres/migrations.js +8 -2
- package/dist/esm/adapters/postgres/session-store.js +42 -0
- package/dist/esm/client.js +35 -28
- package/dist/esm/domain/authorize.js +7 -2
- package/dist/esm/domain/callback.js +124 -7
- package/dist/esm/domain/client-auth.js +2 -2
- package/dist/esm/domain/crypto.js +14 -14
- package/dist/esm/domain/discovery.js +46 -4
- package/dist/esm/domain/dpop.js +122 -0
- package/dist/esm/domain/id-token.js +94 -0
- package/dist/esm/domain/introspect.js +5 -1
- package/dist/esm/domain/jwt.js +30 -2
- package/dist/esm/domain/logout.js +75 -0
- package/dist/esm/domain/method-dispatch.js +27 -1
- package/dist/esm/domain/method-route.js +83 -1
- package/dist/esm/domain/par.js +51 -0
- package/dist/esm/domain/pkce.js +2 -2
- package/dist/esm/domain/refresh.js +12 -1
- package/dist/esm/domain/register.js +74 -0
- package/dist/esm/domain/revoke.js +2 -2
- package/dist/esm/domain/state-envelope.js +2 -2
- package/dist/esm/domain/token-exchange.js +1 -0
- package/dist/esm/domain/token.js +53 -12
- package/dist/esm/domain/userinfo.js +38 -3
- package/dist/esm/error.js +8 -8
- package/dist/esm/http/cookies.js +19 -2
- package/dist/esm/http/errors.js +4 -4
- package/dist/esm/http/handlers/authorize.js +92 -21
- package/dist/esm/http/handlers/callback.js +7 -1
- package/dist/esm/http/handlers/end-session.js +64 -0
- package/dist/esm/http/handlers/metadata.js +7 -4
- package/dist/esm/http/handlers/method-route.js +47 -2
- package/dist/esm/http/handlers/par.js +53 -0
- package/dist/esm/http/handlers/register.js +46 -0
- package/dist/esm/http/handlers/revocation.js +2 -2
- package/dist/esm/http/handlers/token.js +36 -6
- package/dist/esm/http/handlers/userinfo.js +35 -29
- package/dist/esm/http/middleware/tenant.js +6 -6
- package/dist/esm/http/router.js +10 -0
- package/dist/esm/http/schemas/authorize.js +8 -2
- package/dist/esm/http/schemas/end-session.js +13 -0
- package/dist/esm/http/schemas/par.js +9 -0
- package/dist/esm/http/schemas/register.js +16 -0
- package/dist/esm/http/schemas/revocation.js +2 -2
- package/dist/esm/http/schemas/token.js +7 -7
- package/dist/esm/index.js +40 -34
- package/dist/esm/methods/oauth2-factory.js +2 -2
- package/dist/esm/methods/password-hash.js +2 -2
- package/dist/esm/methods/providers/index.js +30 -14
- package/dist/esm/methods/saml-sp/acs.js +208 -0
- package/dist/esm/methods/saml-sp/attributes.js +75 -0
- package/dist/esm/methods/saml-sp/authnrequest.js +63 -0
- package/dist/esm/methods/saml-sp/cache-provider.js +33 -0
- package/dist/esm/methods/saml-sp/cert-rotation.js +13 -0
- package/dist/esm/methods/saml-sp/factory.js +70 -0
- package/dist/esm/methods/saml-sp/index.js +7 -0
- package/dist/esm/methods/saml-sp/metadata.js +69 -0
- package/dist/esm/methods/saml-sp/method.js +29 -0
- package/dist/esm/methods/saml-sp/parse-idp-metadata.js +102 -0
- package/dist/esm/methods/saml-sp/saml-instance.js +49 -0
- package/dist/esm/methods/saml-sp/slo-initiate.js +84 -0
- package/dist/esm/methods/saml-sp/sls.js +154 -0
- package/dist/esm/methods/saml-sp/types.js +0 -0
- package/dist/esm/types/error.js +5 -0
- package/dist/esm/types/result.js +3 -3
- package/dist/esm/ui/forms.js +3 -3
- package/dist/esm/ui/index.js +8 -5
- package/dist/esm/ui/picker.js +2 -2
- package/dist/types/adapters/d1/migrations.d.ts.map +1 -1
- package/dist/types/adapters/d1/session-store.d.ts +3 -0
- package/dist/types/adapters/d1/session-store.d.ts.map +1 -1
- package/dist/types/adapters/durable-object/session-store.d.ts +3 -0
- package/dist/types/adapters/durable-object/session-store.d.ts.map +1 -1
- package/dist/types/adapters/dynamo/session-store.d.ts +3 -0
- package/dist/types/adapters/dynamo/session-store.d.ts.map +1 -1
- package/dist/types/adapters/memory/session-store.d.ts +6 -1
- package/dist/types/adapters/memory/session-store.d.ts.map +1 -1
- package/dist/types/adapters/memory/token-store.d.ts +1 -0
- package/dist/types/adapters/memory/token-store.d.ts.map +1 -1
- package/dist/types/adapters/postgres/migrations.d.ts +1 -1
- package/dist/types/adapters/postgres/migrations.d.ts.map +1 -1
- package/dist/types/adapters/postgres/session-store.d.ts +3 -0
- package/dist/types/adapters/postgres/session-store.d.ts.map +1 -1
- package/dist/types/client.d.ts +19 -0
- package/dist/types/client.d.ts.map +1 -1
- package/dist/types/domain/authorize.d.ts.map +1 -1
- package/dist/types/domain/callback.d.ts +16 -1
- package/dist/types/domain/callback.d.ts.map +1 -1
- package/dist/types/domain/client-credentials.d.ts +2 -0
- package/dist/types/domain/client-credentials.d.ts.map +1 -1
- package/dist/types/domain/discovery.d.ts +37 -0
- package/dist/types/domain/discovery.d.ts.map +1 -1
- package/dist/types/domain/dpop.d.ts +61 -0
- package/dist/types/domain/dpop.d.ts.map +1 -0
- package/dist/types/domain/id-token.d.ts +83 -0
- package/dist/types/domain/id-token.d.ts.map +1 -0
- package/dist/types/domain/introspect.d.ts +8 -0
- package/dist/types/domain/introspect.d.ts.map +1 -1
- package/dist/types/domain/jwt.d.ts +27 -1
- package/dist/types/domain/jwt.d.ts.map +1 -1
- package/dist/types/domain/logout.d.ts +69 -0
- package/dist/types/domain/logout.d.ts.map +1 -0
- package/dist/types/domain/method-dispatch.d.ts.map +1 -1
- package/dist/types/domain/method-route.d.ts +57 -1
- package/dist/types/domain/method-route.d.ts.map +1 -1
- package/dist/types/domain/par.d.ts +62 -0
- package/dist/types/domain/par.d.ts.map +1 -0
- package/dist/types/domain/refresh.d.ts +9 -0
- package/dist/types/domain/refresh.d.ts.map +1 -1
- package/dist/types/domain/register.d.ts +33 -0
- package/dist/types/domain/register.d.ts.map +1 -0
- package/dist/types/domain/token-exchange.d.ts +2 -0
- package/dist/types/domain/token-exchange.d.ts.map +1 -1
- package/dist/types/domain/token.d.ts +41 -1
- package/dist/types/domain/token.d.ts.map +1 -1
- package/dist/types/domain/userinfo.d.ts +44 -5
- package/dist/types/domain/userinfo.d.ts.map +1 -1
- package/dist/types/http/context.d.ts +6 -1
- package/dist/types/http/context.d.ts.map +1 -1
- package/dist/types/http/cookies.d.ts +9 -1
- package/dist/types/http/cookies.d.ts.map +1 -1
- package/dist/types/http/handlers/authorize.d.ts.map +1 -1
- package/dist/types/http/handlers/callback.d.ts.map +1 -1
- package/dist/types/http/handlers/end-session.d.ts +3 -0
- package/dist/types/http/handlers/end-session.d.ts.map +1 -0
- package/dist/types/http/handlers/metadata.d.ts +1 -1
- package/dist/types/http/handlers/metadata.d.ts.map +1 -1
- package/dist/types/http/handlers/method-route.d.ts.map +1 -1
- package/dist/types/http/handlers/par.d.ts +3 -0
- package/dist/types/http/handlers/par.d.ts.map +1 -0
- package/dist/types/http/handlers/register.d.ts +3 -0
- package/dist/types/http/handlers/register.d.ts.map +1 -0
- package/dist/types/http/handlers/token.d.ts.map +1 -1
- package/dist/types/http/handlers/userinfo.d.ts.map +1 -1
- package/dist/types/http/router.d.ts.map +1 -1
- package/dist/types/http/schemas/authorize.d.ts +40 -0
- package/dist/types/http/schemas/authorize.d.ts.map +1 -1
- package/dist/types/http/schemas/end-session.d.ts +31 -0
- package/dist/types/http/schemas/end-session.d.ts.map +1 -0
- package/dist/types/http/schemas/par.d.ts +20 -0
- package/dist/types/http/schemas/par.d.ts.map +1 -0
- package/dist/types/http/schemas/register.d.ts +42 -0
- package/dist/types/http/schemas/register.d.ts.map +1 -0
- package/dist/types/index.d.ts +3 -3
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/methods/saml-sp/acs.d.ts +4 -0
- package/dist/types/methods/saml-sp/acs.d.ts.map +1 -0
- package/dist/types/methods/saml-sp/attributes.d.ts +40 -0
- package/dist/types/methods/saml-sp/attributes.d.ts.map +1 -0
- package/dist/types/methods/saml-sp/authnrequest.d.ts +4 -0
- package/dist/types/methods/saml-sp/authnrequest.d.ts.map +1 -0
- package/dist/types/methods/saml-sp/cache-provider.d.ts +38 -0
- package/dist/types/methods/saml-sp/cache-provider.d.ts.map +1 -0
- package/dist/types/methods/saml-sp/cert-rotation.d.ts +23 -0
- package/dist/types/methods/saml-sp/cert-rotation.d.ts.map +1 -0
- package/dist/types/methods/saml-sp/factory.d.ts +704 -0
- package/dist/types/methods/saml-sp/factory.d.ts.map +1 -0
- package/dist/types/methods/saml-sp/index.d.ts +24 -0
- package/dist/types/methods/saml-sp/index.d.ts.map +1 -0
- package/dist/types/methods/saml-sp/metadata.d.ts +42 -0
- package/dist/types/methods/saml-sp/metadata.d.ts.map +1 -0
- package/dist/types/methods/saml-sp/method.d.ts +17 -0
- package/dist/types/methods/saml-sp/method.d.ts.map +1 -0
- package/dist/types/methods/saml-sp/parse-idp-metadata.d.ts +4 -0
- package/dist/types/methods/saml-sp/parse-idp-metadata.d.ts.map +1 -0
- package/dist/types/methods/saml-sp/saml-instance.d.ts +81 -0
- package/dist/types/methods/saml-sp/saml-instance.d.ts.map +1 -0
- package/dist/types/methods/saml-sp/slo-initiate.d.ts +4 -0
- package/dist/types/methods/saml-sp/slo-initiate.d.ts.map +1 -0
- package/dist/types/methods/saml-sp/sls.d.ts +4 -0
- package/dist/types/methods/saml-sp/sls.d.ts.map +1 -0
- package/dist/types/methods/saml-sp/types.d.ts +204 -0
- package/dist/types/methods/saml-sp/types.d.ts.map +1 -0
- package/dist/types/ports/audit-log.d.ts +40 -0
- package/dist/types/ports/audit-log.d.ts.map +1 -1
- package/dist/types/ports/session-store.d.ts +50 -0
- package/dist/types/ports/session-store.d.ts.map +1 -1
- package/dist/types/ports/token-store.d.ts +12 -0
- package/dist/types/ports/token-store.d.ts.map +1 -1
- package/dist/types/types/authorization.d.ts +23 -0
- package/dist/types/types/authorization.d.ts.map +1 -1
- package/dist/types/types/error.d.ts +9 -0
- package/dist/types/types/error.d.ts.map +1 -1
- package/dist/types/types/flow.d.ts +10 -0
- package/dist/types/types/flow.d.ts.map +1 -1
- package/dist/types/types/idp.d.ts +162 -1
- package/dist/types/types/idp.d.ts.map +1 -1
- package/dist/types/types/method.d.ts +109 -0
- package/dist/types/types/method.d.ts.map +1 -1
- package/dist/types/types/tenant.d.ts +37 -0
- package/dist/types/types/tenant.d.ts.map +1 -1
- package/dist/types/types/token.d.ts +128 -0
- package/dist/types/types/token.d.ts.map +1 -1
- package/package.json +9 -1
- package/src/adapters/d1/migrations.ts +5 -0
- package/src/adapters/d1/session-store.ts +68 -0
- package/src/adapters/durable-object/session-store.ts +61 -0
- package/src/adapters/dynamo/session-store.ts +63 -0
- package/src/adapters/memory/session-store.ts +83 -1
- package/src/adapters/memory/token-store.ts +16 -0
- package/src/adapters/postgres/migrations.ts +6 -0
- package/src/adapters/postgres/session-store.ts +69 -0
- package/src/client.ts +32 -0
- package/src/domain/authorize.ts +9 -0
- package/src/domain/callback.ts +220 -7
- package/src/domain/client-credentials.ts +2 -0
- package/src/domain/discovery.ts +80 -2
- package/src/domain/dpop.ts +293 -0
- package/src/domain/id-token.ts +213 -0
- package/src/domain/introspect.ts +10 -0
- package/src/domain/jwt.ts +80 -1
- package/src/domain/logout.ts +180 -0
- package/src/domain/method-dispatch.ts +53 -1
- package/src/domain/method-route.ts +195 -1
- package/src/domain/par.ts +141 -0
- package/src/domain/refresh.ts +41 -0
- package/src/domain/register.ts +168 -0
- package/src/domain/token-exchange.ts +11 -0
- package/src/domain/token.ts +134 -8
- package/src/domain/userinfo.ts +121 -6
- package/src/http/context.ts +10 -0
- package/src/http/cookies.ts +19 -1
- package/src/http/handlers/authorize.ts +146 -24
- package/src/http/handlers/callback.ts +9 -1
- package/src/http/handlers/end-session.ts +106 -0
- package/src/http/handlers/metadata.ts +7 -2
- package/src/http/handlers/method-route.ts +75 -2
- package/src/http/handlers/par.ts +84 -0
- package/src/http/handlers/register.ts +70 -0
- package/src/http/handlers/token.ts +56 -0
- package/src/http/handlers/userinfo.ts +62 -38
- package/src/http/router.ts +19 -0
- package/src/http/schemas/authorize.ts +27 -0
- package/src/http/schemas/end-session.ts +23 -0
- package/src/http/schemas/par.ts +23 -0
- package/src/http/schemas/register.ts +29 -0
- package/src/index.ts +21 -1
- package/src/methods/saml-sp/acs.ts +399 -0
- package/src/methods/saml-sp/attributes.ts +137 -0
- package/src/methods/saml-sp/authnrequest.ts +128 -0
- package/src/methods/saml-sp/cache-provider.ts +76 -0
- package/src/methods/saml-sp/cert-rotation.ts +34 -0
- package/src/methods/saml-sp/factory.ts +118 -0
- package/src/methods/saml-sp/index.ts +34 -0
- package/src/methods/saml-sp/metadata.ts +204 -0
- package/src/methods/saml-sp/method.ts +65 -0
- package/src/methods/saml-sp/parse-idp-metadata.ts +164 -0
- package/src/methods/saml-sp/saml-instance.ts +173 -0
- package/src/methods/saml-sp/slo-initiate.ts +177 -0
- package/src/methods/saml-sp/sls.ts +306 -0
- package/src/methods/saml-sp/types.ts +203 -0
- package/src/ports/CONSISTENCY.md +77 -21
- package/src/ports/audit-log.ts +42 -0
- package/src/ports/session-store.ts +61 -0
- package/src/ports/token-store.ts +13 -0
- package/src/types/authorization.ts +25 -0
- package/src/types/error.ts +23 -0
- package/src/types/flow.ts +10 -0
- package/src/types/idp.ts +170 -0
- package/src/types/method.ts +110 -0
- package/src/types/tenant.ts +37 -0
- package/src/types/token.ts +135 -0
|
@@ -13,7 +13,8 @@ async function dispatchMethod(input) {
|
|
|
13
13
|
flow: input.flow,
|
|
14
14
|
methodState: input.flow?.methodState ?? null,
|
|
15
15
|
cookies: input.cookies,
|
|
16
|
-
dispatch: input.dispatch
|
|
16
|
+
dispatch: input.dispatch,
|
|
17
|
+
methodScratch: buildMethodScratch(input.sessionStore, input.tenant.id, input.method.id)
|
|
17
18
|
};
|
|
18
19
|
let result;
|
|
19
20
|
try {
|
|
@@ -31,6 +32,31 @@ async function dispatchMethod(input) {
|
|
|
31
32
|
}
|
|
32
33
|
return ok(result);
|
|
33
34
|
}
|
|
35
|
+
function buildMethodScratch(store, tenantId, methodId) {
|
|
36
|
+
const prefix = `scratch:${tenantId}:${methodId}:`;
|
|
37
|
+
const scope = (key) => `${prefix}${key}`;
|
|
38
|
+
const unsupported = (op) => authError.internalError(`SessionStore does not implement ${op}; methodScratch is unavailable on this adapter`);
|
|
39
|
+
return {
|
|
40
|
+
put: async (key, value, ttlMs) => {
|
|
41
|
+
if (!store.saveScratch)
|
|
42
|
+
return err(unsupported("saveScratch"));
|
|
43
|
+
if (ttlMs <= 0) {
|
|
44
|
+
return err(authError.internalError(`methodScratch.put: ttlMs must be positive, got ${ttlMs}`));
|
|
45
|
+
}
|
|
46
|
+
return store.saveScratch(scope(key), value, ttlMs);
|
|
47
|
+
},
|
|
48
|
+
get: async (key) => {
|
|
49
|
+
if (!store.readScratch)
|
|
50
|
+
return err(unsupported("readScratch"));
|
|
51
|
+
return store.readScratch(scope(key));
|
|
52
|
+
},
|
|
53
|
+
delete: async (key) => {
|
|
54
|
+
if (!store.deleteScratch)
|
|
55
|
+
return err(unsupported("deleteScratch"));
|
|
56
|
+
return store.deleteScratch(scope(key));
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
}
|
|
34
60
|
export {
|
|
35
61
|
dispatchMethod
|
|
36
62
|
};
|
|
@@ -5,6 +5,7 @@ import { safeAudit } from "./audit";
|
|
|
5
5
|
import { AUTH_CODE_TTL_MS } from "./authorize";
|
|
6
6
|
import { randomToken } from "./crypto";
|
|
7
7
|
import { dispatchMethod } from "./method-dispatch";
|
|
8
|
+
import { revokeAllForSubject } from "./revoke";
|
|
8
9
|
import { saveEncryptedCode } from "./token";
|
|
9
10
|
async function handleMethodRoute(input, deps) {
|
|
10
11
|
const flowRes = await deps.sessionStore.readFlow(input.flowId);
|
|
@@ -65,6 +66,9 @@ async function translate(result, flow, deps) {
|
|
|
65
66
|
context: final.context ?? null,
|
|
66
67
|
providerSubject: result.providerSubject,
|
|
67
68
|
properties: result.properties,
|
|
69
|
+
...final.appNonce !== undefined ? { appNonce: final.appNonce } : {},
|
|
70
|
+
...final.claimsRequest !== undefined ? { claimsRequest: final.claimsRequest } : {},
|
|
71
|
+
authTime: Math.floor(now / 1000),
|
|
68
72
|
expiresAt: now + AUTH_CODE_TTL_MS
|
|
69
73
|
}, AUTH_CODE_TTL_MS, { keyStore: deps.keyStore, tokenStore: deps.tokenStore });
|
|
70
74
|
if (isErr(saved))
|
|
@@ -103,6 +107,84 @@ async function translate(result, flow, deps) {
|
|
|
103
107
|
return err(result.error);
|
|
104
108
|
}
|
|
105
109
|
}
|
|
110
|
+
async function handlePublicMethodRoute(input, deps) {
|
|
111
|
+
if (!input.method.publicRoutes?.includes(input.route)) {
|
|
112
|
+
return err(authError.invalidRequest(`route "${input.route}" is not public on method "${input.method.id}"`, "path"));
|
|
113
|
+
}
|
|
114
|
+
const dispatched = await dispatchMethod({
|
|
115
|
+
method: input.method,
|
|
116
|
+
route: input.route,
|
|
117
|
+
tenant: input.tenant,
|
|
118
|
+
request: input.rawRequest,
|
|
119
|
+
subPath: input.subPath,
|
|
120
|
+
flow: null,
|
|
121
|
+
cookies: new Map,
|
|
122
|
+
sessionStore: deps.sessionStore,
|
|
123
|
+
dispatch: input.dispatch
|
|
124
|
+
});
|
|
125
|
+
if (isErr(dispatched))
|
|
126
|
+
return err(dispatched.error);
|
|
127
|
+
const r = dispatched.value;
|
|
128
|
+
switch (r.kind) {
|
|
129
|
+
case "challenge": {
|
|
130
|
+
if (r.logout) {
|
|
131
|
+
const sideEffect = await runUpstreamLogout(input, deps, r.logout);
|
|
132
|
+
if (isErr(sideEffect))
|
|
133
|
+
return err(sideEffect.error);
|
|
134
|
+
}
|
|
135
|
+
return ok({
|
|
136
|
+
kind: "challenge",
|
|
137
|
+
response: r.response,
|
|
138
|
+
...r.cache !== undefined ? { cache: r.cache } : {}
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
case "denied":
|
|
142
|
+
return ok({ kind: "denied", reason: r.reason });
|
|
143
|
+
case "success":
|
|
144
|
+
return err(authError.internalError(`public route "${input.route}" on method "${input.method.id}" ` + `returned success — a flowless route cannot authenticate`));
|
|
145
|
+
case "error":
|
|
146
|
+
return err(r.error);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
async function runUpstreamLogout(input, deps, logout) {
|
|
150
|
+
let hookResult = undefined;
|
|
151
|
+
if (deps.onLogout) {
|
|
152
|
+
const evt = {
|
|
153
|
+
tenant: input.tenant,
|
|
154
|
+
methodId: input.method.id,
|
|
155
|
+
methodKind: input.method.kind,
|
|
156
|
+
reason: "upstream_slo",
|
|
157
|
+
...logout.nameId !== undefined ? { nameId: logout.nameId } : {},
|
|
158
|
+
...logout.sessionIndex !== undefined ? { sessionIndex: logout.sessionIndex } : {}
|
|
159
|
+
};
|
|
160
|
+
try {
|
|
161
|
+
hookResult = await deps.onLogout(evt);
|
|
162
|
+
} catch (e) {
|
|
163
|
+
return err(authError.internalError(`onLogout hook threw during upstream Single Logout for method ` + `"${input.method.id}"`, e));
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
const revokeSubject = hookResult && typeof hookResult === "object" ? hookResult.revokeSubject : undefined;
|
|
167
|
+
if (revokeSubject) {
|
|
168
|
+
const revoked = await revokeAllForSubject(input.tenant.id, revokeSubject, {
|
|
169
|
+
tokenStore: deps.tokenStore,
|
|
170
|
+
...deps.auditLog ? { auditLog: deps.auditLog } : {},
|
|
171
|
+
clock: deps.clock
|
|
172
|
+
});
|
|
173
|
+
if (isErr(revoked))
|
|
174
|
+
return err(revoked.error);
|
|
175
|
+
}
|
|
176
|
+
await safeAudit(deps, {
|
|
177
|
+
kind: "session_logout",
|
|
178
|
+
tenantId: input.tenant.id,
|
|
179
|
+
via: "upstream_slo",
|
|
180
|
+
methodId: input.method.id,
|
|
181
|
+
methodKind: input.method.kind,
|
|
182
|
+
...revokeSubject ? { subjectId: revokeSubject } : {},
|
|
183
|
+
timestamp: deps.clock()
|
|
184
|
+
});
|
|
185
|
+
return ok(undefined);
|
|
186
|
+
}
|
|
106
187
|
export {
|
|
107
|
-
handleMethodRoute
|
|
188
|
+
handleMethodRoute,
|
|
189
|
+
handlePublicMethodRoute
|
|
108
190
|
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// src/domain/par.ts
|
|
2
|
+
import { authError } from "../types/error";
|
|
3
|
+
import { err, isErr, ok } from "../types/result";
|
|
4
|
+
import { verifyClientCredentials } from "./client-auth";
|
|
5
|
+
import { randomToken } from "./crypto";
|
|
6
|
+
var PAR_URI_PREFIX = "urn:ietf:params:oauth:request_uri:";
|
|
7
|
+
var DEFAULT_PAR_TTL_MS = 60 * 1000;
|
|
8
|
+
async function pushAuthorizationRequest(req, tenant, deps) {
|
|
9
|
+
if (!deps.sessionStore.savePar || !deps.sessionStore.consumePar) {
|
|
10
|
+
return err(authError.invalidRequest("session adapter does not implement PAR storage"));
|
|
11
|
+
}
|
|
12
|
+
const client = tenant.config.clients.find((c) => c.id === req.clientId);
|
|
13
|
+
if (!client) {
|
|
14
|
+
return err(authError.invalidClient(`unknown client "${req.clientId}"`));
|
|
15
|
+
}
|
|
16
|
+
if (client.type === "confidential") {
|
|
17
|
+
const authErr = await verifyClientCredentials(client, req.clientSecret);
|
|
18
|
+
if (authErr)
|
|
19
|
+
return err(authErr);
|
|
20
|
+
} else if (req.clientSecret !== undefined) {
|
|
21
|
+
return err(authError.invalidClient("public client must not present client_secret"));
|
|
22
|
+
}
|
|
23
|
+
if (req.params.client_id && req.params.client_id !== req.clientId) {
|
|
24
|
+
return err(authError.invalidRequest("client_id in body conflicts with authenticated client", "client_id"));
|
|
25
|
+
}
|
|
26
|
+
if ("request_uri" in req.params) {
|
|
27
|
+
return err(authError.invalidRequest("request_uri MUST NOT be present in a PAR request", "request_uri"));
|
|
28
|
+
}
|
|
29
|
+
const suffix = (deps.newRequestUriSuffix ?? randomToken)();
|
|
30
|
+
const requestUri = PAR_URI_PREFIX + suffix;
|
|
31
|
+
const ttl = deps.ttlMs ?? DEFAULT_PAR_TTL_MS;
|
|
32
|
+
const now = deps.clock();
|
|
33
|
+
const saved = await deps.sessionStore.savePar(requestUri, {
|
|
34
|
+
requestUri,
|
|
35
|
+
params: { ...req.params, client_id: req.clientId },
|
|
36
|
+
clientId: req.clientId,
|
|
37
|
+
issuedAt: now,
|
|
38
|
+
expiresAt: now + ttl
|
|
39
|
+
}, ttl);
|
|
40
|
+
if (isErr(saved))
|
|
41
|
+
return err(saved.error);
|
|
42
|
+
return ok({
|
|
43
|
+
request_uri: requestUri,
|
|
44
|
+
expires_in: Math.floor(ttl / 1000)
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
export {
|
|
48
|
+
DEFAULT_PAR_TTL_MS,
|
|
49
|
+
PAR_URI_PREFIX,
|
|
50
|
+
pushAuthorizationRequest
|
|
51
|
+
};
|
package/dist/esm/domain/pkce.js
CHANGED
|
@@ -31,6 +31,14 @@ async function refreshTokens(req, deps) {
|
|
|
31
31
|
} else if (client.type === "confidential") {
|
|
32
32
|
return err(authError.invalidGrant(INVALID_REFRESH_DESC));
|
|
33
33
|
}
|
|
34
|
+
if (peekedPayload.dpopJkt !== undefined) {
|
|
35
|
+
if (req.dpopJkt === undefined) {
|
|
36
|
+
return err(authError.invalidDpopProof("refresh token is DPoP-bound; request is missing a DPoP proof"));
|
|
37
|
+
}
|
|
38
|
+
if (req.dpopJkt !== peekedPayload.dpopJkt) {
|
|
39
|
+
return err(authError.invalidDpopProof("refresh token DPoP jkt does not match the original binding"));
|
|
40
|
+
}
|
|
41
|
+
}
|
|
34
42
|
const consumed = await deps.tokenStore.consumeRefresh(req.refreshToken, {
|
|
35
43
|
reuseWindowMs: deps.reuseWindowMs
|
|
36
44
|
});
|
|
@@ -68,7 +76,10 @@ async function refreshTokens(req, deps) {
|
|
|
68
76
|
methodId: payload.methodId,
|
|
69
77
|
methodKind: payload.methodKind,
|
|
70
78
|
scopes: requestedScopes,
|
|
71
|
-
audience: payload.audience
|
|
79
|
+
audience: payload.audience,
|
|
80
|
+
authTime: payload.authTime,
|
|
81
|
+
...payload.dpopJkt !== undefined ? { dpopJkt: payload.dpopJkt } : {},
|
|
82
|
+
...payload.claimsRequest !== undefined ? { claimsRequest: payload.claimsRequest } : {}
|
|
72
83
|
},
|
|
73
84
|
family: payload.family,
|
|
74
85
|
deps
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
// src/domain/register.ts
|
|
2
|
+
import { authError } from "../types/error";
|
|
3
|
+
import { err, isErr, ok } from "../types/result";
|
|
4
|
+
import { randomId, randomToken } from "./crypto";
|
|
5
|
+
import { hashClientSecret } from "./token";
|
|
6
|
+
async function registerNewClient(request, tenant, deps) {
|
|
7
|
+
if (!deps.registerClient) {
|
|
8
|
+
return err(authError.invalidRequest("dynamic client registration is not enabled on this deployment"));
|
|
9
|
+
}
|
|
10
|
+
if (!Array.isArray(request.redirect_uris) || request.redirect_uris.length === 0) {
|
|
11
|
+
return err(authError.invalidRequest("redirect_uris must be a non-empty array", "redirect_uris"));
|
|
12
|
+
}
|
|
13
|
+
for (const uri of request.redirect_uris) {
|
|
14
|
+
try {
|
|
15
|
+
new URL(uri);
|
|
16
|
+
} catch {
|
|
17
|
+
return err(authError.invalidRequest(`redirect_uri "${uri}" is not a valid absolute URI`, "redirect_uris"));
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
const authMethod = request.token_endpoint_auth_method ?? "client_secret_basic";
|
|
21
|
+
const isPublic = authMethod === "none";
|
|
22
|
+
const clientId = (deps.newClientId ?? randomId)();
|
|
23
|
+
const grantTypes = request.grant_types ?? ["authorization_code"];
|
|
24
|
+
const responseTypes = request.response_types ?? ["code"];
|
|
25
|
+
const scopes = request.scope ? request.scope.split(/\s+/).filter(Boolean) : ["openid"];
|
|
26
|
+
let secret;
|
|
27
|
+
let secretHash;
|
|
28
|
+
if (!isPublic) {
|
|
29
|
+
secret = (deps.newClientSecret ?? randomToken)();
|
|
30
|
+
secretHash = await hashClientSecret(secret);
|
|
31
|
+
}
|
|
32
|
+
const clientPartial = {
|
|
33
|
+
id: clientId,
|
|
34
|
+
name: request.client_name ?? clientId,
|
|
35
|
+
redirectUris: request.redirect_uris,
|
|
36
|
+
scopes,
|
|
37
|
+
grantTypes: grantTypes.filter((g) => g === "authorization_code" || g === "refresh_token" || g === "client_credentials"),
|
|
38
|
+
...request.post_logout_redirect_uris !== undefined ? { postLogoutRedirectUris: request.post_logout_redirect_uris } : {},
|
|
39
|
+
...request.sector_identifier_uri !== undefined ? { sectorIdentifier: request.sector_identifier_uri } : {}
|
|
40
|
+
};
|
|
41
|
+
const clientConfig = isPublic ? {
|
|
42
|
+
...clientPartial,
|
|
43
|
+
type: "public",
|
|
44
|
+
pkceRequired: true
|
|
45
|
+
} : {
|
|
46
|
+
...clientPartial,
|
|
47
|
+
type: "confidential",
|
|
48
|
+
secretHash,
|
|
49
|
+
pkceRequired: true
|
|
50
|
+
};
|
|
51
|
+
const hookResult = await deps.registerClient({
|
|
52
|
+
tenant,
|
|
53
|
+
request
|
|
54
|
+
});
|
|
55
|
+
if (isErr(hookResult))
|
|
56
|
+
return err(hookResult.error);
|
|
57
|
+
const persisted = hookResult.value.client;
|
|
58
|
+
const persistedSecret = hookResult.value.secret;
|
|
59
|
+
const issuedAt = Math.floor(deps.clock() / 1000);
|
|
60
|
+
return ok({
|
|
61
|
+
client_id: persisted.id,
|
|
62
|
+
...persistedSecret !== undefined ? { client_secret: persistedSecret } : {},
|
|
63
|
+
client_id_issued_at: issuedAt,
|
|
64
|
+
client_secret_expires_at: 0,
|
|
65
|
+
redirect_uris: persisted.redirectUris,
|
|
66
|
+
grant_types: persisted.grantTypes,
|
|
67
|
+
response_types: responseTypes,
|
|
68
|
+
token_endpoint_auth_method: authMethod,
|
|
69
|
+
...request.client_name !== undefined ? { client_name: request.client_name } : {}
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
export {
|
|
73
|
+
registerNewClient
|
|
74
|
+
};
|
|
@@ -75,6 +75,6 @@ function isEnvelopeShape(value) {
|
|
|
75
75
|
return typeof v.tenantId === "string" && typeof v.flowId === "string" && typeof v.nonce === "string" && typeof v.kid === "string";
|
|
76
76
|
}
|
|
77
77
|
export {
|
|
78
|
-
|
|
79
|
-
|
|
78
|
+
mintStateEnvelope,
|
|
79
|
+
verifyStateEnvelope
|
|
80
80
|
};
|
|
@@ -75,6 +75,7 @@ async function exchangeToken(req, deps) {
|
|
|
75
75
|
methodId: subjectClaims.mid ?? "token_exchange",
|
|
76
76
|
methodKind: subjectClaims.mkind ?? "token_exchange",
|
|
77
77
|
scopes: requestedScopes,
|
|
78
|
+
...subjectClaims.auth_time !== undefined ? { authTime: subjectClaims.auth_time } : {},
|
|
78
79
|
...subjectClaims.aud !== undefined && subjectClaims.aud !== callerClient.id ? { audience: subjectClaims.aud } : {}
|
|
79
80
|
},
|
|
80
81
|
family: (deps.newRefreshFamily ?? randomId)(),
|
package/dist/esm/domain/token.js
CHANGED
|
@@ -12,7 +12,8 @@ import {
|
|
|
12
12
|
sha256,
|
|
13
13
|
utf8
|
|
14
14
|
} from "./crypto";
|
|
15
|
-
import {
|
|
15
|
+
import { buildIdTokenClaims, shouldIssueIdToken } from "./id-token";
|
|
16
|
+
import { signAccessToken, signIdToken } from "./jwt";
|
|
16
17
|
import { validatePkce } from "./pkce";
|
|
17
18
|
async function saveEncryptedCode(code, payload, ttl, deps) {
|
|
18
19
|
const keyResult = await deps.keyStore.currentEncryptionKey();
|
|
@@ -57,6 +58,9 @@ async function exchangeCode(req, deps) {
|
|
|
57
58
|
const authResult = await verifyClientCredentials(client, req.clientSecret);
|
|
58
59
|
if (authResult)
|
|
59
60
|
return err(authResult);
|
|
61
|
+
if (client.dpopRequired && req.dpopJkt === undefined) {
|
|
62
|
+
return err(authError.invalidDpopProof(`client "${client.id}" requires DPoP-bound tokens`));
|
|
63
|
+
}
|
|
60
64
|
if (payload.appRedirectUri !== req.redirectUri) {
|
|
61
65
|
return err(authError.invalidGrant("redirect_uri mismatch with auth code"));
|
|
62
66
|
}
|
|
@@ -104,7 +108,10 @@ async function exchangeCode(req, deps) {
|
|
|
104
108
|
const minted = await mintTokens({
|
|
105
109
|
tenant,
|
|
106
110
|
claim,
|
|
107
|
-
payload
|
|
111
|
+
payload: {
|
|
112
|
+
...payload,
|
|
113
|
+
...req.dpopJkt !== undefined ? { dpopJkt: req.dpopJkt } : {}
|
|
114
|
+
},
|
|
108
115
|
deps,
|
|
109
116
|
family: (deps.newRefreshFamily ?? randomId)()
|
|
110
117
|
});
|
|
@@ -115,11 +122,13 @@ async function mintTokens(args) {
|
|
|
115
122
|
const accessTtl = tenant.config.accessTtl !== undefined ? tenant.config.accessTtl * 1000 : DEFAULT_ACCESS_TTL_MS;
|
|
116
123
|
const refreshTtl = tenant.config.refreshTtl !== undefined ? tenant.config.refreshTtl * 1000 : DEFAULT_REFRESH_TTL_MS;
|
|
117
124
|
const now = deps.clock();
|
|
118
|
-
const
|
|
125
|
+
const receivingClient = tenant.config.clients.find((c) => c.id === payload.clientId);
|
|
126
|
+
const subjectId = await deriveSubjectId(claim, receivingClient?.sectorIdentifier);
|
|
119
127
|
const keyRes = await deps.keyStore.currentSigningKey();
|
|
120
128
|
if (isErr(keyRes))
|
|
121
129
|
return err(keyRes.error);
|
|
122
130
|
const signingKey = keyRes.value;
|
|
131
|
+
const userinfoClaimNames = Object.keys(payload.claimsRequest?.userinfo ?? {});
|
|
123
132
|
const claims = {
|
|
124
133
|
iss: deps.issuerUrl,
|
|
125
134
|
sub: subjectId,
|
|
@@ -130,7 +139,10 @@ async function mintTokens(args) {
|
|
|
130
139
|
mid: payload.methodId,
|
|
131
140
|
mkind: payload.methodKind,
|
|
132
141
|
scope: payload.scopes.join(" "),
|
|
133
|
-
claim
|
|
142
|
+
claim,
|
|
143
|
+
...payload.authTime !== undefined ? { auth_time: payload.authTime } : {},
|
|
144
|
+
...payload.dpopJkt !== undefined ? { cnf: { jkt: payload.dpopJkt } } : {},
|
|
145
|
+
...userinfoClaimNames.length > 0 ? { uic: userinfoClaimNames } : {}
|
|
134
146
|
};
|
|
135
147
|
let accessToken;
|
|
136
148
|
try {
|
|
@@ -151,6 +163,9 @@ async function mintTokens(args) {
|
|
|
151
163
|
family,
|
|
152
164
|
methodId: payload.methodId,
|
|
153
165
|
methodKind: payload.methodKind,
|
|
166
|
+
authTime: payload.authTime ?? Math.floor(now / 1000),
|
|
167
|
+
...payload.dpopJkt !== undefined ? { dpopJkt: payload.dpopJkt } : {},
|
|
168
|
+
...payload.claimsRequest !== undefined ? { claimsRequest: payload.claimsRequest } : {},
|
|
154
169
|
issuedAt: now,
|
|
155
170
|
expiresAt: now + refreshTtl
|
|
156
171
|
};
|
|
@@ -158,6 +173,28 @@ async function mintTokens(args) {
|
|
|
158
173
|
if (isErr(saved))
|
|
159
174
|
return err(saved.error);
|
|
160
175
|
}
|
|
176
|
+
let idToken;
|
|
177
|
+
if (payload.authTime !== undefined && shouldIssueIdToken(payload.scopes)) {
|
|
178
|
+
const idClaims = await buildIdTokenClaims({
|
|
179
|
+
issuerUrl: deps.issuerUrl,
|
|
180
|
+
audience: payload.clientId,
|
|
181
|
+
subjectId,
|
|
182
|
+
claim,
|
|
183
|
+
scopes: payload.scopes,
|
|
184
|
+
authTime: payload.authTime,
|
|
185
|
+
...payload.appNonce !== undefined ? { appNonce: payload.appNonce } : {},
|
|
186
|
+
now,
|
|
187
|
+
methodKind: payload.methodKind,
|
|
188
|
+
accessToken,
|
|
189
|
+
...payload.claimsRequest !== undefined ? { claimsRequest: payload.claimsRequest } : {},
|
|
190
|
+
...deps.customScopeClaims !== undefined ? { customScopeClaims: deps.customScopeClaims } : {}
|
|
191
|
+
});
|
|
192
|
+
try {
|
|
193
|
+
idToken = await signIdToken(idClaims, signingKey.privateKeyRef, signingKey.alg, signingKey.kid);
|
|
194
|
+
} catch (e) {
|
|
195
|
+
return err(authError.serverError("id_token sign failed", e));
|
|
196
|
+
}
|
|
197
|
+
}
|
|
161
198
|
await safeAudit(deps, {
|
|
162
199
|
kind: "token_issued",
|
|
163
200
|
tenantId: payload.tenantId,
|
|
@@ -166,23 +203,27 @@ async function mintTokens(args) {
|
|
|
166
203
|
methodKind: payload.methodKind,
|
|
167
204
|
subjectId,
|
|
168
205
|
refreshTokenIdHash: refresh ? await hashTokenForAudit(refresh) : "",
|
|
206
|
+
...idToken !== undefined ? { idTokenIssued: true } : {},
|
|
207
|
+
...payload.dpopJkt !== undefined ? { dpopBound: true } : {},
|
|
169
208
|
timestamp: now
|
|
170
209
|
});
|
|
171
210
|
return ok({
|
|
172
211
|
access_token: accessToken,
|
|
173
|
-
token_type: "Bearer",
|
|
212
|
+
token_type: payload.dpopJkt !== undefined ? "DPoP" : "Bearer",
|
|
174
213
|
expires_in: Math.floor(accessTtl / 1000),
|
|
175
214
|
...refresh !== undefined ? { refresh_token: refresh } : {},
|
|
215
|
+
...idToken !== undefined ? { id_token: idToken } : {},
|
|
176
216
|
scope: payload.scopes.join(" ")
|
|
177
217
|
});
|
|
178
218
|
}
|
|
179
219
|
async function hashClientSecret(plain) {
|
|
180
220
|
return base64url.encode(await sha256(utf8.encode(plain)));
|
|
181
221
|
}
|
|
182
|
-
async function deriveSubjectId(claim) {
|
|
222
|
+
async function deriveSubjectId(claim, sectorIdentifier) {
|
|
183
223
|
const c = claim;
|
|
184
224
|
const ordered = canonicalize(c.properties);
|
|
185
|
-
|
|
225
|
+
const seed = sectorIdentifier !== undefined ? `${sectorIdentifier}\x00${c.type}\x00${ordered}` : `${c.type}\x00${ordered}`;
|
|
226
|
+
return base64url.encode(await sha256(seed)).slice(0, 22);
|
|
186
227
|
}
|
|
187
228
|
function canonicalize(value) {
|
|
188
229
|
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
@@ -196,10 +237,10 @@ async function hashTokenForAudit(token) {
|
|
|
196
237
|
return base64url.encode(await sha256(utf8.encode(token))).slice(0, 16);
|
|
197
238
|
}
|
|
198
239
|
export {
|
|
199
|
-
|
|
200
|
-
mintTokens,
|
|
201
|
-
hashClientSecret,
|
|
202
|
-
exchangeCode,
|
|
240
|
+
DEFAULT_ACCESS_TTL_MS,
|
|
203
241
|
DEFAULT_REFRESH_TTL_MS,
|
|
204
|
-
|
|
242
|
+
exchangeCode,
|
|
243
|
+
hashClientSecret,
|
|
244
|
+
mintTokens,
|
|
245
|
+
saveEncryptedCode
|
|
205
246
|
};
|
|
@@ -1,25 +1,60 @@
|
|
|
1
1
|
// src/domain/userinfo.ts
|
|
2
2
|
import { authError } from "../types/error";
|
|
3
3
|
import { err, isErr, ok } from "../types/result";
|
|
4
|
+
import { computeAth, verifyDpopProof } from "./dpop";
|
|
5
|
+
import { pickScopedClaims } from "./id-token";
|
|
4
6
|
import { verifyAccessToken } from "./jwt";
|
|
5
|
-
async function userinfo(
|
|
7
|
+
async function userinfo(input, deps) {
|
|
6
8
|
const keysRes = await deps.keyStore.signingKeys();
|
|
7
9
|
if (isErr(keysRes))
|
|
8
10
|
return err(keysRes.error);
|
|
9
11
|
let claims;
|
|
10
12
|
try {
|
|
11
|
-
claims = await verifyAccessToken(
|
|
13
|
+
claims = await verifyAccessToken(input.accessToken, keysRes.value, {
|
|
12
14
|
...deps.issuerUrl ? { issuer: deps.issuerUrl } : {}
|
|
13
15
|
});
|
|
14
16
|
} catch {
|
|
15
17
|
return err(authError.invalidGrant("access token invalid or expired"));
|
|
16
18
|
}
|
|
19
|
+
const boundJkt = claims.cnf?.jkt;
|
|
20
|
+
if (boundJkt !== undefined) {
|
|
21
|
+
if (input.scheme !== "DPoP") {
|
|
22
|
+
return err(authError.invalidDpopProof('access token is DPoP-bound; Authorization scheme must be "DPoP"'));
|
|
23
|
+
}
|
|
24
|
+
if (!input.dpopProof) {
|
|
25
|
+
return err(authError.invalidDpopProof("access token is DPoP-bound; request is missing a DPoP proof"));
|
|
26
|
+
}
|
|
27
|
+
if (!input.htu || !input.htm || input.nowSec === undefined) {
|
|
28
|
+
return err(authError.invalidDpopProof("userinfo dpop verification requires htu, htm, and nowSec"));
|
|
29
|
+
}
|
|
30
|
+
if (!deps.tokenStore) {
|
|
31
|
+
return err(authError.invalidDpopProof("userinfo dpop verification requires a token-store (jti replay protection)"));
|
|
32
|
+
}
|
|
33
|
+
const expectedAth = await computeAth(input.accessToken);
|
|
34
|
+
const dpopRes = await verifyDpopProof({
|
|
35
|
+
proofJwt: input.dpopProof,
|
|
36
|
+
htu: input.htu,
|
|
37
|
+
htm: input.htm,
|
|
38
|
+
nowSec: input.nowSec,
|
|
39
|
+
expectedAth
|
|
40
|
+
}, { tokenStore: deps.tokenStore });
|
|
41
|
+
if (isErr(dpopRes))
|
|
42
|
+
return err(dpopRes.error);
|
|
43
|
+
if (dpopRes.value.jkt !== boundJkt) {
|
|
44
|
+
return err(authError.invalidDpopProof("dpop proof key does not match access token cnf.jkt"));
|
|
45
|
+
}
|
|
46
|
+
} else if (input.scheme === "DPoP") {
|
|
47
|
+
return err(authError.invalidGrant("access token is not DPoP-bound; use Authorization: Bearer"));
|
|
48
|
+
}
|
|
17
49
|
const claim = claims.claim;
|
|
50
|
+
const scopes = claims.scope ? claims.scope.split(" ").filter(Boolean) : [];
|
|
51
|
+
const scopedClaims = pickScopedClaims(claim, scopes, claims.uic ?? [], deps.customScopeClaims ?? {});
|
|
18
52
|
return ok({
|
|
19
53
|
sub: claims.sub,
|
|
20
54
|
subject_type: claim.type,
|
|
21
55
|
properties: claim.properties,
|
|
22
|
-
scope: claims.scope
|
|
56
|
+
scope: claims.scope,
|
|
57
|
+
...scopedClaims
|
|
23
58
|
});
|
|
24
59
|
}
|
|
25
60
|
export {
|
package/dist/esm/error.js
CHANGED
|
@@ -61,13 +61,13 @@ class InvalidAuthorizationCodeError extends Error {
|
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
63
|
export {
|
|
64
|
-
|
|
65
|
-
UnauthorizedClientError,
|
|
66
|
-
OauthError,
|
|
67
|
-
MissingProviderError,
|
|
68
|
-
MissingParameterError,
|
|
69
|
-
InvalidSubjectError,
|
|
70
|
-
InvalidRefreshTokenError,
|
|
64
|
+
InvalidAccessTokenError,
|
|
71
65
|
InvalidAuthorizationCodeError,
|
|
72
|
-
|
|
66
|
+
InvalidRefreshTokenError,
|
|
67
|
+
InvalidSubjectError,
|
|
68
|
+
MissingParameterError,
|
|
69
|
+
MissingProviderError,
|
|
70
|
+
OauthError,
|
|
71
|
+
UnauthorizedClientError,
|
|
72
|
+
UnknownStateError
|
|
73
73
|
};
|
package/dist/esm/http/cookies.js
CHANGED
|
@@ -67,6 +67,22 @@ var STRIPPED_HEADERS = [
|
|
|
67
67
|
"permissions-policy",
|
|
68
68
|
"cache-control"
|
|
69
69
|
];
|
|
70
|
+
function cacheControlHeader(cache) {
|
|
71
|
+
if (!cache)
|
|
72
|
+
return "no-store";
|
|
73
|
+
if ((cache.maxAge ?? -1) === 0)
|
|
74
|
+
return "no-store";
|
|
75
|
+
const parts = [];
|
|
76
|
+
if (cache.isPrivate)
|
|
77
|
+
parts.push("private");
|
|
78
|
+
if (cache.maxAge !== undefined)
|
|
79
|
+
parts.push(`max-age=${cache.maxAge}`);
|
|
80
|
+
if (cache.sMaxAge !== undefined)
|
|
81
|
+
parts.push(`s-maxage=${cache.sMaxAge}`);
|
|
82
|
+
if (cache.immutable)
|
|
83
|
+
parts.push("immutable");
|
|
84
|
+
return parts.length ? parts.join(", ") : "no-store";
|
|
85
|
+
}
|
|
70
86
|
function applyResponsePolicy(response, opts = {}) {
|
|
71
87
|
const headers = new Headers(response.headers);
|
|
72
88
|
const stripped = [];
|
|
@@ -92,7 +108,8 @@ function applyResponsePolicy(response, opts = {}) {
|
|
|
92
108
|
});
|
|
93
109
|
}
|
|
94
110
|
export {
|
|
95
|
-
|
|
111
|
+
applyResponsePolicy,
|
|
112
|
+
cacheControlHeader,
|
|
96
113
|
parseCookieHeader,
|
|
97
|
-
|
|
114
|
+
serializeSetCookie
|
|
98
115
|
};
|
package/dist/esm/http/errors.js
CHANGED
|
@@ -63,9 +63,9 @@ function isNonRecoverable(error) {
|
|
|
63
63
|
return false;
|
|
64
64
|
}
|
|
65
65
|
export {
|
|
66
|
-
|
|
67
|
-
publicErrorCode,
|
|
68
|
-
isNonRecoverable,
|
|
66
|
+
authorizeDirectErrorResponse,
|
|
69
67
|
authorizeRedirectErrorResponse,
|
|
70
|
-
|
|
68
|
+
isNonRecoverable,
|
|
69
|
+
publicErrorCode,
|
|
70
|
+
tokenEndpointErrorResponse
|
|
71
71
|
};
|