@_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
|
@@ -1,12 +1,21 @@
|
|
|
1
|
+
// src/adapters/d1/index.ts
|
|
2
|
+
import { D1AuditLog } from "./audit-log";
|
|
3
|
+
import { D1ConfigStore } from "./config-store";
|
|
4
|
+
import { D1KeyStore } from "./key-store";
|
|
5
|
+
import { D1MethodStore } from "./method-store";
|
|
6
|
+
import { D1SessionStore } from "./session-store";
|
|
7
|
+
import { D1TokenStore } from "./token-store";
|
|
8
|
+
import { INITIAL_SCHEMA_SQL, migrate } from "./migrations";
|
|
9
|
+
import { isSessionsCapable, primarySession } from "./session";
|
|
1
10
|
export {
|
|
2
|
-
|
|
3
|
-
migrate,
|
|
4
|
-
isSessionsCapable,
|
|
5
|
-
INITIAL_SCHEMA_SQL,
|
|
6
|
-
D1TokenStore,
|
|
7
|
-
D1SessionStore,
|
|
8
|
-
D1MethodStore,
|
|
9
|
-
D1KeyStore,
|
|
11
|
+
D1AuditLog,
|
|
10
12
|
D1ConfigStore,
|
|
11
|
-
|
|
13
|
+
D1KeyStore,
|
|
14
|
+
D1MethodStore,
|
|
15
|
+
D1SessionStore,
|
|
16
|
+
D1TokenStore,
|
|
17
|
+
INITIAL_SCHEMA_SQL,
|
|
18
|
+
isSessionsCapable,
|
|
19
|
+
migrate,
|
|
20
|
+
primarySession
|
|
12
21
|
};
|
|
@@ -57,6 +57,11 @@ var INITIAL_SCHEMA_SQL = [
|
|
|
57
57
|
payload TEXT NOT NULL,
|
|
58
58
|
expires_at INTEGER NOT NULL
|
|
59
59
|
)`,
|
|
60
|
+
`CREATE TABLE IF NOT EXISTS openauth_scratch (
|
|
61
|
+
scratch_key TEXT PRIMARY KEY,
|
|
62
|
+
value TEXT NOT NULL,
|
|
63
|
+
expires_at INTEGER NOT NULL
|
|
64
|
+
)`,
|
|
60
65
|
`CREATE TABLE IF NOT EXISTS openauth_audit_events (
|
|
61
66
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
62
67
|
ts INTEGER NOT NULL,
|
|
@@ -72,6 +77,6 @@ async function migrate(db) {
|
|
|
72
77
|
}
|
|
73
78
|
}
|
|
74
79
|
export {
|
|
75
|
-
|
|
76
|
-
|
|
80
|
+
INITIAL_SCHEMA_SQL,
|
|
81
|
+
migrate
|
|
77
82
|
};
|
|
@@ -128,6 +128,45 @@ class D1SessionStore {
|
|
|
128
128
|
}
|
|
129
129
|
return ok(undefined);
|
|
130
130
|
}
|
|
131
|
+
async saveScratch(key, value, ttlMs) {
|
|
132
|
+
if (ttlMs <= 0) {
|
|
133
|
+
return err(authError.internalError(`saveScratch: ttlMs must be positive, got ${ttlMs}`));
|
|
134
|
+
}
|
|
135
|
+
const expiresAt = this.#clock() + ttlMs;
|
|
136
|
+
try {
|
|
137
|
+
await primarySession(this.#db).prepare(`INSERT INTO openauth_scratch (scratch_key, value, expires_at) VALUES (?1, ?2, ?3)
|
|
138
|
+
ON CONFLICT(scratch_key) DO UPDATE SET value = excluded.value, expires_at = excluded.expires_at`).bind(key, value, expiresAt).run();
|
|
139
|
+
} catch (e) {
|
|
140
|
+
return err(authError.internalError("saveScratch: upsert failed", e));
|
|
141
|
+
}
|
|
142
|
+
return ok(undefined);
|
|
143
|
+
}
|
|
144
|
+
async readScratch(key) {
|
|
145
|
+
let row;
|
|
146
|
+
try {
|
|
147
|
+
row = await primarySession(this.#db).prepare(`SELECT value, expires_at FROM openauth_scratch WHERE scratch_key = ?1`).bind(key).first();
|
|
148
|
+
} catch (e) {
|
|
149
|
+
return err(authError.internalError("readScratch: query failed", e));
|
|
150
|
+
}
|
|
151
|
+
if (!row) {
|
|
152
|
+
return err(authError.unknownState(`scratch "${key}" unknown`));
|
|
153
|
+
}
|
|
154
|
+
if (this.#clock() >= Number(row.expires_at)) {
|
|
155
|
+
try {
|
|
156
|
+
await primarySession(this.#db).prepare(`DELETE FROM openauth_scratch WHERE scratch_key = ?1`).bind(key).run();
|
|
157
|
+
} catch {}
|
|
158
|
+
return err(authError.unknownState(`scratch "${key}" expired`));
|
|
159
|
+
}
|
|
160
|
+
return ok(row.value);
|
|
161
|
+
}
|
|
162
|
+
async deleteScratch(key) {
|
|
163
|
+
try {
|
|
164
|
+
await primarySession(this.#db).prepare(`DELETE FROM openauth_scratch WHERE scratch_key = ?1`).bind(key).run();
|
|
165
|
+
} catch (e) {
|
|
166
|
+
return err(authError.internalError("deleteScratch: delete failed", e));
|
|
167
|
+
}
|
|
168
|
+
return ok(undefined);
|
|
169
|
+
}
|
|
131
170
|
}
|
|
132
171
|
export {
|
|
133
172
|
D1SessionStore
|
|
@@ -131,9 +131,51 @@ class DurableObjectSessionStore {
|
|
|
131
131
|
}
|
|
132
132
|
return ok(undefined);
|
|
133
133
|
}
|
|
134
|
+
async saveScratch(key, value, ttlMs) {
|
|
135
|
+
if (ttlMs <= 0) {
|
|
136
|
+
return err(authError.internalError(`saveScratch: ttlMs must be positive, got ${ttlMs}`));
|
|
137
|
+
}
|
|
138
|
+
const stored = {
|
|
139
|
+
value,
|
|
140
|
+
expiresAt: this.#clock() + ttlMs
|
|
141
|
+
};
|
|
142
|
+
try {
|
|
143
|
+
await this.#storage.put(scratchKey(key), stored);
|
|
144
|
+
} catch (e) {
|
|
145
|
+
return err(authError.internalError("saveScratch: put failed", e));
|
|
146
|
+
}
|
|
147
|
+
return ok(undefined);
|
|
148
|
+
}
|
|
149
|
+
async readScratch(key) {
|
|
150
|
+
let stored;
|
|
151
|
+
try {
|
|
152
|
+
stored = await this.#storage.get(scratchKey(key));
|
|
153
|
+
} catch (e) {
|
|
154
|
+
return err(authError.internalError("readScratch: get failed", e));
|
|
155
|
+
}
|
|
156
|
+
if (!stored) {
|
|
157
|
+
return err(authError.unknownState(`scratch "${key}" unknown`));
|
|
158
|
+
}
|
|
159
|
+
if (this.#clock() >= stored.expiresAt) {
|
|
160
|
+
try {
|
|
161
|
+
await this.#storage.delete(scratchKey(key));
|
|
162
|
+
} catch {}
|
|
163
|
+
return err(authError.unknownState(`scratch "${key}" expired`));
|
|
164
|
+
}
|
|
165
|
+
return ok(stored.value);
|
|
166
|
+
}
|
|
167
|
+
async deleteScratch(key) {
|
|
168
|
+
try {
|
|
169
|
+
await this.#storage.delete(scratchKey(key));
|
|
170
|
+
} catch (e) {
|
|
171
|
+
return err(authError.internalError("deleteScratch: delete failed", e));
|
|
172
|
+
}
|
|
173
|
+
return ok(undefined);
|
|
174
|
+
}
|
|
134
175
|
}
|
|
135
176
|
var flowKey = (flowId) => `flow:${flowId}`;
|
|
136
177
|
var sessionKey = (sessionId) => `session:${sessionId}`;
|
|
178
|
+
var scratchKey = (key) => `scratch:${key}`;
|
|
137
179
|
export {
|
|
138
180
|
DurableObjectSessionStore
|
|
139
181
|
};
|
|
@@ -1,10 +1,27 @@
|
|
|
1
|
+
// src/adapters/dynamo/index.ts
|
|
2
|
+
import { DynamoAuditLog } from "./audit-log";
|
|
3
|
+
import {
|
|
4
|
+
DynamoConfigStore
|
|
5
|
+
} from "./config-store";
|
|
6
|
+
import { DynamoKeyStore } from "./key-store";
|
|
7
|
+
import {
|
|
8
|
+
DynamoMethodStore
|
|
9
|
+
} from "./method-store";
|
|
10
|
+
import {
|
|
11
|
+
DynamoSessionStore
|
|
12
|
+
} from "./session-store";
|
|
13
|
+
import { DynamoTokenStore } from "./token-store";
|
|
14
|
+
import {
|
|
15
|
+
DynamoPasskeyCredentialStore
|
|
16
|
+
} from "./passkey-credential-store";
|
|
17
|
+
import { fromDynamoDBClient } from "./sdk";
|
|
1
18
|
export {
|
|
2
|
-
|
|
3
|
-
DynamoTokenStore,
|
|
4
|
-
DynamoSessionStore,
|
|
5
|
-
DynamoPasskeyCredentialStore,
|
|
6
|
-
DynamoMethodStore,
|
|
7
|
-
DynamoKeyStore,
|
|
19
|
+
DynamoAuditLog,
|
|
8
20
|
DynamoConfigStore,
|
|
9
|
-
|
|
21
|
+
DynamoKeyStore,
|
|
22
|
+
DynamoMethodStore,
|
|
23
|
+
DynamoPasskeyCredentialStore,
|
|
24
|
+
DynamoSessionStore,
|
|
25
|
+
DynamoTokenStore,
|
|
26
|
+
fromDynamoDBClient
|
|
10
27
|
};
|
|
@@ -152,6 +152,55 @@ class DynamoSessionStore {
|
|
|
152
152
|
}
|
|
153
153
|
return ok(undefined);
|
|
154
154
|
}
|
|
155
|
+
async saveScratch(key, value, ttlMs) {
|
|
156
|
+
if (ttlMs <= 0) {
|
|
157
|
+
return err(authError.internalError(`saveScratch: ttlMs must be positive, got ${ttlMs}`));
|
|
158
|
+
}
|
|
159
|
+
const expiresAtMs = this.#clock() + ttlMs;
|
|
160
|
+
try {
|
|
161
|
+
await this.#exec.put({
|
|
162
|
+
item: {
|
|
163
|
+
pk: "scratch",
|
|
164
|
+
sk: key,
|
|
165
|
+
value,
|
|
166
|
+
expires_at: expiresAtMs,
|
|
167
|
+
ttl: Math.floor(expiresAtMs / 1000)
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
} catch (e) {
|
|
171
|
+
return err(authError.internalError("saveScratch: put failed", e));
|
|
172
|
+
}
|
|
173
|
+
return ok(undefined);
|
|
174
|
+
}
|
|
175
|
+
async readScratch(key) {
|
|
176
|
+
let row;
|
|
177
|
+
try {
|
|
178
|
+
row = await this.#exec.get({
|
|
179
|
+
key: { pk: "scratch", sk: key },
|
|
180
|
+
consistentRead: true
|
|
181
|
+
});
|
|
182
|
+
} catch (e) {
|
|
183
|
+
return err(authError.internalError("readScratch: get failed", e));
|
|
184
|
+
}
|
|
185
|
+
if (!row) {
|
|
186
|
+
return err(authError.unknownState(`scratch "${key}" unknown`));
|
|
187
|
+
}
|
|
188
|
+
if (this.#clock() >= Number(row.expires_at)) {
|
|
189
|
+
try {
|
|
190
|
+
await this.#exec.delete({ key: { pk: "scratch", sk: key } });
|
|
191
|
+
} catch {}
|
|
192
|
+
return err(authError.unknownState(`scratch "${key}" expired`));
|
|
193
|
+
}
|
|
194
|
+
return ok(String(row.value));
|
|
195
|
+
}
|
|
196
|
+
async deleteScratch(key) {
|
|
197
|
+
try {
|
|
198
|
+
await this.#exec.delete({ key: { pk: "scratch", sk: key } });
|
|
199
|
+
} catch (e) {
|
|
200
|
+
return err(authError.internalError("deleteScratch: delete failed", e));
|
|
201
|
+
}
|
|
202
|
+
return ok(undefined);
|
|
203
|
+
}
|
|
155
204
|
}
|
|
156
205
|
function parseFlowPayload(raw) {
|
|
157
206
|
if (typeof raw === "string")
|
|
@@ -1,5 +1,9 @@
|
|
|
1
|
+
// src/adapters/kms/index.ts
|
|
2
|
+
import { inMemoryKmsBackingStore } from "./in-memory-backing";
|
|
3
|
+
import { KmsKeyStore } from "./key-store";
|
|
4
|
+
import { fromKmsClient } from "./sdk";
|
|
1
5
|
export {
|
|
2
|
-
|
|
6
|
+
KmsKeyStore,
|
|
3
7
|
fromKmsClient,
|
|
4
|
-
|
|
8
|
+
inMemoryKmsBackingStore
|
|
5
9
|
};
|
|
@@ -1,5 +1,9 @@
|
|
|
1
|
+
// src/adapters/kv/index.ts
|
|
2
|
+
import { KvAuditLog } from "./audit-log";
|
|
3
|
+
import { KvConfigStore } from "./config-store";
|
|
4
|
+
import { KvMethodStore } from "./method-store";
|
|
1
5
|
export {
|
|
2
|
-
|
|
6
|
+
KvAuditLog,
|
|
3
7
|
KvConfigStore,
|
|
4
|
-
|
|
8
|
+
KvMethodStore
|
|
5
9
|
};
|
|
@@ -1,10 +1,27 @@
|
|
|
1
|
+
// src/adapters/memory/index.ts
|
|
2
|
+
import { MemoryAuditLog } from "./audit-log";
|
|
3
|
+
import {
|
|
4
|
+
MemoryConfigStore
|
|
5
|
+
} from "./config-store";
|
|
6
|
+
import { MemoryKeyStore } from "./key-store";
|
|
7
|
+
import {
|
|
8
|
+
MemoryMethodStore
|
|
9
|
+
} from "./method-store";
|
|
10
|
+
import {
|
|
11
|
+
MemorySessionStore
|
|
12
|
+
} from "./session-store";
|
|
13
|
+
import { MemoryTokenStore } from "./token-store";
|
|
14
|
+
import {
|
|
15
|
+
MemoryPasskeyCredentialStore
|
|
16
|
+
} from "./passkey-credential-store";
|
|
17
|
+
import { realClock } from "./clock";
|
|
1
18
|
export {
|
|
2
|
-
|
|
3
|
-
MemoryTokenStore,
|
|
4
|
-
MemorySessionStore,
|
|
5
|
-
MemoryPasskeyCredentialStore,
|
|
6
|
-
MemoryMethodStore,
|
|
7
|
-
MemoryKeyStore,
|
|
19
|
+
MemoryAuditLog,
|
|
8
20
|
MemoryConfigStore,
|
|
9
|
-
|
|
21
|
+
MemoryKeyStore,
|
|
22
|
+
MemoryMethodStore,
|
|
23
|
+
MemoryPasskeyCredentialStore,
|
|
24
|
+
MemorySessionStore,
|
|
25
|
+
MemoryTokenStore,
|
|
26
|
+
realClock
|
|
10
27
|
};
|
|
@@ -7,6 +7,8 @@ class MemorySessionStore {
|
|
|
7
7
|
#clock;
|
|
8
8
|
#flows = new Map;
|
|
9
9
|
#sessions = new Map;
|
|
10
|
+
#par = new Map;
|
|
11
|
+
#scratch = new Map;
|
|
10
12
|
constructor(opts = {}) {
|
|
11
13
|
this.#clock = opts.clock ?? realClock;
|
|
12
14
|
}
|
|
@@ -76,6 +78,49 @@ class MemorySessionStore {
|
|
|
76
78
|
this.#sessions.delete(sessionId);
|
|
77
79
|
return ok(undefined);
|
|
78
80
|
}
|
|
81
|
+
async savePar(requestUri, payload, ttl) {
|
|
82
|
+
if (ttl <= 0) {
|
|
83
|
+
return err(authError.internalError(`savePar: ttl must be positive, got ${ttl}`));
|
|
84
|
+
}
|
|
85
|
+
this.#par.set(requestUri, {
|
|
86
|
+
record: payload,
|
|
87
|
+
expiresAt: this.#clock() + ttl
|
|
88
|
+
});
|
|
89
|
+
return ok(undefined);
|
|
90
|
+
}
|
|
91
|
+
async consumePar(requestUri) {
|
|
92
|
+
const stored = this.#par.get(requestUri);
|
|
93
|
+
if (!stored) {
|
|
94
|
+
return err(authError.unknownState(`par "${requestUri}" unknown or already consumed`));
|
|
95
|
+
}
|
|
96
|
+
this.#par.delete(requestUri);
|
|
97
|
+
if (this.#clock() >= stored.expiresAt) {
|
|
98
|
+
return err(authError.unknownState(`par "${requestUri}" expired`));
|
|
99
|
+
}
|
|
100
|
+
return ok(stored.record);
|
|
101
|
+
}
|
|
102
|
+
async saveScratch(key, value, ttlMs) {
|
|
103
|
+
if (ttlMs <= 0) {
|
|
104
|
+
return err(authError.internalError(`saveScratch: ttlMs must be positive, got ${ttlMs}`));
|
|
105
|
+
}
|
|
106
|
+
this.#scratch.set(key, { value, expiresAt: this.#clock() + ttlMs });
|
|
107
|
+
return ok(undefined);
|
|
108
|
+
}
|
|
109
|
+
async readScratch(key) {
|
|
110
|
+
const stored = this.#scratch.get(key);
|
|
111
|
+
if (!stored) {
|
|
112
|
+
return err(authError.unknownState(`scratch "${key}" unknown`));
|
|
113
|
+
}
|
|
114
|
+
if (this.#clock() >= stored.expiresAt) {
|
|
115
|
+
this.#scratch.delete(key);
|
|
116
|
+
return err(authError.unknownState(`scratch "${key}" expired`));
|
|
117
|
+
}
|
|
118
|
+
return ok(stored.value);
|
|
119
|
+
}
|
|
120
|
+
async deleteScratch(key) {
|
|
121
|
+
this.#scratch.delete(key);
|
|
122
|
+
return ok(undefined);
|
|
123
|
+
}
|
|
79
124
|
}
|
|
80
125
|
export {
|
|
81
126
|
MemorySessionStore
|
|
@@ -8,6 +8,7 @@ class MemoryTokenStore {
|
|
|
8
8
|
#clock;
|
|
9
9
|
#codes = new Map;
|
|
10
10
|
#refresh = new Map;
|
|
11
|
+
#dpopJtis = new Map;
|
|
11
12
|
constructor(opts = {}) {
|
|
12
13
|
this.#clock = opts.clock ?? realClock;
|
|
13
14
|
}
|
|
@@ -85,6 +86,18 @@ class MemoryTokenStore {
|
|
|
85
86
|
}
|
|
86
87
|
return ok(undefined);
|
|
87
88
|
}
|
|
89
|
+
async recordDpopJti(jti, ttlMs) {
|
|
90
|
+
const now = this.#clock();
|
|
91
|
+
for (const [k, exp] of this.#dpopJtis) {
|
|
92
|
+
if (exp <= now)
|
|
93
|
+
this.#dpopJtis.delete(k);
|
|
94
|
+
}
|
|
95
|
+
if (this.#dpopJtis.has(jti)) {
|
|
96
|
+
return err(authError.invalidGrant(`dpop jti "${jti}" replayed`));
|
|
97
|
+
}
|
|
98
|
+
this.#dpopJtis.set(jti, now + ttlMs);
|
|
99
|
+
return ok(undefined);
|
|
100
|
+
}
|
|
88
101
|
}
|
|
89
102
|
export {
|
|
90
103
|
MemoryTokenStore
|
|
@@ -1,13 +1,36 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
fromPostgresJs,
|
|
1
|
+
// src/adapters/postgres/index.ts
|
|
2
|
+
import {
|
|
4
3
|
fromPGlite,
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
PostgresConfigStore
|
|
4
|
+
fromPostgresJs
|
|
5
|
+
} from "./executor";
|
|
6
|
+
import { INITIAL_SCHEMA_SQL, migrate } from "./migrations";
|
|
7
|
+
import { PostgresAuditLog } from "./audit-log";
|
|
8
|
+
import {
|
|
9
|
+
PostgresConfigStore
|
|
10
|
+
} from "./config-store";
|
|
11
|
+
import { PostgresKeyStore } from "./key-store";
|
|
12
|
+
import {
|
|
13
|
+
PostgresMethodStore
|
|
14
|
+
} from "./method-store";
|
|
15
|
+
import {
|
|
16
|
+
PostgresSessionStore
|
|
17
|
+
} from "./session-store";
|
|
18
|
+
import {
|
|
19
|
+
PostgresTokenStore
|
|
20
|
+
} from "./token-store";
|
|
21
|
+
import {
|
|
22
|
+
PostgresPasskeyCredentialStore
|
|
23
|
+
} from "./passkey-credential-store";
|
|
24
|
+
export {
|
|
25
|
+
INITIAL_SCHEMA_SQL,
|
|
11
26
|
PostgresAuditLog,
|
|
12
|
-
|
|
27
|
+
PostgresConfigStore,
|
|
28
|
+
PostgresKeyStore,
|
|
29
|
+
PostgresMethodStore,
|
|
30
|
+
PostgresPasskeyCredentialStore,
|
|
31
|
+
PostgresSessionStore,
|
|
32
|
+
PostgresTokenStore,
|
|
33
|
+
fromPGlite,
|
|
34
|
+
fromPostgresJs,
|
|
35
|
+
migrate
|
|
13
36
|
};
|
|
@@ -75,6 +75,12 @@ CREATE TABLE IF NOT EXISTS openauth_sessions (
|
|
|
75
75
|
expires_at bigint NOT NULL
|
|
76
76
|
);
|
|
77
77
|
|
|
78
|
+
CREATE TABLE IF NOT EXISTS openauth_scratch (
|
|
79
|
+
scratch_key text PRIMARY KEY,
|
|
80
|
+
value text NOT NULL,
|
|
81
|
+
expires_at bigint NOT NULL
|
|
82
|
+
);
|
|
83
|
+
|
|
78
84
|
CREATE TABLE IF NOT EXISTS openauth_audit_events (
|
|
79
85
|
id bigserial PRIMARY KEY,
|
|
80
86
|
ts bigint NOT NULL,
|
|
@@ -106,6 +112,6 @@ async function migrate(exec) {
|
|
|
106
112
|
}
|
|
107
113
|
}
|
|
108
114
|
export {
|
|
109
|
-
|
|
110
|
-
|
|
115
|
+
INITIAL_SCHEMA_SQL,
|
|
116
|
+
migrate
|
|
111
117
|
};
|
|
@@ -119,6 +119,48 @@ class PostgresSessionStore {
|
|
|
119
119
|
}
|
|
120
120
|
return ok(undefined);
|
|
121
121
|
}
|
|
122
|
+
async saveScratch(key, value, ttlMs) {
|
|
123
|
+
if (ttlMs <= 0) {
|
|
124
|
+
return err(authError.internalError(`saveScratch: ttlMs must be positive, got ${ttlMs}`));
|
|
125
|
+
}
|
|
126
|
+
const expiresAt = this.#clock() + ttlMs;
|
|
127
|
+
try {
|
|
128
|
+
await this.#exec.query(`INSERT INTO openauth_scratch (scratch_key, value, expires_at)
|
|
129
|
+
VALUES ($1, $2, $3)
|
|
130
|
+
ON CONFLICT (scratch_key)
|
|
131
|
+
DO UPDATE SET value = EXCLUDED.value, expires_at = EXCLUDED.expires_at`, [key, value, expiresAt]);
|
|
132
|
+
} catch (e) {
|
|
133
|
+
return err(authError.internalError("saveScratch: upsert failed", e));
|
|
134
|
+
}
|
|
135
|
+
return ok(undefined);
|
|
136
|
+
}
|
|
137
|
+
async readScratch(key) {
|
|
138
|
+
let row;
|
|
139
|
+
try {
|
|
140
|
+
const result = await this.#exec.query(`SELECT value, expires_at FROM openauth_scratch WHERE scratch_key = $1`, [key]);
|
|
141
|
+
row = result.rows[0];
|
|
142
|
+
} catch (e) {
|
|
143
|
+
return err(authError.internalError("readScratch: query failed", e));
|
|
144
|
+
}
|
|
145
|
+
if (!row) {
|
|
146
|
+
return err(authError.unknownState(`scratch "${key}" unknown`));
|
|
147
|
+
}
|
|
148
|
+
if (this.#clock() >= Number(row.expires_at)) {
|
|
149
|
+
try {
|
|
150
|
+
await this.#exec.query(`DELETE FROM openauth_scratch WHERE scratch_key = $1`, [key]);
|
|
151
|
+
} catch {}
|
|
152
|
+
return err(authError.unknownState(`scratch "${key}" expired`));
|
|
153
|
+
}
|
|
154
|
+
return ok(row.value);
|
|
155
|
+
}
|
|
156
|
+
async deleteScratch(key) {
|
|
157
|
+
try {
|
|
158
|
+
await this.#exec.query(`DELETE FROM openauth_scratch WHERE scratch_key = $1`, [key]);
|
|
159
|
+
} catch (e) {
|
|
160
|
+
return err(authError.internalError("deleteScratch: delete failed", e));
|
|
161
|
+
}
|
|
162
|
+
return ok(undefined);
|
|
163
|
+
}
|
|
122
164
|
}
|
|
123
165
|
function parseFlowRecord(raw) {
|
|
124
166
|
if (typeof raw === "string")
|
package/dist/esm/client.js
CHANGED
|
@@ -33,44 +33,49 @@ function createClient(input) {
|
|
|
33
33
|
if (cached)
|
|
34
34
|
return cached;
|
|
35
35
|
const keyset = await (f || fetch)(wk.jwks_uri).then((r) => r.json());
|
|
36
|
-
const
|
|
37
|
-
jwksCache.set(issuer,
|
|
38
|
-
return
|
|
36
|
+
const result = createLocalJWKSet(keyset);
|
|
37
|
+
jwksCache.set(issuer, result);
|
|
38
|
+
return result;
|
|
39
39
|
}
|
|
40
40
|
const result = {
|
|
41
41
|
async authorize(redirectURI, response, opts) {
|
|
42
|
-
const
|
|
42
|
+
const result = new URL(issuer + "/authorize");
|
|
43
43
|
const challenge = {
|
|
44
44
|
state: crypto.randomUUID()
|
|
45
45
|
};
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
46
|
+
result.searchParams.set("client_id", input.clientID);
|
|
47
|
+
result.searchParams.set("redirect_uri", redirectURI);
|
|
48
|
+
result.searchParams.set("response_type", response);
|
|
49
|
+
result.searchParams.set("state", challenge.state);
|
|
50
50
|
if (opts?.provider)
|
|
51
|
-
|
|
51
|
+
result.searchParams.set("provider", opts.provider);
|
|
52
|
+
if (opts?.scope !== undefined) {
|
|
53
|
+
const scope = Array.isArray(opts.scope) ? opts.scope.join(" ") : opts.scope;
|
|
54
|
+
if (scope)
|
|
55
|
+
result.searchParams.set("scope", scope);
|
|
56
|
+
}
|
|
52
57
|
if (opts?.pkce && response === "code") {
|
|
53
58
|
const pkce = await generatePKCE();
|
|
54
|
-
|
|
55
|
-
|
|
59
|
+
result.searchParams.set("code_challenge_method", "S256");
|
|
60
|
+
result.searchParams.set("code_challenge", pkce.challenge);
|
|
56
61
|
challenge.verifier = pkce.verifier;
|
|
57
62
|
}
|
|
58
63
|
return {
|
|
59
64
|
challenge,
|
|
60
|
-
url:
|
|
65
|
+
url: result.toString()
|
|
61
66
|
};
|
|
62
67
|
},
|
|
63
68
|
async pkce(redirectURI, opts) {
|
|
64
|
-
const
|
|
69
|
+
const result = new URL(issuer + "/authorize");
|
|
65
70
|
if (opts?.provider)
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
71
|
+
result.searchParams.set("provider", opts.provider);
|
|
72
|
+
result.searchParams.set("client_id", input.clientID);
|
|
73
|
+
result.searchParams.set("redirect_uri", redirectURI);
|
|
74
|
+
result.searchParams.set("response_type", "code");
|
|
70
75
|
const pkce = await generatePKCE();
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
return [pkce.verifier,
|
|
76
|
+
result.searchParams.set("code_challenge_method", "S256");
|
|
77
|
+
result.searchParams.set("code_challenge", pkce.challenge);
|
|
78
|
+
return [pkce.verifier, result.toString()];
|
|
74
79
|
},
|
|
75
80
|
async exchange(code, redirectURI, verifier) {
|
|
76
81
|
const tokens = await f(issuer + "/token", {
|
|
@@ -97,7 +102,8 @@ function createClient(input) {
|
|
|
97
102
|
tokens: {
|
|
98
103
|
access: json.access_token,
|
|
99
104
|
refresh: json.refresh_token,
|
|
100
|
-
expiresIn: json.expires_in
|
|
105
|
+
expiresIn: json.expires_in,
|
|
106
|
+
...typeof json.id_token === "string" ? { idToken: json.id_token } : {}
|
|
101
107
|
}
|
|
102
108
|
};
|
|
103
109
|
},
|
|
@@ -136,25 +142,26 @@ function createClient(input) {
|
|
|
136
142
|
tokens: {
|
|
137
143
|
access: json.access_token,
|
|
138
144
|
refresh: json.refresh_token,
|
|
139
|
-
expiresIn: json.expires_in
|
|
145
|
+
expiresIn: json.expires_in,
|
|
146
|
+
...typeof json.id_token === "string" ? { idToken: json.id_token } : {}
|
|
140
147
|
}
|
|
141
148
|
};
|
|
142
149
|
},
|
|
143
150
|
async verify(subjects, token, options) {
|
|
144
151
|
const jwks = await getJWKS();
|
|
145
152
|
try {
|
|
146
|
-
const
|
|
153
|
+
const result = await jwtVerify(token, jwks, {
|
|
147
154
|
issuer
|
|
148
155
|
});
|
|
149
|
-
const claim =
|
|
156
|
+
const claim = result.payload.claim;
|
|
150
157
|
let subjectType;
|
|
151
158
|
let subjectProperties;
|
|
152
159
|
if (claim && typeof claim.type === "string") {
|
|
153
160
|
subjectType = claim.type;
|
|
154
161
|
subjectProperties = claim.properties;
|
|
155
|
-
} else if (
|
|
156
|
-
subjectType =
|
|
157
|
-
subjectProperties =
|
|
162
|
+
} else if (result.payload.mode === "access" && typeof result.payload.type === "string") {
|
|
163
|
+
subjectType = result.payload.type;
|
|
164
|
+
subjectProperties = result.payload.properties;
|
|
158
165
|
}
|
|
159
166
|
if (subjectType === undefined) {
|
|
160
167
|
return { err: new InvalidSubjectError };
|
|
@@ -168,7 +175,7 @@ function createClient(input) {
|
|
|
168
175
|
return { err: new InvalidSubjectError };
|
|
169
176
|
}
|
|
170
177
|
return {
|
|
171
|
-
aud:
|
|
178
|
+
aud: result.payload.aud,
|
|
172
179
|
subject: {
|
|
173
180
|
type: subjectType,
|
|
174
181
|
properties: validated.value
|