@_mustachio/openauth 0.11.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 +23 -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 +27 -27
- package/dist/esm/domain/authorize.js +2 -2
- package/dist/esm/domain/callback.js +121 -7
- package/dist/esm/domain/client-auth.js +2 -2
- package/dist/esm/domain/crypto.js +14 -14
- package/dist/esm/domain/discovery.js +2 -2
- package/dist/esm/domain/dpop.js +4 -4
- package/dist/esm/domain/id-token.js +5 -5
- package/dist/esm/domain/jwt.js +4 -4
- package/dist/esm/domain/method-dispatch.js +27 -1
- package/dist/esm/domain/method-route.js +80 -1
- package/dist/esm/domain/par.js +2 -2
- package/dist/esm/domain/pkce.js +2 -2
- package/dist/esm/domain/revoke.js +2 -2
- package/dist/esm/domain/state-envelope.js +2 -2
- package/dist/esm/domain/token.js +5 -5
- 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 +3 -19
- package/dist/esm/http/handlers/callback.js +7 -1
- package/dist/esm/http/handlers/metadata.js +2 -2
- package/dist/esm/http/handlers/method-route.js +47 -2
- package/dist/esm/http/handlers/revocation.js +2 -2
- package/dist/esm/http/middleware/tenant.js +6 -6
- package/dist/esm/http/schemas/authorize.js +2 -2
- package/dist/esm/http/schemas/revocation.js +2 -2
- package/dist/esm/http/schemas/token.js +7 -7
- package/dist/esm/index.js +33 -32
- 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/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 +3 -0
- package/dist/types/adapters/memory/session-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/domain/callback.d.ts +16 -1
- package/dist/types/domain/callback.d.ts.map +1 -1
- 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/http/context.d.ts +3 -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/callback.d.ts.map +1 -1
- package/dist/types/http/handlers/method-route.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -1
- 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 +18 -5
- package/dist/types/ports/audit-log.d.ts.map +1 -1
- package/dist/types/ports/session-store.d.ts +23 -0
- package/dist/types/ports/session-store.d.ts.map +1 -1
- package/dist/types/types/idp.d.ts +71 -0
- 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/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 +39 -0
- package/src/adapters/postgres/migrations.ts +6 -0
- package/src/adapters/postgres/session-store.ts +69 -0
- package/src/domain/callback.ts +215 -7
- package/src/domain/method-dispatch.ts +53 -1
- package/src/domain/method-route.ts +190 -1
- package/src/http/context.ts +6 -0
- package/src/http/cookies.ts +19 -1
- package/src/http/handlers/authorize.ts +2 -21
- package/src/http/handlers/callback.ts +9 -1
- package/src/http/handlers/method-route.ts +75 -2
- package/src/index.ts +3 -0
- 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 +25 -0
- package/src/ports/audit-log.ts +18 -5
- package/src/ports/session-store.ts +28 -0
- package/src/types/idp.ts +74 -0
- package/src/types/method.ts +110 -0
package/src/types/idp.ts
CHANGED
|
@@ -69,6 +69,56 @@ export type FailureEvent = {
|
|
|
69
69
|
error: AuthError
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
+
/**
|
|
73
|
+
* Input to the optional `IdPOptions.onLogout` hook.
|
|
74
|
+
*
|
|
75
|
+
* Fires when an upstream provider notifies this IdP that a federated
|
|
76
|
+
* session has ended — today, a SAML front-channel `LogoutRequest`
|
|
77
|
+
* delivered to the SP's SLS endpoint. By the time this runs the library
|
|
78
|
+
* has already cryptographically verified the upstream logout message
|
|
79
|
+
* (XML-DSig via the SAML method), so the hook is purely the host's
|
|
80
|
+
* teardown point.
|
|
81
|
+
*
|
|
82
|
+
* The library deliberately does **not** know which OIDC `subject` an
|
|
83
|
+
* upstream identifier (`nameId`) maps to — that mapping lives in the
|
|
84
|
+
* host's `success` callback, not the library. So the host clears its
|
|
85
|
+
* own session and returns the subject (if any) whose library-issued
|
|
86
|
+
* tokens should be revoked; the library then runs the same
|
|
87
|
+
* `revokeAllForSubject` primitive `/end_session` uses. Returning
|
|
88
|
+
* nothing skips library-side revocation (the host handled everything,
|
|
89
|
+
* or there is nothing to revoke).
|
|
90
|
+
*
|
|
91
|
+
* Method-agnostic on purpose: any federation method that can verify an
|
|
92
|
+
* upstream logout signal reuses this. SAML SLO is the first caller;
|
|
93
|
+
* OIDC back-channel logout would be the next.
|
|
94
|
+
*/
|
|
95
|
+
export type LogoutEventInput = {
|
|
96
|
+
tenant: TenantContext
|
|
97
|
+
methodId: string
|
|
98
|
+
methodKind: string
|
|
99
|
+
/** What kind of upstream logout this is. Extensible discriminant. */
|
|
100
|
+
reason: "upstream_slo"
|
|
101
|
+
/**
|
|
102
|
+
* Upstream subject identifier from the verified logout message
|
|
103
|
+
* (SAML `LogoutRequest/NameID`). Absent if the message omitted it.
|
|
104
|
+
*/
|
|
105
|
+
nameId?: string
|
|
106
|
+
/**
|
|
107
|
+
* Upstream session index from the verified logout message
|
|
108
|
+
* (SAML `SessionIndex`), when present. Lets a host that tracks
|
|
109
|
+
* per-session state scope its teardown.
|
|
110
|
+
*/
|
|
111
|
+
sessionIndex?: string
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Return of `IdPOptions.onLogout`. `revokeSubject` names the OIDC
|
|
116
|
+
* subject whose library-issued refresh tokens the library should
|
|
117
|
+
* revoke (the host resolves it from `nameId` — only the host has that
|
|
118
|
+
* map). Omit / return nothing to skip library-side revocation.
|
|
119
|
+
*/
|
|
120
|
+
export type LogoutHookResult = { revokeSubject?: string } | void
|
|
121
|
+
|
|
72
122
|
/**
|
|
73
123
|
* Optional hook called at `/token` time, after PKCE has succeeded and
|
|
74
124
|
* after the `success` callback has produced a `SubjectClaim`, but
|
|
@@ -259,6 +309,30 @@ export type IdPOptions = {
|
|
|
259
309
|
onFailure?: (event: FailureEvent) => Promise<void>
|
|
260
310
|
}
|
|
261
311
|
|
|
312
|
+
/**
|
|
313
|
+
* Optional hook fired when an upstream provider signals that a
|
|
314
|
+
* federated session ended — SAML front-channel Single Logout today.
|
|
315
|
+
* The library has already verified the signed logout message; this
|
|
316
|
+
* hook is where the host tears down its own session and names the
|
|
317
|
+
* OIDC subject (if any) whose library-issued tokens to revoke. See
|
|
318
|
+
* the `LogoutEventInput` / `LogoutHookResult` type docs.
|
|
319
|
+
*
|
|
320
|
+
* Unlike `hooks.onSuccess`/`onFailure` (observation only) this hook
|
|
321
|
+
* **influences** library behaviour — its return drives token
|
|
322
|
+
* revocation — so it sits at the top level alongside `success`.
|
|
323
|
+
*
|
|
324
|
+
* Absent ⇒ the library still verifies the logout, emits a
|
|
325
|
+
* `session_logout` audit event, and returns the protocol
|
|
326
|
+
* `LogoutResponse`, but performs no token revocation (it cannot map
|
|
327
|
+
* the upstream id to a subject without the host).
|
|
328
|
+
*
|
|
329
|
+
* If it throws, the SLS endpoint fails closed with an internal error
|
|
330
|
+
* rather than acknowledging a logout it could not fully process.
|
|
331
|
+
*/
|
|
332
|
+
onLogout?: (
|
|
333
|
+
input: LogoutEventInput,
|
|
334
|
+
) => Promise<LogoutHookResult> | LogoutHookResult
|
|
335
|
+
|
|
262
336
|
/**
|
|
263
337
|
* Optional escape hatch for high-sensitivity deployments — see the
|
|
264
338
|
* `PersistUpstreamTokens` type doc.
|
package/src/types/method.ts
CHANGED
|
@@ -56,6 +56,37 @@ export type AuthMethod<P = unknown, S = unknown> = {
|
|
|
56
56
|
* same factory get distinct URL spaces).
|
|
57
57
|
*/
|
|
58
58
|
routes: Record<string, MethodHandler<P, S>>
|
|
59
|
+
/**
|
|
60
|
+
* Opt-in allowlist of route keys (same `"GET /metadata"` string form
|
|
61
|
+
* as `routes` keys) that the framework dispatches **without** a flow
|
|
62
|
+
* cookie or flow record — anonymous, unauthenticated GETs. The sole
|
|
63
|
+
* intended use is publishing static, per-instance descriptive
|
|
64
|
+
* documents (SAML SP metadata XML). The handler receives
|
|
65
|
+
* `ctx.flow === null` and `ctx.methodState === null` and MUST be a
|
|
66
|
+
* pure function of `ctx.tenant` + `ctx.dispatch` + its captured
|
|
67
|
+
* config — it must not assume an authenticated principal.
|
|
68
|
+
*
|
|
69
|
+
* Absent (the default for every method) ⇒ behaviour is unchanged:
|
|
70
|
+
* every `/m/<id>/*` request requires the `idp.flow` cookie. The
|
|
71
|
+
* cookie gate is skipped *only* for a route key a method explicitly
|
|
72
|
+
* lists here — fail-closed by construction.
|
|
73
|
+
*/
|
|
74
|
+
publicRoutes?: ReadonlyArray<string>
|
|
75
|
+
/**
|
|
76
|
+
* Opt-in: this method instance handles **unsolicited** upstream
|
|
77
|
+
* callbacks — a `POST /cb/<methodId>` carrying a provider assertion
|
|
78
|
+
* with no framework state envelope and no prior flow (SAML
|
|
79
|
+
* IdP-initiated SSO). When `true`, the framework, instead of
|
|
80
|
+
* rejecting a stateless callback, dispatches `GET /callback` with
|
|
81
|
+
* `flow === null` and a derived `dispatch` (issuer/ACS); the handler
|
|
82
|
+
* verifies the assertion and returns `success` **with
|
|
83
|
+
* `unsolicitedBinding`**. Absent (every method's default) ⇒ a
|
|
84
|
+
* stateless callback stays an `invalid_request` (the conservative
|
|
85
|
+
* default — many deployments do not want IdP-initiated). General
|
|
86
|
+
* capability, not SAML-specific; set per instance (a SAML instance
|
|
87
|
+
* sets it only when its config enables IdP-initiated).
|
|
88
|
+
*/
|
|
89
|
+
unsolicitedCallback?: boolean
|
|
59
90
|
/**
|
|
60
91
|
* Token-exchange function for the `/token` endpoint when the method
|
|
61
92
|
* participates in client-credentials-style flows (e.g. `m2m`). Most
|
|
@@ -102,6 +133,47 @@ export type MethodContext<S = unknown> = {
|
|
|
102
133
|
* and the relevant data is on `flow`).
|
|
103
134
|
*/
|
|
104
135
|
dispatch: MethodDispatchData | null
|
|
136
|
+
/**
|
|
137
|
+
* Per-method-instance scratch storage scoped to
|
|
138
|
+
* `(tenant.id, method.id)`. Survives across flows — distinct from
|
|
139
|
+
* `methodState`, which is per-flow.
|
|
140
|
+
*
|
|
141
|
+
* Most methods do NOT need this. It exists for cross-flow
|
|
142
|
+
* deduplication patterns such as SAML SP assertion-ID replay
|
|
143
|
+
* protection.
|
|
144
|
+
*
|
|
145
|
+
* Backed by `SessionStore.{saveScratch,readScratch,deleteScratch}`
|
|
146
|
+
* when those optional methods are implemented. Against adapters that
|
|
147
|
+
* don't implement them, every call returns
|
|
148
|
+
* `{ ok: false, error: unsupported }` — the method should surface a
|
|
149
|
+
* `MethodResult.error` with a clear message, not silently degrade.
|
|
150
|
+
*/
|
|
151
|
+
methodScratch: MethodScratch
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Caller-facing API for per-method-instance scratch. The framework
|
|
156
|
+
* scopes user-supplied keys with a `(tenantId, methodId)` prefix before
|
|
157
|
+
* delegating to `SessionStore` — adapters never see raw method keys.
|
|
158
|
+
*
|
|
159
|
+
* Values are UTF-8 strings; methods JSON-encode if they want to stash
|
|
160
|
+
* objects. Keeping the port-level type narrow simplifies adapter
|
|
161
|
+
* implementations (one TEXT column, one Dynamo `S` attribute, etc.).
|
|
162
|
+
*/
|
|
163
|
+
export type MethodScratch = {
|
|
164
|
+
/**
|
|
165
|
+
* Persist `value` under `key` with the given TTL. Overwrites prior
|
|
166
|
+
* value for the same key. `ttlMs` must be positive.
|
|
167
|
+
*/
|
|
168
|
+
put(key: string, value: string, ttlMs: number): Promise<Result<void>>
|
|
169
|
+
/**
|
|
170
|
+
* Read the value previously stored at `key`. Returns `unknown_state`
|
|
171
|
+
* if the key is missing or expired (the underlying adapter MAY
|
|
172
|
+
* lazily evict expired entries on read).
|
|
173
|
+
*/
|
|
174
|
+
get(key: string): Promise<Result<string>>
|
|
175
|
+
/** Idempotent. Resolves `ok` whether the key existed or not. */
|
|
176
|
+
delete(key: string): Promise<Result<void>>
|
|
105
177
|
}
|
|
106
178
|
|
|
107
179
|
/** Framework-supplied data available to the method at `/authorize` time. */
|
|
@@ -143,6 +215,27 @@ export type MethodResult<P = unknown, S = unknown> =
|
|
|
143
215
|
saveMethodState?: S
|
|
144
216
|
/** Serialized into a `Cache-Control` header by the framework. */
|
|
145
217
|
cache?: CachePolicy
|
|
218
|
+
/**
|
|
219
|
+
* Verified upstream-logout notification. Set **only** by a
|
|
220
|
+
* flowless **public** logout route (e.g. SAML front-channel SLS)
|
|
221
|
+
* once it has cryptographically verified the inbound logout
|
|
222
|
+
* message. The method stays port-free — it proves authenticity
|
|
223
|
+
* and builds the protocol response (`response` = the signed
|
|
224
|
+
* `LogoutResponse` redirect / ack); the privileged side effect
|
|
225
|
+
* runs in the framework.
|
|
226
|
+
*
|
|
227
|
+
* When present on a public route the framework fires
|
|
228
|
+
* `IdPOptions.onLogout` and, if that returns `{ revokeSubject }`,
|
|
229
|
+
* runs `revokeAllForSubject` — then returns `response`. Ignored
|
|
230
|
+
* on non-public (flow-bearing) routes: an authenticated method
|
|
231
|
+
* route never logs anyone out. Mirrors the Phase 2 V′ pattern
|
|
232
|
+
* (`success.unsolicitedBinding`): an optional field on an
|
|
233
|
+
* existing variant, not a new `MethodResult` kind.
|
|
234
|
+
*/
|
|
235
|
+
logout?: {
|
|
236
|
+
nameId?: string
|
|
237
|
+
sessionIndex?: string
|
|
238
|
+
}
|
|
146
239
|
}
|
|
147
240
|
/**
|
|
148
241
|
* Authentication succeeded. The HTTP layer hands `providerSubject` +
|
|
@@ -155,6 +248,23 @@ export type MethodResult<P = unknown, S = unknown> =
|
|
|
155
248
|
providerSubject: string
|
|
156
249
|
properties: P
|
|
157
250
|
setCookies?: SetCookie[]
|
|
251
|
+
/**
|
|
252
|
+
* RP binding for a **flowless** (unsolicited / IdP-initiated)
|
|
253
|
+
* authentication. Consulted **only** when the method ran with no
|
|
254
|
+
* `flow` (e.g. an unsolicited SAML Response — see
|
|
255
|
+
* `AuthMethod.unsolicitedCallback`). On the normal SP-initiated
|
|
256
|
+
* path a `flow` exists and this is ignored; on the flowless path
|
|
257
|
+
* it is **required** (the framework has no pending RP request to
|
|
258
|
+
* read `client_id` / `redirect_uri` / `scope` from, so the method
|
|
259
|
+
* supplies the operator-configured defaults). The framework still
|
|
260
|
+
* validates `clientId` / `redirectUri` against the tenant's
|
|
261
|
+
* registered client before issuing a code.
|
|
262
|
+
*/
|
|
263
|
+
unsolicitedBinding?: {
|
|
264
|
+
clientId: string
|
|
265
|
+
redirectUri: string
|
|
266
|
+
scopes: string[]
|
|
267
|
+
}
|
|
158
268
|
}
|
|
159
269
|
/** User refused / failed auth in a non-error way (e.g. consent declined). */
|
|
160
270
|
| { kind: "denied"; reason: string; setCookies?: SetCookie[] }
|