@better-auth/oauth-provider 1.7.0-beta.1 → 1.7.0-beta.10
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/{client-assertion-CderPEmR.mjs → client-assertion-D-tAYsKC.mjs} +105 -90
- package/dist/client-resource.d.mts +43 -7
- package/dist/client-resource.mjs +45 -25
- package/dist/client.d.mts +1 -1
- package/dist/client.mjs +3 -13
- package/dist/index.d.mts +111 -22
- package/dist/index.mjs +2401 -2045
- package/dist/introspect-DvHp2a64.mjs +2507 -0
- package/dist/{oauth-B_qonG53.d.mts → oauth-BrNRbP2A.d.mts} +507 -205
- package/dist/{oauth-CU79t-eG.d.mts → oauth-ScTJEcFV.d.mts} +1167 -60
- package/dist/resource-challenge-B-cqv4ur.mjs +63 -0
- package/dist/rolldown-runtime-wcPFST8Q.mjs +13 -0
- package/dist/signed-query-Df1MNiSH.mjs +44 -0
- package/dist/utils-DO8lmoDw.mjs +769 -0
- package/dist/{version-DIwdpXrQ.mjs → version-a5HhJg8A.mjs} +1 -1
- package/package.json +9 -10
- package/dist/mcp-CYnz-MXn.mjs +0 -56
- package/dist/utils-Cx_XnD9i.mjs +0 -449
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
1
|
+
import * as z from "zod";
|
|
2
|
+
import { PrivateKeyJwtSigningAlgorithm } from "@better-auth/core/oauth2";
|
|
3
3
|
import { JWTPayload } from "jose";
|
|
4
|
+
import { JWSAlgorithms } from "better-auth/plugins";
|
|
4
5
|
import { InferOptionSchema, Session, User } from "better-auth/types";
|
|
5
6
|
import { GenericEndpointContext, LiteralString } from "@better-auth/core";
|
|
6
7
|
|
|
@@ -46,6 +47,7 @@ declare const schema: {
|
|
|
46
47
|
model: string;
|
|
47
48
|
field: string;
|
|
48
49
|
};
|
|
50
|
+
index: true;
|
|
49
51
|
};
|
|
50
52
|
createdAt: {
|
|
51
53
|
type: "date";
|
|
@@ -99,6 +101,14 @@ declare const schema: {
|
|
|
99
101
|
type: "string[]";
|
|
100
102
|
required: false;
|
|
101
103
|
};
|
|
104
|
+
backchannelLogoutUri: {
|
|
105
|
+
type: "string";
|
|
106
|
+
required: false;
|
|
107
|
+
};
|
|
108
|
+
backchannelLogoutSessionRequired: {
|
|
109
|
+
type: "boolean";
|
|
110
|
+
required: false;
|
|
111
|
+
};
|
|
102
112
|
tokenEndpointAuthMethod: {
|
|
103
113
|
type: "string";
|
|
104
114
|
required: false;
|
|
@@ -131,6 +141,11 @@ declare const schema: {
|
|
|
131
141
|
type: "boolean";
|
|
132
142
|
required: false;
|
|
133
143
|
};
|
|
144
|
+
dpopBoundAccessTokens: {
|
|
145
|
+
type: "boolean";
|
|
146
|
+
required: false;
|
|
147
|
+
defaultValue: false;
|
|
148
|
+
};
|
|
134
149
|
referenceId: {
|
|
135
150
|
type: "string";
|
|
136
151
|
required: false;
|
|
@@ -141,6 +156,141 @@ declare const schema: {
|
|
|
141
156
|
};
|
|
142
157
|
};
|
|
143
158
|
};
|
|
159
|
+
/**
|
|
160
|
+
* A protected resource the AS issues access tokens for.
|
|
161
|
+
*
|
|
162
|
+
* Promotes protected resources into a first-class persisted entity with
|
|
163
|
+
* per-resource token policy. A null value
|
|
164
|
+
* on any policy column means "inherit the plugin-level default at token
|
|
165
|
+
* issuance time" — admins can later override without re-seeding.
|
|
166
|
+
*
|
|
167
|
+
* @see RFC 8707 (Resource Indicators) — `identifier` is the `resource` parameter value
|
|
168
|
+
* @see RFC 9068 §2.2 — `customClaims` cannot override reserved JWT claims (enforced server-side)
|
|
169
|
+
*/
|
|
170
|
+
oauthResource: {
|
|
171
|
+
modelName: string;
|
|
172
|
+
fields: {
|
|
173
|
+
identifier: {
|
|
174
|
+
type: "string";
|
|
175
|
+
required: true;
|
|
176
|
+
unique: true;
|
|
177
|
+
};
|
|
178
|
+
name: {
|
|
179
|
+
type: "string";
|
|
180
|
+
required: true;
|
|
181
|
+
};
|
|
182
|
+
accessTokenTtl: {
|
|
183
|
+
type: "number";
|
|
184
|
+
required: false;
|
|
185
|
+
};
|
|
186
|
+
refreshTokenTtl: {
|
|
187
|
+
type: "number";
|
|
188
|
+
required: false;
|
|
189
|
+
};
|
|
190
|
+
signingAlgorithm: {
|
|
191
|
+
type: "string";
|
|
192
|
+
required: false;
|
|
193
|
+
};
|
|
194
|
+
signingKeyId: {
|
|
195
|
+
type: "string";
|
|
196
|
+
required: false;
|
|
197
|
+
};
|
|
198
|
+
allowedScopes: {
|
|
199
|
+
type: "string[]";
|
|
200
|
+
required: false;
|
|
201
|
+
};
|
|
202
|
+
customClaims: {
|
|
203
|
+
type: "json";
|
|
204
|
+
required: false;
|
|
205
|
+
};
|
|
206
|
+
dpopBoundAccessTokensRequired: {
|
|
207
|
+
type: "boolean";
|
|
208
|
+
required: false;
|
|
209
|
+
defaultValue: false;
|
|
210
|
+
};
|
|
211
|
+
disabled: {
|
|
212
|
+
type: "boolean";
|
|
213
|
+
required: false;
|
|
214
|
+
defaultValue: false;
|
|
215
|
+
};
|
|
216
|
+
createdAt: {
|
|
217
|
+
type: "date";
|
|
218
|
+
required: false;
|
|
219
|
+
};
|
|
220
|
+
updatedAt: {
|
|
221
|
+
type: "date";
|
|
222
|
+
required: false;
|
|
223
|
+
};
|
|
224
|
+
policyVersion: {
|
|
225
|
+
type: "number";
|
|
226
|
+
required: false;
|
|
227
|
+
defaultValue: number;
|
|
228
|
+
};
|
|
229
|
+
metadata: {
|
|
230
|
+
type: "json";
|
|
231
|
+
required: false;
|
|
232
|
+
};
|
|
233
|
+
};
|
|
234
|
+
};
|
|
235
|
+
/**
|
|
236
|
+
* Join table — which clients are allowed to request which resources.
|
|
237
|
+
*
|
|
238
|
+
* Authoritative only when `enforcePerClientResources: true` on plugin options.
|
|
239
|
+
* When the flag is off, clients implicitly have access to all enabled resources
|
|
240
|
+
* (preserves pre-entity behavior).
|
|
241
|
+
*
|
|
242
|
+
* Composite uniqueness on `(clientId, resourceId)` is load-bearing — the
|
|
243
|
+
* `enforcePerClientResources` linkage check assumes one row per pair.
|
|
244
|
+
*
|
|
245
|
+
* Better Auth's schema layer doesn't expose composite-UNIQUE syntax (no
|
|
246
|
+
* way to declare `UNIQUE(clientId, resourceId)` at the column level). To
|
|
247
|
+
* enforce it at the database level for free, we set the row's `id` to a
|
|
248
|
+
* deterministic `${clientId}::${resourceId}` value at write time and let
|
|
249
|
+
* the implicit `UNIQUE` constraint on the primary key catch duplicates
|
|
250
|
+
* (see `buildClientResourceLinkId` and the `forceAllowId: true` flag on
|
|
251
|
+
* the `adapter.create` call in `oauthResource/endpoints.ts`). The double
|
|
252
|
+
* colon separator is chosen because `::` cannot appear in either a
|
|
253
|
+
* client_id (URL-safe random string) or a resource identifier (RFC 8707
|
|
254
|
+
* absolute URI — `::` would be an IPv6 form rejected by the validator),
|
|
255
|
+
* so the encoding is collision-free.
|
|
256
|
+
*
|
|
257
|
+
* Concurrent inserts of the same pair surface as a UNIQUE-constraint
|
|
258
|
+
* error which the endpoint catches and converts to a 200 "alreadyLinked"
|
|
259
|
+
* response (idempotency).
|
|
260
|
+
*/
|
|
261
|
+
oauthClientResource: {
|
|
262
|
+
modelName: string;
|
|
263
|
+
fields: {
|
|
264
|
+
clientId: {
|
|
265
|
+
type: "string";
|
|
266
|
+
required: true;
|
|
267
|
+
references: {
|
|
268
|
+
model: string;
|
|
269
|
+
field: string;
|
|
270
|
+
onDelete: "cascade";
|
|
271
|
+
};
|
|
272
|
+
index: true;
|
|
273
|
+
};
|
|
274
|
+
resourceId: {
|
|
275
|
+
type: "string";
|
|
276
|
+
required: true;
|
|
277
|
+
references: {
|
|
278
|
+
model: string;
|
|
279
|
+
field: string;
|
|
280
|
+
onDelete: "cascade";
|
|
281
|
+
};
|
|
282
|
+
index: true;
|
|
283
|
+
};
|
|
284
|
+
metadata: {
|
|
285
|
+
type: "json";
|
|
286
|
+
required: false;
|
|
287
|
+
};
|
|
288
|
+
createdAt: {
|
|
289
|
+
type: "date";
|
|
290
|
+
required: false;
|
|
291
|
+
};
|
|
292
|
+
};
|
|
293
|
+
};
|
|
144
294
|
/**
|
|
145
295
|
* An opaque refresh token created with "offline_access"
|
|
146
296
|
*
|
|
@@ -151,6 +301,7 @@ declare const schema: {
|
|
|
151
301
|
token: {
|
|
152
302
|
type: "string";
|
|
153
303
|
required: true;
|
|
304
|
+
unique: true;
|
|
154
305
|
};
|
|
155
306
|
clientId: {
|
|
156
307
|
type: "string";
|
|
@@ -159,6 +310,7 @@ declare const schema: {
|
|
|
159
310
|
model: string;
|
|
160
311
|
field: string;
|
|
161
312
|
};
|
|
313
|
+
index: true;
|
|
162
314
|
};
|
|
163
315
|
sessionId: {
|
|
164
316
|
type: "string";
|
|
@@ -168,6 +320,7 @@ declare const schema: {
|
|
|
168
320
|
field: string;
|
|
169
321
|
onDelete: "set null";
|
|
170
322
|
};
|
|
323
|
+
index: true;
|
|
171
324
|
};
|
|
172
325
|
userId: {
|
|
173
326
|
type: "string";
|
|
@@ -176,11 +329,25 @@ declare const schema: {
|
|
|
176
329
|
model: string;
|
|
177
330
|
field: string;
|
|
178
331
|
};
|
|
332
|
+
index: true;
|
|
179
333
|
};
|
|
180
334
|
referenceId: {
|
|
181
335
|
type: "string";
|
|
182
336
|
required: false;
|
|
183
337
|
};
|
|
338
|
+
authorizationCodeId: {
|
|
339
|
+
type: "string";
|
|
340
|
+
required: false;
|
|
341
|
+
index: true;
|
|
342
|
+
};
|
|
343
|
+
resources: {
|
|
344
|
+
type: "string[]";
|
|
345
|
+
required: false;
|
|
346
|
+
};
|
|
347
|
+
requestedUserInfoClaims: {
|
|
348
|
+
type: "string[]";
|
|
349
|
+
required: false;
|
|
350
|
+
};
|
|
184
351
|
expiresAt: {
|
|
185
352
|
type: "date";
|
|
186
353
|
};
|
|
@@ -191,10 +358,26 @@ declare const schema: {
|
|
|
191
358
|
type: "date";
|
|
192
359
|
required: false;
|
|
193
360
|
};
|
|
361
|
+
rotatedAt: {
|
|
362
|
+
type: "date";
|
|
363
|
+
required: false;
|
|
364
|
+
};
|
|
365
|
+
rotationReplayResponse: {
|
|
366
|
+
type: "string";
|
|
367
|
+
required: false;
|
|
368
|
+
};
|
|
369
|
+
rotationReplayExpiresAt: {
|
|
370
|
+
type: "date";
|
|
371
|
+
required: false;
|
|
372
|
+
};
|
|
194
373
|
authTime: {
|
|
195
374
|
type: "date";
|
|
196
375
|
required: false;
|
|
197
376
|
};
|
|
377
|
+
confirmation: {
|
|
378
|
+
type: "json";
|
|
379
|
+
required: false;
|
|
380
|
+
};
|
|
198
381
|
scopes: {
|
|
199
382
|
type: "string[]";
|
|
200
383
|
required: true;
|
|
@@ -202,7 +385,7 @@ declare const schema: {
|
|
|
202
385
|
};
|
|
203
386
|
};
|
|
204
387
|
/**
|
|
205
|
-
* An opaque access token sent when there is no audience
|
|
388
|
+
* An opaque access token sent when there is no resource audience claim
|
|
206
389
|
* to assigned to the JWT.
|
|
207
390
|
*
|
|
208
391
|
* Access tokens are linked to a session, better-auth
|
|
@@ -227,6 +410,7 @@ declare const schema: {
|
|
|
227
410
|
model: string;
|
|
228
411
|
field: string;
|
|
229
412
|
};
|
|
413
|
+
index: true;
|
|
230
414
|
};
|
|
231
415
|
sessionId: {
|
|
232
416
|
type: "string";
|
|
@@ -236,6 +420,7 @@ declare const schema: {
|
|
|
236
420
|
field: string;
|
|
237
421
|
onDelete: "set null";
|
|
238
422
|
};
|
|
423
|
+
index: true;
|
|
239
424
|
};
|
|
240
425
|
userId: {
|
|
241
426
|
type: "string";
|
|
@@ -244,11 +429,25 @@ declare const schema: {
|
|
|
244
429
|
model: string;
|
|
245
430
|
field: string;
|
|
246
431
|
};
|
|
432
|
+
index: true;
|
|
247
433
|
};
|
|
248
434
|
referenceId: {
|
|
249
435
|
type: "string";
|
|
250
436
|
required: false;
|
|
251
437
|
};
|
|
438
|
+
authorizationCodeId: {
|
|
439
|
+
type: "string";
|
|
440
|
+
required: false;
|
|
441
|
+
index: true;
|
|
442
|
+
};
|
|
443
|
+
resources: {
|
|
444
|
+
type: "string[]";
|
|
445
|
+
required: false;
|
|
446
|
+
};
|
|
447
|
+
requestedUserInfoClaims: {
|
|
448
|
+
type: "string[]";
|
|
449
|
+
required: false;
|
|
450
|
+
};
|
|
252
451
|
refreshId: {
|
|
253
452
|
type: "string";
|
|
254
453
|
required: false;
|
|
@@ -256,6 +455,7 @@ declare const schema: {
|
|
|
256
455
|
model: string;
|
|
257
456
|
field: string;
|
|
258
457
|
};
|
|
458
|
+
index: true;
|
|
259
459
|
};
|
|
260
460
|
expiresAt: {
|
|
261
461
|
type: "date";
|
|
@@ -263,6 +463,14 @@ declare const schema: {
|
|
|
263
463
|
createdAt: {
|
|
264
464
|
type: "date";
|
|
265
465
|
};
|
|
466
|
+
revoked: {
|
|
467
|
+
type: "date";
|
|
468
|
+
required: false;
|
|
469
|
+
};
|
|
470
|
+
confirmation: {
|
|
471
|
+
type: "json";
|
|
472
|
+
required: false;
|
|
473
|
+
};
|
|
266
474
|
scopes: {
|
|
267
475
|
type: "string[]";
|
|
268
476
|
required: true;
|
|
@@ -279,6 +487,7 @@ declare const schema: {
|
|
|
279
487
|
model: string;
|
|
280
488
|
field: string;
|
|
281
489
|
};
|
|
490
|
+
index: true;
|
|
282
491
|
};
|
|
283
492
|
userId: {
|
|
284
493
|
type: "string";
|
|
@@ -287,11 +496,20 @@ declare const schema: {
|
|
|
287
496
|
model: string;
|
|
288
497
|
field: string;
|
|
289
498
|
};
|
|
499
|
+
index: true;
|
|
290
500
|
};
|
|
291
501
|
referenceId: {
|
|
292
502
|
type: "string";
|
|
293
503
|
required: false;
|
|
294
504
|
};
|
|
505
|
+
resources: {
|
|
506
|
+
type: "string[]";
|
|
507
|
+
required: false;
|
|
508
|
+
};
|
|
509
|
+
requestedUserInfoClaims: {
|
|
510
|
+
type: "string[]";
|
|
511
|
+
required: false;
|
|
512
|
+
};
|
|
295
513
|
scopes: {
|
|
296
514
|
type: "string[]";
|
|
297
515
|
required: true;
|
|
@@ -304,13 +522,104 @@ declare const schema: {
|
|
|
304
522
|
};
|
|
305
523
|
};
|
|
306
524
|
};
|
|
525
|
+
/**
|
|
526
|
+
* Single-use record for `private_key_jwt` client assertion `jti` values. The
|
|
527
|
+
* row id is a digest of the per-client assertion identifier, so a replayed or
|
|
528
|
+
* concurrent assertion collides on the primary key and the insert fails
|
|
529
|
+
* atomically on every adapter (SQL primary key, MongoDB `_id`), including
|
|
530
|
+
* across multiple server processes.
|
|
531
|
+
*
|
|
532
|
+
* A row keeps blocking its id until deleted; `expiresAt` marks when removal
|
|
533
|
+
* is safe, since the assertion it guards has expired and is rejected earlier.
|
|
534
|
+
* TODO: no scheduled job prunes expired rows yet; like the verification
|
|
535
|
+
* table, they accumulate until a deployment-level sweep removes them.
|
|
536
|
+
*/
|
|
537
|
+
oauthClientAssertion: {
|
|
538
|
+
modelName: string;
|
|
539
|
+
fields: {
|
|
540
|
+
expiresAt: {
|
|
541
|
+
type: "date";
|
|
542
|
+
required: true;
|
|
543
|
+
};
|
|
544
|
+
};
|
|
545
|
+
};
|
|
307
546
|
};
|
|
308
547
|
//#endregion
|
|
309
548
|
//#region src/types/helpers.d.ts
|
|
310
549
|
type Awaitable<T> = Promise<T> | T;
|
|
311
550
|
//#endregion
|
|
551
|
+
//#region src/types/zod.d.ts
|
|
552
|
+
/**
|
|
553
|
+
* Validates an RFC 8707 resource indicator. The value must be an absolute URI
|
|
554
|
+
* with no fragment (RFC 8707 §2). Unlike a redirect URI it is not restricted to
|
|
555
|
+
* HTTPS, because a resource server identifier may use any absolute URI scheme;
|
|
556
|
+
* configured OAuth resources are the authoritative control over
|
|
557
|
+
* which resources a token may target.
|
|
558
|
+
*/
|
|
559
|
+
declare const ResourceUriSchema: z.ZodString;
|
|
560
|
+
/**
|
|
561
|
+
* Request body accepted at `POST /oauth2/register` (RFC 7591 §2 client
|
|
562
|
+
* metadata). This is the single source of truth for the registration contract:
|
|
563
|
+
* the endpoint validates against it and {@link ClientRegistrationRequest} is
|
|
564
|
+
* inferred from it, so the type a `validateInitialAccessToken` callback receives
|
|
565
|
+
* always matches what is actually validated. `grant_types` and
|
|
566
|
+
* `token_endpoint_auth_method` are open strings because extensions can register
|
|
567
|
+
* custom values. Server-assigned fields (`client_id`, `client_secret`, the
|
|
568
|
+
* issued/expiry timestamps) and internal state (`disabled`, `reference_id`) are
|
|
569
|
+
* never part of a registration request.
|
|
570
|
+
*
|
|
571
|
+
* @see https://datatracker.ietf.org/doc/html/rfc7591#section-2
|
|
572
|
+
*/
|
|
573
|
+
declare const clientRegistrationRequestSchema: z.ZodObject<{
|
|
574
|
+
redirect_uris: z.ZodOptional<z.ZodArray<z.ZodURL>>;
|
|
575
|
+
scope: z.ZodOptional<z.ZodString>;
|
|
576
|
+
client_name: z.ZodOptional<z.ZodString>;
|
|
577
|
+
client_uri: z.ZodOptional<z.ZodString>;
|
|
578
|
+
logo_uri: z.ZodOptional<z.ZodString>;
|
|
579
|
+
contacts: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
580
|
+
tos_uri: z.ZodOptional<z.ZodString>;
|
|
581
|
+
policy_uri: z.ZodOptional<z.ZodString>;
|
|
582
|
+
software_id: z.ZodOptional<z.ZodString>;
|
|
583
|
+
software_version: z.ZodOptional<z.ZodString>;
|
|
584
|
+
software_statement: z.ZodOptional<z.ZodString>;
|
|
585
|
+
post_logout_redirect_uris: z.ZodOptional<z.ZodArray<z.ZodURL>>;
|
|
586
|
+
backchannel_logout_uri: z.ZodOptional<z.ZodURL>;
|
|
587
|
+
backchannel_logout_session_required: z.ZodOptional<z.ZodBoolean>;
|
|
588
|
+
token_endpoint_auth_method: z.ZodOptional<z.ZodString>;
|
|
589
|
+
jwks: z.ZodOptional<z.ZodUnion<readonly [z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>>, z.ZodObject<{
|
|
590
|
+
keys: z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
591
|
+
}, z.core.$strip>]>>;
|
|
592
|
+
jwks_uri: z.ZodOptional<z.ZodString>;
|
|
593
|
+
grant_types: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
594
|
+
response_types: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
595
|
+
code: "code";
|
|
596
|
+
}>>>;
|
|
597
|
+
type: z.ZodOptional<z.ZodEnum<{
|
|
598
|
+
web: "web";
|
|
599
|
+
native: "native";
|
|
600
|
+
"user-agent-based": "user-agent-based";
|
|
601
|
+
}>>;
|
|
602
|
+
subject_type: z.ZodOptional<z.ZodEnum<{
|
|
603
|
+
public: "public";
|
|
604
|
+
pairwise: "pairwise";
|
|
605
|
+
}>>;
|
|
606
|
+
dpop_bound_access_tokens: z.ZodOptional<z.ZodBoolean>;
|
|
607
|
+
resources: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
608
|
+
skip_consent: z.ZodOptional<z.ZodNever>;
|
|
609
|
+
}, z.core.$strip>;
|
|
610
|
+
/**
|
|
611
|
+
* Client metadata as submitted in an RFC 7591 §2 registration request, inferred
|
|
612
|
+
* from {@link clientRegistrationRequestSchema}. Every value is self-asserted by
|
|
613
|
+
* the caller (RFC 7591 §5) and is the raw request before registration defaults
|
|
614
|
+
* are applied, so a `validateInitialAccessToken` callback should treat it as
|
|
615
|
+
* untrusted and not assume defaulted fields are present.
|
|
616
|
+
*
|
|
617
|
+
* @see https://datatracker.ietf.org/doc/html/rfc7591#section-2
|
|
618
|
+
*/
|
|
619
|
+
type ClientRegistrationRequest = z.infer<typeof clientRegistrationRequestSchema>;
|
|
620
|
+
//#endregion
|
|
312
621
|
//#region src/types/index.d.ts
|
|
313
|
-
type StoreTokenType = "access_token" | "refresh_token" | "authorization_code";
|
|
622
|
+
type StoreTokenType = "access_token" | "refresh_token" | "authorization_code" | (string & {});
|
|
314
623
|
type InternallySupportedScopes = "openid" | "profile" | "email" | "offline_access";
|
|
315
624
|
type Scope = LiteralString | InternallySupportedScopes;
|
|
316
625
|
type Prompt = "none" | "consent" | "login" | "create" | "select_account";
|
|
@@ -320,11 +629,11 @@ type AuthorizePrompt = Prompt | "login consent" | "select_account consent";
|
|
|
320
629
|
* metadata document, a federated registry, an attestation header, etc.) and
|
|
321
630
|
* what fields that source contributes to discovery metadata.
|
|
322
631
|
*
|
|
323
|
-
* Plugins
|
|
324
|
-
* The host walks
|
|
325
|
-
* non-null `resolve()` result.
|
|
632
|
+
* Plugins contribute one of these through
|
|
633
|
+
* {@link OAuthProviderExtension.clientDiscovery}. The host walks every
|
|
634
|
+
* configured entry in order and returns the first non-null `resolve()` result.
|
|
326
635
|
*/
|
|
327
|
-
interface ClientDiscovery
|
|
636
|
+
interface ClientDiscovery {
|
|
328
637
|
/**
|
|
329
638
|
* Stable identifier used in error messages and diagnostics. Convention
|
|
330
639
|
* is to match the plugin id (for example `"cimd"`).
|
|
@@ -346,7 +655,7 @@ interface ClientDiscovery<Scopes extends readonly Scope[] = InternallySupportedS
|
|
|
346
655
|
* - `null`: `getClient()` falls through to the next matching discovery
|
|
347
656
|
* or to the database record (if any).
|
|
348
657
|
*/
|
|
349
|
-
resolve: (ctx: GenericEndpointContext, clientId: string, existing: SchemaClient<
|
|
658
|
+
resolve: (ctx: GenericEndpointContext, clientId: string, existing: SchemaClient<Scope[]> | null) => Awaitable<SchemaClient<Scope[]> | null>;
|
|
350
659
|
/**
|
|
351
660
|
* Fields merged into `/.well-known/oauth-authorization-server` and
|
|
352
661
|
* `/.well-known/openid-configuration` responses. Useful for advertising
|
|
@@ -355,6 +664,337 @@ interface ClientDiscovery<Scopes extends readonly Scope[] = InternallySupportedS
|
|
|
355
664
|
*/
|
|
356
665
|
discoveryMetadata?: Record<string, unknown>;
|
|
357
666
|
}
|
|
667
|
+
interface OAuthAuthenticatedClient {
|
|
668
|
+
clientId: string;
|
|
669
|
+
client: SchemaClient<Scope[]>;
|
|
670
|
+
method?: TokenEndpointAuthMethod;
|
|
671
|
+
/**
|
|
672
|
+
* A sender-constraint the authentication step already proved (for example a
|
|
673
|
+
* wallet-instance key thumbprint). Pass it to `issueTokens` as
|
|
674
|
+
* {@link OAuthTokenIssueParams.confirmation} to bind the issued token to it.
|
|
675
|
+
* The authorization server writes this as token material and does not verify
|
|
676
|
+
* it again, so a strategy must set it only after proving possession.
|
|
677
|
+
*/
|
|
678
|
+
confirmation?: Confirmation;
|
|
679
|
+
}
|
|
680
|
+
interface OAuthClientAuthenticationRequest {
|
|
681
|
+
/**
|
|
682
|
+
* Scopes to validate against the registered client.
|
|
683
|
+
*/
|
|
684
|
+
scopes?: string[];
|
|
685
|
+
/**
|
|
686
|
+
* Set to `false` for public extension grants that only require client_id.
|
|
687
|
+
*
|
|
688
|
+
* @default true
|
|
689
|
+
*/
|
|
690
|
+
requireCredentials?: boolean;
|
|
691
|
+
}
|
|
692
|
+
interface OAuthTokenIssueParams {
|
|
693
|
+
client: SchemaClient<Scope[]>;
|
|
694
|
+
scopes: string[];
|
|
695
|
+
user?: User;
|
|
696
|
+
referenceId?: string;
|
|
697
|
+
sessionId?: string;
|
|
698
|
+
nonce?: string;
|
|
699
|
+
refreshToken?: OAuthRefreshToken<Scope[]> & {
|
|
700
|
+
id: string;
|
|
701
|
+
};
|
|
702
|
+
authTime?: Date;
|
|
703
|
+
verificationValue?: VerificationValue;
|
|
704
|
+
resources?: string[];
|
|
705
|
+
/** Full original authorized resources for the grant, used to seed refresh tokens. */
|
|
706
|
+
originalResources?: string[];
|
|
707
|
+
/**
|
|
708
|
+
* OIDC UserInfo claim names requested by the authorization request's
|
|
709
|
+
* `claims.userinfo` object. The authorization server persists these names so
|
|
710
|
+
* refresh-token rotation and opaque access tokens continue honoring the same
|
|
711
|
+
* UserInfo request contract.
|
|
712
|
+
*/
|
|
713
|
+
requestedUserInfoClaims?: string[];
|
|
714
|
+
/**
|
|
715
|
+
* Additional JWT access-token claims for this single issuance.
|
|
716
|
+
*
|
|
717
|
+
* JWT-only: these are baked into the signed token at mint. Opaque access
|
|
718
|
+
* tokens persist no per-issuance claims, so they do NOT reappear at
|
|
719
|
+
* introspection. A claim that must be visible at opaque-token introspection
|
|
720
|
+
* belongs in a grant-type-stable `claims.accessToken` contributor instead,
|
|
721
|
+
* which the introspection path re-derives. Reserved RFC 9068 claim names stay
|
|
722
|
+
* owned by the authorization server.
|
|
723
|
+
*/
|
|
724
|
+
accessTokenClaims?: Record<string, unknown>;
|
|
725
|
+
/**
|
|
726
|
+
* Additional ID-token claims for this single issuance. Additive: they cannot
|
|
727
|
+
* replace identity, authentication-context, or AS-owned claims.
|
|
728
|
+
*/
|
|
729
|
+
idTokenClaims?: Record<string, unknown>;
|
|
730
|
+
/**
|
|
731
|
+
* Additional fields for the token response envelope. Standard OAuth token
|
|
732
|
+
* response fields stay owned by the authorization server.
|
|
733
|
+
*/
|
|
734
|
+
tokenResponse?: Record<string, unknown>;
|
|
735
|
+
/**
|
|
736
|
+
* Sender-constraint to bind this issuance to (RFC 7800 `cnf`). When set, the
|
|
737
|
+
* issuer stamps it as the access token's `cnf` and derives `token_type` from
|
|
738
|
+
* it, instead of leaving the token a bearer token. Use it to carry a
|
|
739
|
+
* confirmation a client-auth strategy or an out-of-band flow already proved
|
|
740
|
+
* (see {@link OAuthAuthenticatedClient.confirmation}). `cnf` is AS-owned: it
|
|
741
|
+
* is stamped after, and cannot be overridden by, contributed claims.
|
|
742
|
+
*/
|
|
743
|
+
confirmation?: Confirmation;
|
|
744
|
+
}
|
|
745
|
+
interface OAuthTokenResponse {
|
|
746
|
+
access_token: string;
|
|
747
|
+
expires_in: number;
|
|
748
|
+
expires_at: number;
|
|
749
|
+
token_type: TokenType;
|
|
750
|
+
refresh_token: string | undefined;
|
|
751
|
+
scope: string;
|
|
752
|
+
id_token: string | undefined;
|
|
753
|
+
[key: string]: unknown;
|
|
754
|
+
}
|
|
755
|
+
type ActiveAccessTokenPayload = JWTPayload & {
|
|
756
|
+
active: true;
|
|
757
|
+
};
|
|
758
|
+
/**
|
|
759
|
+
* The OAuth Provider's server-side capability surface, bound to a request `ctx`.
|
|
760
|
+
* A grant handler receives one as `provider`; a companion plugin's own endpoint
|
|
761
|
+
* obtains one with `getOAuthProviderApi(ctx, opts, grantType?)`. The same object
|
|
762
|
+
* serves both, so issuance, client resolution, and token verification behave the
|
|
763
|
+
* same inside and outside a grant.
|
|
764
|
+
*/
|
|
765
|
+
interface OAuthProviderApi {
|
|
766
|
+
/**
|
|
767
|
+
* Resolves a registered client by id, consulting extension client-discovery
|
|
768
|
+
* sources. Returns `null` when no client matches.
|
|
769
|
+
*/
|
|
770
|
+
getClient: (clientId: string) => Awaitable<SchemaClient<Scope[]> | null>;
|
|
771
|
+
/**
|
|
772
|
+
* Authenticates the calling client from the request (client secret, assertion,
|
|
773
|
+
* or none). For assertion-based methods, the RFC 7523 audience is bound to the
|
|
774
|
+
* endpoint serving the request, so an assertion cannot be replayed across
|
|
775
|
+
* endpoints. Returns the authenticated client, plus any `confirmation` an
|
|
776
|
+
* assertion strategy proved.
|
|
777
|
+
*/
|
|
778
|
+
authenticateClient: (request?: OAuthClientAuthenticationRequest) => Awaitable<OAuthAuthenticatedClient>;
|
|
779
|
+
/**
|
|
780
|
+
* Issues the token set for this grant (access token, optional refresh token,
|
|
781
|
+
* optional ID token, resource policy, response envelope, and any
|
|
782
|
+
* sender-constraint). The grant type is fixed by the `getOAuthProviderApi`
|
|
783
|
+
* binding (the dispatcher's grant for an in-grant handler, the caller's grant
|
|
784
|
+
* for an out-of-grant endpoint), so it cannot be mislabeled per issuance.
|
|
785
|
+
*
|
|
786
|
+
* Authorization is the caller's responsibility. The authorization server does
|
|
787
|
+
* NOT re-check that `params.scopes`, `params.user`, or `params.resources` are
|
|
788
|
+
* a subset of what `authenticateClient` validated: this is a raw minting
|
|
789
|
+
* primitive, and the built-in grants each validate scopes themselves before
|
|
790
|
+
* calling it.
|
|
791
|
+
*/
|
|
792
|
+
issueTokens: (params: OAuthTokenIssueParams) => Awaitable<OAuthTokenResponse>;
|
|
793
|
+
/**
|
|
794
|
+
* Computes the stored lookup key for a token value (the same hash the
|
|
795
|
+
* provider persists), so a caller can find or revoke a previously issued
|
|
796
|
+
* opaque token by its value.
|
|
797
|
+
*/
|
|
798
|
+
hashToken: (token: string, type: StoreTokenType) => Awaitable<string>;
|
|
799
|
+
/**
|
|
800
|
+
* Validates an access token for introspection-style callers. The returned
|
|
801
|
+
* payload can be inactive; protected-resource endpoints should use
|
|
802
|
+
* `requireActiveAccessToken`.
|
|
803
|
+
*/
|
|
804
|
+
validateAccessToken: (token: string, clientId?: string) => Awaitable<JWTPayload>;
|
|
805
|
+
/**
|
|
806
|
+
* Validates an access token for a protected resource and throws the OAuth
|
|
807
|
+
* bearer challenge when the token is inactive or unknown.
|
|
808
|
+
*/
|
|
809
|
+
requireActiveAccessToken: (token: string, clientId?: string) => Awaitable<ActiveAccessTokenPayload>;
|
|
810
|
+
}
|
|
811
|
+
interface OAuthExtensionGrantHandlerInput {
|
|
812
|
+
ctx: GenericEndpointContext;
|
|
813
|
+
opts: OAuthOptions<Scope[]>;
|
|
814
|
+
grantType: GrantType;
|
|
815
|
+
/** The provider capability surface, pre-bound to this grant's `grantType`. */
|
|
816
|
+
provider: OAuthProviderApi;
|
|
817
|
+
}
|
|
818
|
+
type OAuthExtensionGrantHandler = (input: OAuthExtensionGrantHandlerInput) => Awaitable<OAuthTokenResponse>;
|
|
819
|
+
interface OAuthClientAuthenticationInput {
|
|
820
|
+
ctx: GenericEndpointContext;
|
|
821
|
+
opts: OAuthOptions<Scope[]>;
|
|
822
|
+
assertion: string;
|
|
823
|
+
assertionType: string;
|
|
824
|
+
clientId?: string;
|
|
825
|
+
/**
|
|
826
|
+
* The endpoint URL the assertion was presented to. A strategy MUST bind the
|
|
827
|
+
* assertion to this audience (see {@link OAuthClientAuthenticationStrategy.authenticate}).
|
|
828
|
+
*/
|
|
829
|
+
expectedAudience?: string;
|
|
830
|
+
}
|
|
831
|
+
interface OAuthClientAuthenticationResult {
|
|
832
|
+
/** The client id the assertion proved the caller controls. */
|
|
833
|
+
clientId: string;
|
|
834
|
+
/**
|
|
835
|
+
* A sender-constraint the strategy proved (for example a wallet-instance key
|
|
836
|
+
* thumbprint). The provider stamps it as the issued token's RFC 7800 `cnf`.
|
|
837
|
+
* Set it only after proving possession; the authorization server writes it as
|
|
838
|
+
* token material and does not verify it again.
|
|
839
|
+
*/
|
|
840
|
+
confirmation?: Confirmation;
|
|
841
|
+
}
|
|
842
|
+
interface OAuthClientAuthenticationStrategy {
|
|
843
|
+
/**
|
|
844
|
+
* Assertion type URIs this strategy consumes from `client_assertion_type`.
|
|
845
|
+
* Values must be absolute URIs per RFC 7521. When omitted, the strategy key
|
|
846
|
+
* in `OAuthProviderExtension.clientAuthentication` is used and must also be
|
|
847
|
+
* an absolute URI.
|
|
848
|
+
*/
|
|
849
|
+
assertionTypes?: string[];
|
|
850
|
+
/**
|
|
851
|
+
* Verifies the presented assertion and returns the proven client id (plus any
|
|
852
|
+
* sender-constraint it established). The strategy proves the caller controls
|
|
853
|
+
* `clientId`; it does not supply the authorization record. The provider
|
|
854
|
+
* resolves and authorizes the client itself, so a strategy cannot influence
|
|
855
|
+
* the client's grants, scopes, or enabled state.
|
|
856
|
+
*
|
|
857
|
+
* The strategy owns the full RFC 7521/7523 verification. After verifying the
|
|
858
|
+
* signature against its own key source, it MUST enforce the assertion-hygiene
|
|
859
|
+
* checks the built-in `private_key_jwt` path enforces, or the provider will
|
|
860
|
+
* accept a forged or replayed assertion:
|
|
861
|
+
* - bind the assertion to `input.expectedAudience` (RFC 7523 §3 rule 3),
|
|
862
|
+
* - require a bounded `exp` (RFC 7523 §3 rule 4),
|
|
863
|
+
* - reject replays via a single-use `jti`.
|
|
864
|
+
*
|
|
865
|
+
* The exported `consumeClientAssertion` helper performs the audience,
|
|
866
|
+
* lifetime, and `jti` single-use checks for a decoded payload; call it after
|
|
867
|
+
* signature verification so an extension method inherits the same guarantees
|
|
868
|
+
* as `private_key_jwt`.
|
|
869
|
+
*/
|
|
870
|
+
authenticate: (input: OAuthClientAuthenticationInput) => Awaitable<OAuthClientAuthenticationResult>;
|
|
871
|
+
}
|
|
872
|
+
interface OAuthMetadataExtensionInput {
|
|
873
|
+
ctx: GenericEndpointContext;
|
|
874
|
+
opts: OAuthOptions<Scope[]>;
|
|
875
|
+
type: "oauth-authorization-server" | "openid-configuration";
|
|
876
|
+
/**
|
|
877
|
+
* The discovery document the provider assembled (core authorization-server
|
|
878
|
+
* fields plus any client-discovery metadata). Contributions from other
|
|
879
|
+
* extensions are merged afterwards and are not reflected here, so a
|
|
880
|
+
* contributor decides what to add from provider state alone, independent of
|
|
881
|
+
* extension registration order. The contributor returns the fields to add.
|
|
882
|
+
*/
|
|
883
|
+
document: AuthServerMetadata | OIDCMetadata;
|
|
884
|
+
}
|
|
885
|
+
interface OAuthClaimExtensionInput {
|
|
886
|
+
ctx: GenericEndpointContext;
|
|
887
|
+
opts: OAuthOptions<Scope[]>;
|
|
888
|
+
user?: (User & Record<string, unknown>) | null;
|
|
889
|
+
client: SchemaClient<Scope[]>;
|
|
890
|
+
scopes: string[];
|
|
891
|
+
grantType?: GrantType;
|
|
892
|
+
referenceId?: string;
|
|
893
|
+
/**
|
|
894
|
+
* Session the tokens are issued for, when one is available. Best-effort:
|
|
895
|
+
* set on the session-backed grants (authorization_code, refresh_token),
|
|
896
|
+
* undefined otherwise (client_credentials, introspection, or a session that
|
|
897
|
+
* was deleted or unlinked). Treat as possibly undefined.
|
|
898
|
+
*/
|
|
899
|
+
sessionId?: string;
|
|
900
|
+
resources?: string[];
|
|
901
|
+
/** Parsed client metadata, as returned by `parseClientMetadata`. */
|
|
902
|
+
metadata?: Record<string, unknown>;
|
|
903
|
+
}
|
|
904
|
+
interface OAuthUserInfoExtensionInput {
|
|
905
|
+
ctx: GenericEndpointContext;
|
|
906
|
+
opts: OAuthOptions<Scope[]>;
|
|
907
|
+
user: User & Record<string, unknown>;
|
|
908
|
+
scopes: string[];
|
|
909
|
+
jwt: JWTPayload;
|
|
910
|
+
client?: SchemaClient<Scope[]>;
|
|
911
|
+
/**
|
|
912
|
+
* Claim names explicitly requested through the OIDC `claims.userinfo`
|
|
913
|
+
* authorization request parameter.
|
|
914
|
+
*/
|
|
915
|
+
requestedClaims: string[];
|
|
916
|
+
}
|
|
917
|
+
/**
|
|
918
|
+
* What a companion plugin contributes to the OAuth Provider, registered through
|
|
919
|
+
* `extendOAuthProvider(ctx, extension)` (or the `oauthProvider({ extensions })`
|
|
920
|
+
* option).
|
|
921
|
+
*
|
|
922
|
+
* All five kinds live on one object so a single protocol plugin (for example
|
|
923
|
+
* RFC 8693 token exchange, which adds a grant, advertises metadata, and emits
|
|
924
|
+
* claims) registers atomically and the host validates the combined surface in
|
|
925
|
+
* one place. Every field is independently optional, so a single-concern plugin
|
|
926
|
+
* (such as `@better-auth/cimd`, which contributes only `clientDiscovery`) sets
|
|
927
|
+
* just the one it needs. This is the shape every future OAuth RFC plugin copies.
|
|
928
|
+
*
|
|
929
|
+
* Two contribution disciplines:
|
|
930
|
+
* - Dispatched kinds (`grants`, `clientAuthentication`) must be disjoint across
|
|
931
|
+
* extensions: registering a grant type, auth method, or assertion type that
|
|
932
|
+
* another extension already registered is rejected at setup, since the second
|
|
933
|
+
* would otherwise be silently unreachable.
|
|
934
|
+
* - Additive kinds (`metadata`, `claims`) never override authorization-server
|
|
935
|
+
* core; a key already owned by the provider is kept, and a key two extensions
|
|
936
|
+
* both contribute resolves to the first-registered extension.
|
|
937
|
+
*/
|
|
938
|
+
interface OAuthProviderExtension {
|
|
939
|
+
/**
|
|
940
|
+
* Token grants keyed by absolute-URI `grant_type`. The token endpoint
|
|
941
|
+
* dispatches a matching `grant_type` to the handler, which authenticates the
|
|
942
|
+
* client and issues tokens through the shared `provider`.
|
|
943
|
+
*/
|
|
944
|
+
grants?: Record<string, OAuthExtensionGrantHandler>;
|
|
945
|
+
/**
|
|
946
|
+
* Assertion-based client authentication, keyed by the advertised
|
|
947
|
+
* `token_endpoint_auth_method`. Consumes the matching `client_assertion_type`
|
|
948
|
+
* at the token, introspection, and revocation endpoints. Built-in method
|
|
949
|
+
* names (`client_secret_basic`/`_post`, `private_key_jwt`, `none`) are
|
|
950
|
+
* reserved.
|
|
951
|
+
*/
|
|
952
|
+
clientAuthentication?: Record<string, OAuthClientAuthenticationStrategy>;
|
|
953
|
+
/**
|
|
954
|
+
* Additional discovery metadata fields. Core fields (`issuer`,
|
|
955
|
+
* `token_endpoint`, advertised grants and auth methods, ...) stay owned by
|
|
956
|
+
* the provider; only absent keys are added. To advertise the claim names a
|
|
957
|
+
* claims contributor emits, set `advertisedMetadata.claims_supported`: the
|
|
958
|
+
* provider owns `claims_supported` and does not infer it from contributors.
|
|
959
|
+
*/
|
|
960
|
+
metadata?: (input: OAuthMetadataExtensionInput) => Record<string, unknown>;
|
|
961
|
+
/**
|
|
962
|
+
* Additional claims for access tokens, ID tokens, and the UserInfo response.
|
|
963
|
+
* Strictly additive: a contributor can add new claims but never replace an
|
|
964
|
+
* identity, authentication-context, reserved RFC 9068, or other AS-owned
|
|
965
|
+
* claim. Access-token claims are re-derived at opaque-token introspection, so
|
|
966
|
+
* they must be grant-type-stable (a contributor receives `grantType:
|
|
967
|
+
* undefined` there). See the claim-authority overview in the docs for the
|
|
968
|
+
* full per-token precedence ladder.
|
|
969
|
+
*/
|
|
970
|
+
claims?: {
|
|
971
|
+
accessToken?: (input: OAuthClaimExtensionInput) => Awaitable<Record<string, unknown>>;
|
|
972
|
+
idToken?: (input: OAuthClaimExtensionInput) => Awaitable<Record<string, unknown>>;
|
|
973
|
+
userInfo?: (input: OAuthUserInfoExtensionInput) => Awaitable<Record<string, unknown>>;
|
|
974
|
+
};
|
|
975
|
+
/**
|
|
976
|
+
* Client-id resolution sources consulted by `getClient()`, plus the
|
|
977
|
+
* discovery-metadata fields they advertise. Entries across all extensions
|
|
978
|
+
* run in order; the first to return a client wins. A plugin that resolves
|
|
979
|
+
* clients from an external source (a metadata-document URL, a federated
|
|
980
|
+
* registry, an attestation header) contributes it here.
|
|
981
|
+
*/
|
|
982
|
+
clientDiscovery?: ClientDiscovery | ClientDiscovery[];
|
|
983
|
+
}
|
|
984
|
+
/**
|
|
985
|
+
* Result of authorizing an RFC 7591 initial access token, returned by
|
|
986
|
+
* {@link OAuthOptions.validateInitialAccessToken}.
|
|
987
|
+
*/
|
|
988
|
+
interface InitialAccessTokenAuthorization {
|
|
989
|
+
/**
|
|
990
|
+
* Ownership reference to attach to the created OAuth client.
|
|
991
|
+
*
|
|
992
|
+
* Associates machine-provisioned clients with an organization, team, tenant,
|
|
993
|
+
* or other application-level owner. Omit to create an unowned client (the
|
|
994
|
+
* client is stored with neither a `user_id` nor a `reference_id`).
|
|
995
|
+
*/
|
|
996
|
+
referenceId?: string;
|
|
997
|
+
}
|
|
358
998
|
interface OAuthOptions<Scopes extends readonly Scope[] = InternallySupportedScopes[]> {
|
|
359
999
|
/**
|
|
360
1000
|
* Custom schema definitions
|
|
@@ -373,15 +1013,89 @@ interface OAuthOptions<Scopes extends readonly Scope[] = InternallySupportedScop
|
|
|
373
1013
|
*/
|
|
374
1014
|
scopes?: Scopes;
|
|
375
1015
|
/**
|
|
376
|
-
*
|
|
1016
|
+
* Protected resources the AS issues access tokens for. Promotes the
|
|
1017
|
+
* resource model into a first-class persisted entity with per-resource
|
|
1018
|
+
* token policy.
|
|
1019
|
+
*
|
|
1020
|
+
* - String form: each string becomes an `oauthResource` row using plugin-level
|
|
1021
|
+
* defaults.
|
|
1022
|
+
* - Object form: explicit per-resource policy (TTL, signing alg, scope
|
|
1023
|
+
* allowlist, custom claims, sender-constraint requirements).
|
|
377
1024
|
*
|
|
378
|
-
*
|
|
379
|
-
* @
|
|
380
|
-
*
|
|
381
|
-
*
|
|
1025
|
+
* Seeding is keyed by `identifier`. Behavior on re-seed is controlled by
|
|
1026
|
+
* {@link OAuthOptions.resourceSeedMode}.
|
|
1027
|
+
*
|
|
1028
|
+
* @see RFC 8707 — `identifier` is the `resource` parameter value
|
|
1029
|
+
* @example
|
|
1030
|
+
* ```ts
|
|
1031
|
+
* resources: [
|
|
1032
|
+
* { identifier: "https://api.example.com/admin", accessTokenTtl: 300,
|
|
1033
|
+
* allowedScopes: ["admin:read", "admin:write"] },
|
|
1034
|
+
* "https://api.example.com/public",
|
|
382
1035
|
* ]
|
|
1036
|
+
* ```
|
|
1037
|
+
*/
|
|
1038
|
+
resources?: Array<string | OAuthResourceInput>;
|
|
1039
|
+
/**
|
|
1040
|
+
* Controls whether boot-time `resources` config overwrites DB-edited rows.
|
|
1041
|
+
*
|
|
1042
|
+
* - `"insertOnly"` (default, safe): only inserts rows whose `identifier` is
|
|
1043
|
+
* not already present. Existing rows are untouched — admin edits via CRUD
|
|
1044
|
+
* are never reverted on restart.
|
|
1045
|
+
* - `"merge"`: inserts missing rows; updates only fields present in the
|
|
1046
|
+
* config object for existing rows.
|
|
1047
|
+
* - `"overwrite"`: inserts missing rows; replaces existing rows with the
|
|
1048
|
+
* config values. Use only when the config is the source of truth.
|
|
1049
|
+
*
|
|
1050
|
+
* Defaults to the safe option to prevent accidental policy reverts in
|
|
1051
|
+
* production deployments.
|
|
1052
|
+
*
|
|
1053
|
+
* @default "insertOnly"
|
|
1054
|
+
*/
|
|
1055
|
+
resourceSeedMode?: "insertOnly" | "merge" | "overwrite";
|
|
1056
|
+
/**
|
|
1057
|
+
* Opt-in cache membership for resources by `identifier`. Mirrors the
|
|
1058
|
+
* {@link OAuthOptions.cachedTrustedClients} pattern.
|
|
1059
|
+
*
|
|
1060
|
+
* Cached resources are invalidated on every CRUD write. Resources not in
|
|
1061
|
+
* this set are looked up from the DB on every request — the safe default
|
|
1062
|
+
* when admins edit rows through external tooling.
|
|
1063
|
+
*/
|
|
1064
|
+
cachedResources?: Set<string>;
|
|
1065
|
+
/**
|
|
1066
|
+
* When true, `/oauth2/token` and `/oauth2/authorize` require the client to be
|
|
1067
|
+
* linked to every requested resource via `oauthClientResource`. When false,
|
|
1068
|
+
* clients implicitly have access to all enabled resources.
|
|
1069
|
+
*
|
|
1070
|
+
* Defaults to `true`, enabling per-client validation per RFC 8707 §3. An
|
|
1071
|
+
* explicit `false` keeps all enabled resources requestable by any client.
|
|
1072
|
+
*
|
|
1073
|
+
* The resolved value is logged at plugin init so admins see which default
|
|
1074
|
+
* applied.
|
|
1075
|
+
*/
|
|
1076
|
+
enforcePerClientResources?: boolean;
|
|
1077
|
+
/**
|
|
1078
|
+
* Customize how a resource `identifier` is validated when resources are
|
|
1079
|
+
* created via CRUD or DCR. The default rejects non-URI identifiers per
|
|
1080
|
+
* RFC 8707 §2 (absolute URI, no fragment). Override only for trusted
|
|
1081
|
+
* internal use cases.
|
|
1082
|
+
*
|
|
1083
|
+
* @default RFC 8707 strict URI validator
|
|
1084
|
+
*/
|
|
1085
|
+
identifierValidator?: (identifier: string) => Awaitable<boolean>;
|
|
1086
|
+
/**
|
|
1087
|
+
* RBAC on OAuth resources. Mirrors {@link OAuthOptions.clientPrivileges}.
|
|
1088
|
+
*
|
|
1089
|
+
* Gates the admin resource CRUD endpoints. Return `false` (or `undefined`)
|
|
1090
|
+
* to deny the action.
|
|
383
1091
|
*/
|
|
384
|
-
|
|
1092
|
+
resourcePrivileges?: (context: {
|
|
1093
|
+
headers: Headers;
|
|
1094
|
+
action: "create" | "read" | "update" | "delete" | "list" | "link" | "unlink";
|
|
1095
|
+
user?: User & Record<string, unknown>;
|
|
1096
|
+
session?: Session & Record<string, unknown>;
|
|
1097
|
+
resourceId?: string;
|
|
1098
|
+
}) => Awaitable<boolean | undefined>;
|
|
385
1099
|
/**
|
|
386
1100
|
* Automatically cache trusted clients by client_id.
|
|
387
1101
|
* Clients are cached at request.
|
|
@@ -416,6 +1130,18 @@ interface OAuthOptions<Scopes extends readonly Scope[] = InternallySupportedScop
|
|
|
416
1130
|
* @default 2592000 (30 days)
|
|
417
1131
|
*/
|
|
418
1132
|
refreshTokenExpiresIn?: number;
|
|
1133
|
+
/**
|
|
1134
|
+
* Seconds that a rotated refresh token can be reused to receive the same
|
|
1135
|
+
* token response for the same effective scopes, requested resources, and
|
|
1136
|
+
* sender constraint.
|
|
1137
|
+
*
|
|
1138
|
+
* Matching reuse inside this interval is treated as refresh-response replay,
|
|
1139
|
+
* not refresh-token replay. Set to `0` to treat any rotated refresh token
|
|
1140
|
+
* reuse as replay.
|
|
1141
|
+
*
|
|
1142
|
+
* @default 0
|
|
1143
|
+
*/
|
|
1144
|
+
refreshTokenReuseInterval?: number;
|
|
419
1145
|
/**
|
|
420
1146
|
* The amount of time in seconds that the authorization code is valid for.
|
|
421
1147
|
*
|
|
@@ -453,8 +1179,9 @@ interface OAuthOptions<Scopes extends readonly Scope[] = InternallySupportedScop
|
|
|
453
1179
|
* Allow unauthenticated dynamic client registration.
|
|
454
1180
|
*
|
|
455
1181
|
* When enabled, the `/oauth2/register` endpoint accepts requests
|
|
456
|
-
* without a session
|
|
457
|
-
*
|
|
1182
|
+
* without a session. Public clients use
|
|
1183
|
+
* `token_endpoint_auth_method: "none"`; confidential clients receive a
|
|
1184
|
+
* one-time `client_secret` in the registration response.
|
|
458
1185
|
*
|
|
459
1186
|
* For verified client discovery (MCP), consider installing the
|
|
460
1187
|
* `@better-auth/cimd` plugin, which verifies client identity through
|
|
@@ -464,26 +1191,60 @@ interface OAuthOptions<Scopes extends readonly Scope[] = InternallySupportedScop
|
|
|
464
1191
|
*/
|
|
465
1192
|
allowUnauthenticatedClientRegistration?: boolean;
|
|
466
1193
|
/**
|
|
467
|
-
* Allow dynamic client registration
|
|
1194
|
+
* Allow dynamic client registration (RFC 7591) at `POST /oauth2/register`.
|
|
1195
|
+
*
|
|
1196
|
+
* Once enabled, a registration request is authorized through one of three
|
|
1197
|
+
* modes:
|
|
1198
|
+
* - session-backed: a logged-in user with client-create privileges.
|
|
1199
|
+
* - token-backed: a valid initial access token, when
|
|
1200
|
+
* {@link OAuthOptions.validateInitialAccessToken} is defined.
|
|
1201
|
+
* - open: unauthenticated registration, when
|
|
1202
|
+
* {@link OAuthOptions.allowUnauthenticatedClientRegistration}
|
|
1203
|
+
* is enabled.
|
|
468
1204
|
*
|
|
469
1205
|
* @default false
|
|
470
1206
|
*/
|
|
471
1207
|
allowDynamicClientRegistration?: boolean;
|
|
472
1208
|
/**
|
|
473
|
-
*
|
|
474
|
-
*
|
|
475
|
-
*
|
|
476
|
-
*
|
|
477
|
-
*
|
|
1209
|
+
* Validates an RFC 7591 initial access token for protected dynamic client
|
|
1210
|
+
* registration, read from the `Authorization: Bearer <token>` header on
|
|
1211
|
+
* `POST /oauth2/register`.
|
|
1212
|
+
*
|
|
1213
|
+
* Return an {@link InitialAccessTokenAuthorization} (optionally carrying a
|
|
1214
|
+
* `referenceId` owner) to authorize the registration, or `false` to reject
|
|
1215
|
+
* the token. Defining this callback enables the token-backed registration
|
|
1216
|
+
* mode; while it is undefined, a Bearer token presented to the endpoint is
|
|
1217
|
+
* rejected rather than downgraded to open registration.
|
|
1218
|
+
*
|
|
1219
|
+
* `clientMetadata` is the schema-validated request body. It is self-asserted
|
|
1220
|
+
* (RFC 7591 §5) and not yet semantically validated, so a request authorized
|
|
1221
|
+
* here may still be rejected by a later metadata check. Compare the token in
|
|
1222
|
+
* constant time; issuance, storage, expiration, and revocation are
|
|
1223
|
+
* deployment-specific in RFC 7591 and belong in your application.
|
|
478
1224
|
*
|
|
479
|
-
*
|
|
480
|
-
*
|
|
481
|
-
* `/.well-known/openid-configuration` responses.
|
|
1225
|
+
* `headers` is the raw request `Headers`, available to correlate the token
|
|
1226
|
+
* with other request context (a tenant header, a forwarded client identity).
|
|
482
1227
|
*
|
|
483
|
-
*
|
|
484
|
-
*
|
|
1228
|
+
* With the `bearer` plugin enabled, a Bearer value that resolves to a valid
|
|
1229
|
+
* user session is handled as that session, not as an initial access token.
|
|
1230
|
+
*
|
|
1231
|
+
* @see InitialAccessTokenAuthorization
|
|
485
1232
|
*/
|
|
486
|
-
|
|
1233
|
+
validateInitialAccessToken?: (context: {
|
|
1234
|
+
initialAccessToken: string;
|
|
1235
|
+
headers: Headers;
|
|
1236
|
+
clientMetadata: ClientRegistrationRequest;
|
|
1237
|
+
}) => Awaitable<InitialAccessTokenAuthorization | false>;
|
|
1238
|
+
/**
|
|
1239
|
+
* OAuth/OIDC extension points used by companion plugins to add protocol
|
|
1240
|
+
* grants, client authentication methods, metadata, claims, and client-id
|
|
1241
|
+
* discovery without modifying oauth-provider core for each RFC.
|
|
1242
|
+
*
|
|
1243
|
+
* Extension plugins should prefer `extendOAuthProvider(ctx, extension)` in
|
|
1244
|
+
* their `init()` hook so users can compose plugins declaratively. Plugins
|
|
1245
|
+
* such as `@better-auth/cimd` contribute their client discovery this way.
|
|
1246
|
+
*/
|
|
1247
|
+
extensions?: OAuthProviderExtension[];
|
|
487
1248
|
/**
|
|
488
1249
|
* List of scopes for newly registered clients
|
|
489
1250
|
* if not requested.
|
|
@@ -507,6 +1268,17 @@ interface OAuthOptions<Scopes extends readonly Scope[] = InternallySupportedScop
|
|
|
507
1268
|
* @default - clientRegistrationDefaultScopes
|
|
508
1269
|
*/
|
|
509
1270
|
clientRegistrationAllowedScopes?: Scopes;
|
|
1271
|
+
/**
|
|
1272
|
+
* Whether dynamically registered confidential clients require PKCE by default.
|
|
1273
|
+
*
|
|
1274
|
+
* This is server-owned registration policy. Dynamic client registration does
|
|
1275
|
+
* not accept `require_pkce` from the client request, and public clients or
|
|
1276
|
+
* authorization requests with `offline_access` still require PKCE unless the
|
|
1277
|
+
* confidential OIDC request includes both `openid` and `nonce`.
|
|
1278
|
+
*
|
|
1279
|
+
* @default true
|
|
1280
|
+
*/
|
|
1281
|
+
clientRegistrationRequirePKCE?: boolean;
|
|
510
1282
|
/**
|
|
511
1283
|
* How long a dynamically created confidential client
|
|
512
1284
|
* should last for.
|
|
@@ -592,11 +1364,16 @@ interface OAuthOptions<Scopes extends readonly Scope[] = InternallySupportedScop
|
|
|
592
1364
|
*
|
|
593
1365
|
* - `client_id` - The ID of the client.
|
|
594
1366
|
* - `scope` - The requested scopes.
|
|
1367
|
+
* - `claims` - The OIDC claims request, when the client requested specific
|
|
1368
|
+
* claims. Consent pages should surface `claims.userinfo` names alongside
|
|
1369
|
+
* scopes because accepted UserInfo claims can affect the UserInfo response.
|
|
595
1370
|
* - `code` - The authorization code.
|
|
596
1371
|
*
|
|
597
1372
|
* once the user consents, you need to call the `/oauth2/consent` endpoint
|
|
598
|
-
* with the code and `accept: true` to complete the authorization.
|
|
599
|
-
*
|
|
1373
|
+
* with the code and `accept: true` to complete the authorization. Include a
|
|
1374
|
+
* `claims` object if the user accepted only some requested UserInfo claims.
|
|
1375
|
+
* The endpoint will then return the client to the `redirect_uri` with the
|
|
1376
|
+
* authorization code.
|
|
600
1377
|
*
|
|
601
1378
|
* @example
|
|
602
1379
|
* ```ts
|
|
@@ -790,6 +1567,11 @@ interface OAuthOptions<Scopes extends readonly Scope[] = InternallySupportedScop
|
|
|
790
1567
|
* in the /userinfo request (matches jwt.scopes) */
|
|
791
1568
|
scopes: Scopes; /** The access token payload used in the /userinfo request */
|
|
792
1569
|
jwt: JWTPayload;
|
|
1570
|
+
/**
|
|
1571
|
+
* Claim names explicitly requested through the OIDC `claims.userinfo`
|
|
1572
|
+
* authorization request parameter.
|
|
1573
|
+
*/
|
|
1574
|
+
requestedClaims: string[];
|
|
793
1575
|
}) => Awaitable<Record<string, any>>;
|
|
794
1576
|
/**
|
|
795
1577
|
* Custom claims attached to OIDC id tokens.
|
|
@@ -799,6 +1581,11 @@ interface OAuthOptions<Scopes extends readonly Scope[] = InternallySupportedScop
|
|
|
799
1581
|
* example.com should namespace an organization at
|
|
800
1582
|
* https://example.com/organization.
|
|
801
1583
|
*
|
|
1584
|
+
* Reserved ID token claim names (`iss`, `sub`, `aud`, `exp`, `nbf`, `iat`,
|
|
1585
|
+
* `jti`, `nonce`, `sid`, `at_hash`, `c_hash`, `s_hash`, `auth_time`, `acr`,
|
|
1586
|
+
* `amr`, `azp`) are stripped at issuance with a warning log. The
|
|
1587
|
+
* authorization server owns these values.
|
|
1588
|
+
*
|
|
802
1589
|
* @param info - context that may be useful when creating custom claims
|
|
803
1590
|
*/
|
|
804
1591
|
customIdTokenClaims?: (info: {
|
|
@@ -822,8 +1609,8 @@ interface OAuthOptions<Scopes extends readonly Scope[] = InternallySupportedScop
|
|
|
822
1609
|
customAccessTokenClaims?: (info: {
|
|
823
1610
|
/** The user object if token is associated to a user. Null if user doesn't exist. Undefined if user not applicable. */user?: (User & Record<string, unknown>) | null; /** reference of the consent/authorization */
|
|
824
1611
|
referenceId?: string; /** Scopes granted for this token */
|
|
825
|
-
scopes: Scopes; /** The
|
|
826
|
-
|
|
1612
|
+
scopes: Scopes; /** The resources requested. */
|
|
1613
|
+
resources?: string[]; /** oAuthClient metadata */
|
|
827
1614
|
metadata?: Record<string, any>;
|
|
828
1615
|
}) => Awaitable<Record<string, any>>;
|
|
829
1616
|
/**
|
|
@@ -1066,6 +1853,27 @@ interface OAuthOptions<Scopes extends readonly Scope[] = InternallySupportedScop
|
|
|
1066
1853
|
clientId: string;
|
|
1067
1854
|
ctx: GenericEndpointContext;
|
|
1068
1855
|
}) => Promise<Record<string, string> | null>;
|
|
1856
|
+
/**
|
|
1857
|
+
* DPoP proof validation settings.
|
|
1858
|
+
*
|
|
1859
|
+
* DPoP is enabled by default when a client or resource asks for DPoP-bound
|
|
1860
|
+
* access tokens. These values tune proof validation without changing that
|
|
1861
|
+
* contract.
|
|
1862
|
+
*/
|
|
1863
|
+
dpop?: {
|
|
1864
|
+
/**
|
|
1865
|
+
* Accepted age of a DPoP proof JWT in seconds.
|
|
1866
|
+
*
|
|
1867
|
+
* @default 300
|
|
1868
|
+
*/
|
|
1869
|
+
proofMaxAgeSeconds?: number;
|
|
1870
|
+
/**
|
|
1871
|
+
* Supported JWS algorithms for DPoP proof JWTs.
|
|
1872
|
+
*
|
|
1873
|
+
* @default ["EdDSA", "ES256", "ES512", "PS256", "RS256"]
|
|
1874
|
+
*/
|
|
1875
|
+
signingAlgorithms?: JWSAlgorithms[];
|
|
1876
|
+
};
|
|
1069
1877
|
}
|
|
1070
1878
|
interface OAuthAuthorizationQuery {
|
|
1071
1879
|
/**
|
|
@@ -1074,6 +1882,13 @@ interface OAuthAuthorizationQuery {
|
|
|
1074
1882
|
* Optional in the query when using request_uri (PAR) — resolved from stored params.
|
|
1075
1883
|
*/
|
|
1076
1884
|
response_type?: "code";
|
|
1885
|
+
/**
|
|
1886
|
+
* OpenID Connect Request Object by value.
|
|
1887
|
+
*
|
|
1888
|
+
* The parameter is parsed so unsupported use can be rejected with
|
|
1889
|
+
* `request_not_supported`; Better Auth does not process Request Objects yet.
|
|
1890
|
+
*/
|
|
1891
|
+
request?: string;
|
|
1077
1892
|
/**
|
|
1078
1893
|
* PAR request_uri. When present, other params are resolved from the stored request.
|
|
1079
1894
|
*/
|
|
@@ -1096,10 +1911,12 @@ interface OAuthAuthorizationQuery {
|
|
|
1096
1911
|
* Cross-Site Request Forgery (CSRF, XSRF) mitigation is done by cryptographically binding the
|
|
1097
1912
|
* value of this parameter with a browser cookie.
|
|
1098
1913
|
*
|
|
1914
|
+
* Recommended for clients, but optional for the authorization server.
|
|
1915
|
+
*
|
|
1099
1916
|
* Note: Better Auth stores the state in a database instead of a cookie. - This is to minimize
|
|
1100
1917
|
* the complication with native apps and other clients that may not have access to cookies.
|
|
1101
1918
|
*/
|
|
1102
|
-
state
|
|
1919
|
+
state?: string;
|
|
1103
1920
|
/**
|
|
1104
1921
|
* The client ID. Must be the ID of a registered client.
|
|
1105
1922
|
*/
|
|
@@ -1179,6 +1996,118 @@ interface OAuthAuthorizationQuery {
|
|
|
1179
1996
|
* with the Claim Value being the nonce value sent in the Authentication Request.
|
|
1180
1997
|
*/
|
|
1181
1998
|
nonce?: string;
|
|
1999
|
+
/**
|
|
2000
|
+
* OIDC Claims request parameter. In an authorization request it is a
|
|
2001
|
+
* form-encoded JSON string; Request Object resolvers may provide the parsed
|
|
2002
|
+
* object form.
|
|
2003
|
+
*
|
|
2004
|
+
* @see https://openid.net/specs/openid-connect-core-1_0.html#ClaimsParameter
|
|
2005
|
+
*/
|
|
2006
|
+
claims?: string | Record<string, unknown>;
|
|
2007
|
+
/**
|
|
2008
|
+
* RFC 9449 authorization request parameter. When present, the authorization
|
|
2009
|
+
* code is bound to this JWK thumbprint and the token request must present a
|
|
2010
|
+
* matching DPoP proof.
|
|
2011
|
+
*/
|
|
2012
|
+
dpop_jkt?: string;
|
|
2013
|
+
/**
|
|
2014
|
+
* Resource parameter as specified by [RFC 8707](https://www.rfc-editor.org/rfc/rfc8707.html)
|
|
2015
|
+
*/
|
|
2016
|
+
resource?: string | string[];
|
|
2017
|
+
}
|
|
2018
|
+
/**
|
|
2019
|
+
* A persisted protected-resource row as stored in `oauthResource`.
|
|
2020
|
+
*
|
|
2021
|
+
* `null` on any policy column means "inherit the plugin-level default at
|
|
2022
|
+
* token issuance time" — admins can later override without re-seeding.
|
|
2023
|
+
*/
|
|
2024
|
+
interface OAuthResource {
|
|
2025
|
+
/** Auto-generated primary key */
|
|
2026
|
+
id: string;
|
|
2027
|
+
/**
|
|
2028
|
+
* Business key used in the `aud` claim and as the RFC 8707 `resource` value.
|
|
2029
|
+
*/
|
|
2030
|
+
identifier: string;
|
|
2031
|
+
/** Human-friendly label for admin UIs */
|
|
2032
|
+
name: string;
|
|
2033
|
+
/** Access token TTL in seconds; null inherits {@link OAuthOptions.accessTokenExpiresIn} */
|
|
2034
|
+
accessTokenTtl?: number | null;
|
|
2035
|
+
/** Refresh token TTL in seconds; null inherits {@link OAuthOptions.refreshTokenExpiresIn} */
|
|
2036
|
+
refreshTokenTtl?: number | null;
|
|
2037
|
+
/** When set, overrides the JWT plugin's getLatestKey() default at signing time. */
|
|
2038
|
+
signingAlgorithm?: JWSAlgorithms | null;
|
|
2039
|
+
signingKeyId?: string | null;
|
|
2040
|
+
/**
|
|
2041
|
+
* When non-null, requested scopes must intersect this set or the request is
|
|
2042
|
+
* rejected with `invalid_scope`.
|
|
2043
|
+
*/
|
|
2044
|
+
allowedScopes?: string[] | null;
|
|
2045
|
+
/**
|
|
2046
|
+
* Per-resource claims merged into the access token JWT payload. Reserved
|
|
2047
|
+
* RFC 9068 claim names (`iss`, `sub`, `aud`, `exp`, `iat`, `jti`,
|
|
2048
|
+
* `client_id`, `scope`, `auth_time`, `acr`, `amr`) are stripped at issuance
|
|
2049
|
+
* with a warning log — never silently dropped.
|
|
2050
|
+
*/
|
|
2051
|
+
customClaims?: Record<string, unknown> | null;
|
|
2052
|
+
/**
|
|
2053
|
+
* Require newly issued access tokens for this resource to be DPoP-bound.
|
|
2054
|
+
*/
|
|
2055
|
+
dpopBoundAccessTokensRequired?: boolean;
|
|
2056
|
+
/**
|
|
2057
|
+
* Disabled → no new issuance for this resource; existing tokens still verify
|
|
2058
|
+
* until natural expiry. Compare to delete, which hard-rejects existing tokens.
|
|
2059
|
+
*/
|
|
2060
|
+
disabled: boolean;
|
|
2061
|
+
createdAt: Date;
|
|
2062
|
+
updatedAt: Date;
|
|
2063
|
+
/**
|
|
2064
|
+
* Forward-migration anchor. Lets the runtime branch behavior when claim
|
|
2065
|
+
* emission or validation semantics change in a future PR without forcing
|
|
2066
|
+
* every row to migrate. PR 1 ships with `policyVersion = 1`.
|
|
2067
|
+
*/
|
|
2068
|
+
policyVersion: number;
|
|
2069
|
+
/** Open-ended extension data — not yet promoted to columns. */
|
|
2070
|
+
metadata?: Record<string, unknown> | null;
|
|
2071
|
+
}
|
|
2072
|
+
/**
|
|
2073
|
+
* Plugin-config input for {@link OAuthOptions.resources}. A subset of the
|
|
2074
|
+
* persisted {@link OAuthResource} — only `identifier` is required; the rest
|
|
2075
|
+
* fall back to plugin defaults when omitted.
|
|
2076
|
+
*/
|
|
2077
|
+
interface OAuthResourceInput {
|
|
2078
|
+
identifier: string;
|
|
2079
|
+
name?: string;
|
|
2080
|
+
accessTokenTtl?: number;
|
|
2081
|
+
refreshTokenTtl?: number;
|
|
2082
|
+
signingAlgorithm?: JWSAlgorithms;
|
|
2083
|
+
signingKeyId?: string;
|
|
2084
|
+
allowedScopes?: string[];
|
|
2085
|
+
customClaims?: Record<string, unknown>;
|
|
2086
|
+
dpopBoundAccessTokensRequired?: boolean;
|
|
2087
|
+
disabled?: boolean;
|
|
2088
|
+
metadata?: Record<string, unknown>;
|
|
2089
|
+
}
|
|
2090
|
+
/**
|
|
2091
|
+
* A row of `oauthClientResource` linking a client to a resource.
|
|
2092
|
+
*
|
|
2093
|
+
* Authoritative only when {@link OAuthOptions.enforcePerClientResources} is true.
|
|
2094
|
+
*/
|
|
2095
|
+
interface OAuthClientResource {
|
|
2096
|
+
clientId: string;
|
|
2097
|
+
resourceId: string;
|
|
2098
|
+
metadata?: Record<string, unknown> | null;
|
|
2099
|
+
createdAt: Date;
|
|
2100
|
+
}
|
|
2101
|
+
/**
|
|
2102
|
+
* The authorization request as persisted alongside a minted code. Identical to
|
|
2103
|
+
* {@link OAuthAuthorizationQuery} except `redirect_uri` is optional: a headless
|
|
2104
|
+
* authorization request (first-party-apps / device-style) carries none, and
|
|
2105
|
+
* RFC 6749 §4.1.3 only binds `redirect_uri` at the token endpoint when the
|
|
2106
|
+
* authorization request included one. Mirrors the runtime
|
|
2107
|
+
* `storedAuthorizationQuerySchema`.
|
|
2108
|
+
*/
|
|
2109
|
+
interface StoredAuthorizationQuery extends Omit<OAuthAuthorizationQuery, "redirect_uri"> {
|
|
2110
|
+
redirect_uri?: string;
|
|
1182
2111
|
}
|
|
1183
2112
|
/**
|
|
1184
2113
|
* Stored within the verification.value field
|
|
@@ -1189,9 +2118,10 @@ interface OAuthAuthorizationQuery {
|
|
|
1189
2118
|
*/
|
|
1190
2119
|
interface VerificationValue {
|
|
1191
2120
|
type: "authorization_code";
|
|
1192
|
-
query:
|
|
2121
|
+
query: StoredAuthorizationQuery;
|
|
1193
2122
|
sessionId: string;
|
|
1194
2123
|
userId: string;
|
|
2124
|
+
resource?: string[];
|
|
1195
2125
|
referenceId?: string;
|
|
1196
2126
|
authTime?: number;
|
|
1197
2127
|
}
|
|
@@ -1260,10 +2190,26 @@ interface SchemaClient<Scopes extends readonly Scope[] = InternallySupportedScop
|
|
|
1260
2190
|
* For example, `https://example.com/logout/callback`
|
|
1261
2191
|
*/
|
|
1262
2192
|
postLogoutRedirectUris?: string[];
|
|
1263
|
-
|
|
2193
|
+
/**
|
|
2194
|
+
* RP URL that will receive a signed Logout Token when the end-user's OP
|
|
2195
|
+
* session ends. Registering it is the per-client opt-in for back-channel
|
|
2196
|
+
* logout. Must be absolute, without a fragment, and HTTPS for confidential
|
|
2197
|
+
* clients.
|
|
2198
|
+
*
|
|
2199
|
+
* @see https://openid.net/specs/openid-connect-backchannel-1_0.html#RPMetadata
|
|
2200
|
+
*/
|
|
2201
|
+
backchannelLogoutUri?: string;
|
|
2202
|
+
/**
|
|
2203
|
+
* When true, the RP requires the `sid` claim in every Logout Token.
|
|
2204
|
+
* User-scoped (sid-less) logouts are not dispatched to such a client.
|
|
2205
|
+
*
|
|
2206
|
+
* @default false
|
|
2207
|
+
*/
|
|
2208
|
+
backchannelLogoutSessionRequired?: boolean;
|
|
2209
|
+
tokenEndpointAuthMethod?: TokenEndpointAuthMethod;
|
|
1264
2210
|
grantTypes?: GrantType[];
|
|
1265
2211
|
responseTypes?: "code"[];
|
|
1266
|
-
/** Client's JSON Web Key Set
|
|
2212
|
+
/** Client's JSON Web Key Set metadata. Mutually exclusive with `jwksUri`. */
|
|
1267
2213
|
jwks?: string;
|
|
1268
2214
|
/** URI for the client's JSON Web Key Set. Mutually exclusive with `jwks`. Must be HTTPS. */
|
|
1269
2215
|
jwksUri?: string;
|
|
@@ -1298,6 +2244,11 @@ interface SchemaClient<Scopes extends readonly Scope[] = InternallySupportedScop
|
|
|
1298
2244
|
* requesting offline_access scope, regardless of this setting.
|
|
1299
2245
|
*/
|
|
1300
2246
|
requirePKCE?: boolean;
|
|
2247
|
+
/**
|
|
2248
|
+
* RFC 9449 dynamic client metadata. When true, every token request from this
|
|
2249
|
+
* client must include a valid DPoP proof and receive DPoP-bound tokens.
|
|
2250
|
+
*/
|
|
2251
|
+
dpopBoundAccessTokens?: boolean;
|
|
1301
2252
|
/** Used to indicate if consent screen can be skipped */
|
|
1302
2253
|
skipConsent?: boolean;
|
|
1303
2254
|
/** Used to enable client to logout via the `/oauth2/end-session` endpoint */
|
|
@@ -1341,6 +2292,11 @@ interface OAuthOpaqueAccessToken<Scopes extends readonly Scope[] = InternallySup
|
|
|
1341
2292
|
* where no user is involved.
|
|
1342
2293
|
*/
|
|
1343
2294
|
referenceId?: string;
|
|
2295
|
+
/**
|
|
2296
|
+
* Stored authorization-code identifier that produced this token family.
|
|
2297
|
+
* Used to revoke tokens after authorization-code replay is detected.
|
|
2298
|
+
*/
|
|
2299
|
+
authorizationCodeId?: string;
|
|
1344
2300
|
/**
|
|
1345
2301
|
* The refresh token the access token is associated with.
|
|
1346
2302
|
*
|
|
@@ -1351,28 +2307,65 @@ interface OAuthOpaqueAccessToken<Scopes extends readonly Scope[] = InternallySup
|
|
|
1351
2307
|
expiresAt: Date;
|
|
1352
2308
|
/** The creation date of the access token. */
|
|
1353
2309
|
createdAt: Date;
|
|
2310
|
+
/**
|
|
2311
|
+
* When the access token was revoked. Set by session-end dispatch, the
|
|
2312
|
+
* revoke endpoint, and back-channel logout. Introspection and protected
|
|
2313
|
+
* endpoints MUST treat a revoked token as inactive.
|
|
2314
|
+
*/
|
|
2315
|
+
revoked?: Date | null;
|
|
1354
2316
|
/**
|
|
1355
2317
|
* Scope granted for the access token.
|
|
1356
2318
|
*
|
|
1357
2319
|
* Shall match the refreshId.scopes if refreshId is provided.
|
|
1358
2320
|
*/
|
|
1359
2321
|
scopes: Scopes;
|
|
2322
|
+
/**
|
|
2323
|
+
* Resources allowed for this access token.
|
|
2324
|
+
*/
|
|
2325
|
+
resources?: string[];
|
|
2326
|
+
/**
|
|
2327
|
+
* OIDC UserInfo claim names requested by the authorization request's
|
|
2328
|
+
* `claims.userinfo` object.
|
|
2329
|
+
*/
|
|
2330
|
+
requestedUserInfoClaims?: string[];
|
|
2331
|
+
/**
|
|
2332
|
+
* RFC 7800 `cnf` confirmation that sender-constrains this access token (for
|
|
2333
|
+
* example DPoP `{ jkt }`). Surfaced as the `cnf` claim at introspection.
|
|
2334
|
+
*/
|
|
2335
|
+
confirmation?: Confirmation;
|
|
1360
2336
|
}
|
|
1361
2337
|
/**
|
|
1362
2338
|
* Refresh Token Database Schema
|
|
1363
2339
|
*/
|
|
1364
2340
|
interface OAuthRefreshToken<Scopes extends readonly Scope[] = InternallySupportedScopes[]> {
|
|
1365
2341
|
token: string;
|
|
1366
|
-
sessionId
|
|
2342
|
+
sessionId?: string;
|
|
1367
2343
|
userId: string;
|
|
1368
2344
|
referenceId?: string;
|
|
2345
|
+
authorizationCodeId?: string;
|
|
1369
2346
|
clientId?: string;
|
|
1370
2347
|
expiresAt: Date;
|
|
1371
2348
|
createdAt: Date;
|
|
1372
2349
|
/**
|
|
1373
|
-
* When
|
|
2350
|
+
* When this token stopped being active.
|
|
2351
|
+
*
|
|
2352
|
+
* A token can be revoked by /oauth2/revoke or consumed by rotation. Use
|
|
2353
|
+
* `rotatedAt` to distinguish rotation from explicit revocation.
|
|
1374
2354
|
*/
|
|
1375
2355
|
revoked?: Date;
|
|
2356
|
+
/**
|
|
2357
|
+
* When this refresh token was consumed by rotation.
|
|
2358
|
+
*/
|
|
2359
|
+
rotatedAt?: Date;
|
|
2360
|
+
/**
|
|
2361
|
+
* Encrypted token endpoint response and request fingerprint to replay during
|
|
2362
|
+
* the configured refresh-token reuse interval.
|
|
2363
|
+
*/
|
|
2364
|
+
rotationReplayResponse?: string;
|
|
2365
|
+
/**
|
|
2366
|
+
* When the cached rotation response stops being replayable.
|
|
2367
|
+
*/
|
|
2368
|
+
rotationReplayExpiresAt?: Date;
|
|
1376
2369
|
/**
|
|
1377
2370
|
* The time the user originally authenticated.
|
|
1378
2371
|
* Persisted so refreshed ID tokens can include a correct `auth_time` claim.
|
|
@@ -1384,6 +2377,20 @@ interface OAuthRefreshToken<Scopes extends readonly Scope[] = InternallySupporte
|
|
|
1384
2377
|
* Considered Immutable once granted.
|
|
1385
2378
|
*/
|
|
1386
2379
|
scopes: Scopes;
|
|
2380
|
+
/**
|
|
2381
|
+
* Resources allowed for this refresh token
|
|
2382
|
+
*/
|
|
2383
|
+
resources?: string[];
|
|
2384
|
+
/**
|
|
2385
|
+
* OIDC UserInfo claim names requested by the authorization request's
|
|
2386
|
+
* `claims.userinfo` object. Carried forward on rotation.
|
|
2387
|
+
*/
|
|
2388
|
+
requestedUserInfoClaims?: string[];
|
|
2389
|
+
/**
|
|
2390
|
+
* RFC 7800 `cnf` confirmation that sender-constrains this refresh-token
|
|
2391
|
+
* family (for example DPoP `{ jkt }`). Carried forward on rotation.
|
|
2392
|
+
*/
|
|
2393
|
+
confirmation?: Confirmation;
|
|
1387
2394
|
}
|
|
1388
2395
|
/**
|
|
1389
2396
|
* Consent Database Schema
|
|
@@ -1392,7 +2399,13 @@ type OAuthConsent<Scopes extends readonly Scope[] = InternallySupportedScopes[]>
|
|
|
1392
2399
|
id: string;
|
|
1393
2400
|
clientId: string;
|
|
1394
2401
|
userId: string;
|
|
2402
|
+
resources?: string[];
|
|
1395
2403
|
referenceId?: string;
|
|
2404
|
+
/**
|
|
2405
|
+
* OIDC UserInfo claim names consented from the authorization request's
|
|
2406
|
+
* `claims.userinfo` object.
|
|
2407
|
+
*/
|
|
2408
|
+
requestedUserInfoClaims?: string[];
|
|
1396
2409
|
scopes: Scopes;
|
|
1397
2410
|
createdAt: Date;
|
|
1398
2411
|
updatedAt: Date;
|
|
@@ -1402,10 +2415,30 @@ type OAuthConsent<Scopes extends readonly Scope[] = InternallySupportedScopes[]>
|
|
|
1402
2415
|
/**
|
|
1403
2416
|
* Supported grant types of the token endpoint
|
|
1404
2417
|
*/
|
|
1405
|
-
type
|
|
1406
|
-
type
|
|
2418
|
+
type BuiltInGrantType = "authorization_code" | "client_credentials" | "refresh_token";
|
|
2419
|
+
type GrantType = BuiltInGrantType | (string & {});
|
|
2420
|
+
type BuiltInAuthMethod = "client_secret_basic" | "client_secret_post" | "private_key_jwt";
|
|
2421
|
+
type AuthMethod = BuiltInAuthMethod | (string & {});
|
|
1407
2422
|
type TokenEndpointAuthMethod = AuthMethod | "none";
|
|
1408
2423
|
type BearerMethodsSupported = "header" | "body";
|
|
2424
|
+
/**
|
|
2425
|
+
* RFC 7800 `cnf` (confirmation) members that sender-constrain an access token to
|
|
2426
|
+
* a key the client must prove possession of. Each binding mechanism populates
|
|
2427
|
+
* one member of the same object: DPoP sets `jkt` (RFC 9449 §6), mTLS sets
|
|
2428
|
+
* `x5t#S256` (RFC 8705 §3.1). The authorization server is the sole authority
|
|
2429
|
+
* over this value; it is token material, never a contributed claim.
|
|
2430
|
+
*/
|
|
2431
|
+
type Confirmation = {
|
|
2432
|
+
jkt: string;
|
|
2433
|
+
} | {
|
|
2434
|
+
"x5t#S256": string;
|
|
2435
|
+
};
|
|
2436
|
+
/**
|
|
2437
|
+
* Token presentation scheme returned in `token_type`. A DPoP-bound token uses
|
|
2438
|
+
* `"DPoP"` (RFC 9449 §5); everything else (including mTLS-bound) uses
|
|
2439
|
+
* `"Bearer"`, since the mTLS constraint lives at the TLS layer.
|
|
2440
|
+
*/
|
|
2441
|
+
type TokenType = "Bearer" | "DPoP";
|
|
1409
2442
|
/**
|
|
1410
2443
|
* Metadata for authentication servers.
|
|
1411
2444
|
*
|
|
@@ -1445,9 +2478,11 @@ interface AuthServerMetadata {
|
|
|
1445
2478
|
/**
|
|
1446
2479
|
* The URL of the dynamic client registration endpoint.
|
|
1447
2480
|
*
|
|
2481
|
+
* This field is only present when `allowDynamicClientRegistration` is enabled.
|
|
2482
|
+
*
|
|
1448
2483
|
* @default `/oauth2/register`
|
|
1449
2484
|
*/
|
|
1450
|
-
registration_endpoint
|
|
2485
|
+
registration_endpoint?: string;
|
|
1451
2486
|
/**
|
|
1452
2487
|
* Supported scopes.
|
|
1453
2488
|
*/
|
|
@@ -1480,7 +2515,7 @@ interface AuthServerMetadata {
|
|
|
1480
2515
|
* token endpoint for the "private_key_jwt" and "client_secret_jwt"
|
|
1481
2516
|
* authentication methods (see field token_endpoint_auth_methods_supported).
|
|
1482
2517
|
*/
|
|
1483
|
-
token_endpoint_auth_signing_alg_values_supported?:
|
|
2518
|
+
token_endpoint_auth_signing_alg_values_supported?: PrivateKeyJwtSigningAlgorithm[];
|
|
1484
2519
|
/**
|
|
1485
2520
|
* URL of a page containing human-readable information
|
|
1486
2521
|
* that developers might want or need to know when using the
|
|
@@ -1518,7 +2553,7 @@ interface AuthServerMetadata {
|
|
|
1518
2553
|
* @default
|
|
1519
2554
|
* ["client_secret_basic", "client_secret_post"]
|
|
1520
2555
|
*/
|
|
1521
|
-
revocation_endpoint_auth_methods_supported?:
|
|
2556
|
+
revocation_endpoint_auth_methods_supported?: TokenEndpointAuthMethod[];
|
|
1522
2557
|
/**
|
|
1523
2558
|
* Array containing a list of the JWS signing
|
|
1524
2559
|
* algorithms ("alg" values) supported by the revocation endpoint for
|
|
@@ -1526,7 +2561,7 @@ interface AuthServerMetadata {
|
|
|
1526
2561
|
* token endpoint for the "private_key_jwt" and "client_secret_jwt"
|
|
1527
2562
|
* authentication methods (see field revocation_endpoint_auth_methods_supported).
|
|
1528
2563
|
*/
|
|
1529
|
-
revocation_endpoint_auth_signing_alg_values_supported?:
|
|
2564
|
+
revocation_endpoint_auth_signing_alg_values_supported?: PrivateKeyJwtSigningAlgorithm[];
|
|
1530
2565
|
/**
|
|
1531
2566
|
* URL of the authorization server's OAuth 2.0
|
|
1532
2567
|
* introspection endpoint [RFC7662](https://datatracker.ietf.org/doc/html/rfc7662)
|
|
@@ -1539,7 +2574,7 @@ interface AuthServerMetadata {
|
|
|
1539
2574
|
* @default
|
|
1540
2575
|
* ["client_secret_basic", "client_secret_post"]
|
|
1541
2576
|
*/
|
|
1542
|
-
introspection_endpoint_auth_methods_supported?:
|
|
2577
|
+
introspection_endpoint_auth_methods_supported?: TokenEndpointAuthMethod[];
|
|
1543
2578
|
/**
|
|
1544
2579
|
* Array containing a list of the JWS signing
|
|
1545
2580
|
* algorithms ("alg" values) supported by the introspection endpoint
|
|
@@ -1547,7 +2582,7 @@ interface AuthServerMetadata {
|
|
|
1547
2582
|
* the "private_key_jwt" and "client_secret_jwt" authentication methods
|
|
1548
2583
|
* (see field introspection_endpoint_auth_methods_supported).
|
|
1549
2584
|
*/
|
|
1550
|
-
introspection_endpoint_auth_signing_alg_values_supported?:
|
|
2585
|
+
introspection_endpoint_auth_signing_alg_values_supported?: PrivateKeyJwtSigningAlgorithm[];
|
|
1551
2586
|
/**
|
|
1552
2587
|
* Supported code challenge methods.
|
|
1553
2588
|
*
|
|
@@ -1573,6 +2608,34 @@ interface AuthServerMetadata {
|
|
|
1573
2608
|
* it on its own.
|
|
1574
2609
|
*/
|
|
1575
2610
|
client_id_metadata_document_supported?: boolean;
|
|
2611
|
+
/**
|
|
2612
|
+
* Boolean value specifying whether the OP supports back-channel logout,
|
|
2613
|
+
* with true indicating support.
|
|
2614
|
+
*
|
|
2615
|
+
* Registered in the "OAuth Authorization Server Metadata" IANA registry
|
|
2616
|
+
* under OpenID Connect Back-Channel Logout 1.0, so this may appear at both
|
|
2617
|
+
* `.well-known/oauth-authorization-server` and `.well-known/openid-configuration`.
|
|
2618
|
+
*
|
|
2619
|
+
* @default false
|
|
2620
|
+
* @see https://openid.net/specs/openid-connect-backchannel-1_0.html#OPMetadata
|
|
2621
|
+
*/
|
|
2622
|
+
backchannel_logout_supported?: boolean;
|
|
2623
|
+
/**
|
|
2624
|
+
* Boolean value specifying whether the OP can pass a `sid` (session ID)
|
|
2625
|
+
* Claim in the Logout Token to identify the RP session with the OP.
|
|
2626
|
+
*
|
|
2627
|
+
* When true, the OP also includes `sid` in ID Tokens it issues.
|
|
2628
|
+
*
|
|
2629
|
+
* @default false
|
|
2630
|
+
* @see https://openid.net/specs/openid-connect-backchannel-1_0.html#OPMetadata
|
|
2631
|
+
*/
|
|
2632
|
+
backchannel_logout_session_supported?: boolean;
|
|
2633
|
+
/**
|
|
2634
|
+
* JWS algorithms supported for RFC 9449 DPoP proof JWTs.
|
|
2635
|
+
*
|
|
2636
|
+
* @see https://datatracker.ietf.org/doc/html/rfc9449
|
|
2637
|
+
*/
|
|
2638
|
+
dpop_signing_alg_values_supported?: JWSAlgorithms[];
|
|
1576
2639
|
}
|
|
1577
2640
|
/**
|
|
1578
2641
|
* Metadata returned by the openid-configuration endpoint:
|
|
@@ -1591,19 +2654,16 @@ interface OIDCMetadata extends AuthServerMetadata {
|
|
|
1591
2654
|
*/
|
|
1592
2655
|
userinfo_endpoint: string;
|
|
1593
2656
|
/**
|
|
1594
|
-
*
|
|
1595
|
-
*
|
|
1596
|
-
* - `urn:mace:incommon:iap:silver`: Silver level of assurance
|
|
1597
|
-
* - `urn:mace:incommon:iap:bronze`: Bronze level of assurance
|
|
2657
|
+
* Authentication Context Class Reference values supported.
|
|
1598
2658
|
*
|
|
1599
|
-
*
|
|
1600
|
-
*
|
|
2659
|
+
* Better Auth does not advertise this field by default because it does not
|
|
2660
|
+
* currently evaluate requested Authentication Context Class References.
|
|
1601
2661
|
*
|
|
1602
2662
|
* @default
|
|
1603
|
-
*
|
|
1604
|
-
* @see https://
|
|
2663
|
+
* undefined
|
|
2664
|
+
* @see https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata
|
|
1605
2665
|
*/
|
|
1606
|
-
acr_values_supported
|
|
2666
|
+
acr_values_supported?: string[];
|
|
1607
2667
|
/**
|
|
1608
2668
|
* Supported subject types.
|
|
1609
2669
|
*
|
|
@@ -1631,12 +2691,36 @@ interface OIDCMetadata extends AuthServerMetadata {
|
|
|
1631
2691
|
* ["sub", "iss", "aud", "exp", "nbf", "iat", "jti", "email", "email_verified", "name", "family_name", "given_name", "sid", "scope", "azp"]
|
|
1632
2692
|
*/
|
|
1633
2693
|
claims_supported: string[];
|
|
2694
|
+
/**
|
|
2695
|
+
* Whether the OP supports the OIDC `claims` request parameter.
|
|
2696
|
+
*
|
|
2697
|
+
* @default true
|
|
2698
|
+
* @see https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata
|
|
2699
|
+
*/
|
|
2700
|
+
claims_parameter_supported?: boolean;
|
|
1634
2701
|
/**
|
|
1635
2702
|
* RP-Initiated Logout Endpoint
|
|
1636
2703
|
*
|
|
1637
2704
|
* @see https://openid.net/specs/openid-connect-rpinitiated-1_0.html
|
|
1638
2705
|
*/
|
|
1639
2706
|
end_session_endpoint: string;
|
|
2707
|
+
/**
|
|
2708
|
+
* Whether the OP supports OpenID Connect Request Objects by value.
|
|
2709
|
+
*
|
|
2710
|
+
* @default false
|
|
2711
|
+
* @see https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata
|
|
2712
|
+
*/
|
|
2713
|
+
request_parameter_supported?: boolean;
|
|
2714
|
+
/**
|
|
2715
|
+
* Whether the OP supports OpenID Connect Request Objects by reference.
|
|
2716
|
+
*
|
|
2717
|
+
* Discovery defaults this field to true when omitted, so providers that do
|
|
2718
|
+
* not support it should advertise false explicitly.
|
|
2719
|
+
*
|
|
2720
|
+
* @default false
|
|
2721
|
+
* @see https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata
|
|
2722
|
+
*/
|
|
2723
|
+
request_uri_parameter_supported?: boolean;
|
|
1640
2724
|
/**
|
|
1641
2725
|
* Prompt values supported by this OIDC server
|
|
1642
2726
|
*
|
|
@@ -1675,7 +2759,23 @@ interface OAuthClient {
|
|
|
1675
2759
|
software_statement?: string;
|
|
1676
2760
|
redirect_uris: string[];
|
|
1677
2761
|
post_logout_redirect_uris?: string[];
|
|
1678
|
-
|
|
2762
|
+
/**
|
|
2763
|
+
* RP URL that the OP POSTs a signed Logout Token to when a session at the OP
|
|
2764
|
+
* ends. The RP uses the token to terminate its own session state for that
|
|
2765
|
+
* user (including any access tokens it has bound to the session).
|
|
2766
|
+
*
|
|
2767
|
+
* @see https://openid.net/specs/openid-connect-backchannel-1_0.html#RPMetadata
|
|
2768
|
+
*/
|
|
2769
|
+
backchannel_logout_uri?: string;
|
|
2770
|
+
/**
|
|
2771
|
+
* When true, the RP requires the `sid` Claim in every Logout Token it
|
|
2772
|
+
* receives; the OP will not dispatch user-scoped (sid-less) logouts to it.
|
|
2773
|
+
*
|
|
2774
|
+
* @default false
|
|
2775
|
+
* @see https://openid.net/specs/openid-connect-backchannel-1_0.html#RPMetadata
|
|
2776
|
+
*/
|
|
2777
|
+
backchannel_logout_session_required?: boolean;
|
|
2778
|
+
token_endpoint_auth_method?: TokenEndpointAuthMethod;
|
|
1679
2779
|
grant_types?: GrantType[];
|
|
1680
2780
|
response_types?: "code"[];
|
|
1681
2781
|
public?: boolean;
|
|
@@ -1688,10 +2788,17 @@ interface OAuthClient {
|
|
|
1688
2788
|
*
|
|
1689
2789
|
* @default true
|
|
1690
2790
|
*
|
|
1691
|
-
* Note: PKCE is always required for public clients
|
|
1692
|
-
*
|
|
2791
|
+
* Note: PKCE is always required for public clients. When requesting
|
|
2792
|
+
* offline_access without PKCE, confidential OIDC clients must send both
|
|
2793
|
+
* `openid` and `nonce`.
|
|
1693
2794
|
*/
|
|
1694
2795
|
require_pkce?: boolean;
|
|
2796
|
+
/**
|
|
2797
|
+
* RFC 9449 dynamic client metadata. When true, token requests from this
|
|
2798
|
+
* client must include a valid DPoP proof and receive DPoP-bound access
|
|
2799
|
+
* tokens.
|
|
2800
|
+
*/
|
|
2801
|
+
dpop_bound_access_tokens?: boolean;
|
|
1695
2802
|
/**
|
|
1696
2803
|
* Subject identifier type for this client.
|
|
1697
2804
|
*
|
|
@@ -1739,4 +2846,4 @@ interface ResourceServerMetadata {
|
|
|
1739
2846
|
dpop_bound_access_tokens_required?: boolean;
|
|
1740
2847
|
}
|
|
1741
2848
|
//#endregion
|
|
1742
|
-
export {
|
|
2849
|
+
export { OAuthProviderExtension as A, StoreTokenType as B, OAuthConsent as C, OAuthOpaqueAccessToken as D, OAuthMetadataExtensionInput as E, OAuthTokenResponse as F, VerificationValue as H, OAuthUserInfoExtensionInput as I, Prompt as L, OAuthResource as M, OAuthResourceInput as N, OAuthOptions as O, OAuthTokenIssueParams as P, SchemaClient as R, OAuthClientResource as S, OAuthExtensionGrantHandlerInput as T, ClientRegistrationRequest as U, StoredAuthorizationQuery as V, ResourceUriSchema as W, OAuthClaimExtensionInput as _, GrantType as a, OAuthClientAuthenticationResult as b, ResourceServerMetadata as c, ActiveAccessTokenPayload as d, AuthorizePrompt as f, OAuthAuthorizationQuery as g, OAuthAuthenticatedClient as h, Confirmation as i, OAuthRefreshToken as j, OAuthProviderApi as k, TokenEndpointAuthMethod as l, InitialAccessTokenAuthorization as m, AuthServerMetadata as n, OAuthClient as o, ClientDiscovery as p, BearerMethodsSupported as r, OIDCMetadata as s, AuthMethod as t, TokenType as u, OAuthClientAuthenticationInput as v, OAuthExtensionGrantHandler as w, OAuthClientAuthenticationStrategy as x, OAuthClientAuthenticationRequest as y, Scope as z };
|