@better-auth/oauth-provider 1.7.9 → 1.8.0-beta.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.
@@ -1,10 +1,49 @@
1
1
  import * as z from "zod";
2
2
  import { PrivateKeyJwtSigningAlgorithm } from "@better-auth/core/oauth2";
3
- import { JWTPayload } from "jose";
4
3
  import { JWSAlgorithms } from "better-auth/plugins";
4
+ import { JWTPayload } from "jose";
5
5
  import { InferOptionSchema, Session, User } from "better-auth/types";
6
6
  import { GenericEndpointContext, LiteralString } from "@better-auth/core";
7
7
 
8
+ //#region src/register.d.ts
9
+ type OAuthClientRegistrationMetadata = Omit<OAuthClient, "client_id" | "redirect_uris" | "client_secret_expires_at"> & {
10
+ client_id?: string;
11
+ redirect_uris?: string[];
12
+ client_secret_expires_at?: number | string;
13
+ metadata?: Record<string, unknown>;
14
+ resources?: string[];
15
+ };
16
+ /**
17
+ * Rejects a URI the server will POST to unless it is an absolute https URL
18
+ * with no fragment or credentials on a publicly routable host. Back-channel
19
+ * endpoints use it as an SSRF guard, since the server, not the browser, calls
20
+ * them.
21
+ */
22
+ declare function assertPublicRoutableHttpsUri(field: string, uri: string): void;
23
+ interface OAuthClientRegistrationResult {
24
+ client: SchemaClient<Scope[]>;
25
+ clientSecret?: string;
26
+ resources: string[];
27
+ created: boolean;
28
+ }
29
+ interface RegisterClientMetadataDocumentInput {
30
+ metadata: OAuthClient;
31
+ clientId: string;
32
+ clientDiscoveryId: string;
33
+ existingClient?: SchemaClient<Scope[]>;
34
+ }
35
+ /**
36
+ * First-party persistence seam for a validated Client ID Metadata Document.
37
+ *
38
+ * This operation owns both initial creation and atomic replacement. It never
39
+ * generates a client secret, preserves operator-controlled flags on
40
+ * replacement, and ensures server-default resource links in the same
41
+ * transaction.
42
+ *
43
+ * @internal
44
+ */
45
+ declare function registerClientMetadataDocument(ctx: GenericEndpointContext, opts: OAuthOptions<Scope[]>, input: RegisterClientMetadataDocumentInput): Promise<OAuthClientRegistrationResult>;
46
+ //#endregion
8
47
  //#region src/schema.d.ts
9
48
  declare const schema: {
10
49
  oauthClient: {
@@ -40,6 +79,10 @@ declare const schema: {
40
79
  type: "string";
41
80
  required: false;
42
81
  };
82
+ sectorIdentifier: {
83
+ type: "string";
84
+ required: false;
85
+ };
43
86
  scopes: {
44
87
  type: "string[]";
45
88
  required: false;
@@ -118,6 +161,14 @@ declare const schema: {
118
161
  type: "boolean";
119
162
  required: false;
120
163
  };
164
+ frontchannelLogoutUri: {
165
+ type: "string";
166
+ required: false;
167
+ };
168
+ frontchannelLogoutSessionRequired: {
169
+ type: "boolean";
170
+ required: false;
171
+ };
121
172
  tokenEndpointAuthMethod: {
122
173
  type: "string";
123
174
  required: false;
@@ -371,6 +422,14 @@ declare const schema: {
371
422
  type: "date";
372
423
  required: false;
373
424
  };
425
+ acr: {
426
+ type: "string";
427
+ required: false;
428
+ };
429
+ amr: {
430
+ type: "string[]";
431
+ required: false;
432
+ };
374
433
  confirmation: {
375
434
  type: "json";
376
435
  required: false;
@@ -582,6 +641,8 @@ declare const clientRegistrationRequestSchema: z.ZodObject<{
582
641
  post_logout_redirect_uris: z.ZodOptional<z.ZodArray<z.ZodURL>>;
583
642
  backchannel_logout_uri: z.ZodOptional<z.ZodURL>;
584
643
  backchannel_logout_session_required: z.ZodOptional<z.ZodBoolean>;
644
+ frontchannel_logout_uri: z.ZodOptional<z.ZodURL>;
645
+ frontchannel_logout_session_required: z.ZodOptional<z.ZodBoolean>;
585
646
  token_endpoint_auth_method: z.ZodOptional<z.ZodString>;
586
647
  jwks: z.ZodOptional<z.ZodObject<{
587
648
  keys: z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
@@ -614,26 +675,27 @@ declare const clientRegistrationRequestSchema: z.ZodObject<{
614
675
  * unknown extension without unsafe casts or ad-hoc allowlists.
615
676
  */
616
677
  declare const oauthClientMetadataSchema: z.ZodObject<{
617
- contacts: z.ZodOptional<z.ZodArray<z.ZodString>>;
618
678
  jwks: z.ZodOptional<z.ZodObject<{
619
679
  keys: z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
620
680
  }, z.core.$strip>>;
621
- resources: z.ZodOptional<z.ZodArray<z.ZodString>>;
681
+ contacts: z.ZodOptional<z.ZodArray<z.ZodString>>;
622
682
  scope: z.ZodOptional<z.ZodString>;
623
- redirect_uris: z.ZodOptional<z.ZodArray<z.ZodURL>>;
624
683
  client_name: z.ZodOptional<z.ZodString>;
625
684
  client_uri: z.ZodOptional<z.ZodString>;
626
685
  logo_uri: z.ZodOptional<z.ZodString>;
627
686
  tos_uri: z.ZodOptional<z.ZodString>;
628
687
  policy_uri: z.ZodOptional<z.ZodString>;
688
+ jwks_uri: z.ZodOptional<z.ZodString>;
629
689
  software_id: z.ZodOptional<z.ZodString>;
630
690
  software_version: z.ZodOptional<z.ZodString>;
631
691
  software_statement: z.ZodOptional<z.ZodString>;
692
+ redirect_uris: z.ZodOptional<z.ZodArray<z.ZodURL>>;
632
693
  post_logout_redirect_uris: z.ZodOptional<z.ZodArray<z.ZodURL>>;
633
694
  backchannel_logout_uri: z.ZodOptional<z.ZodURL>;
634
695
  backchannel_logout_session_required: z.ZodOptional<z.ZodBoolean>;
696
+ frontchannel_logout_uri: z.ZodOptional<z.ZodURL>;
697
+ frontchannel_logout_session_required: z.ZodOptional<z.ZodBoolean>;
635
698
  token_endpoint_auth_method: z.ZodOptional<z.ZodString>;
636
- jwks_uri: z.ZodOptional<z.ZodString>;
637
699
  grant_types: z.ZodOptional<z.ZodArray<z.ZodString>>;
638
700
  response_types: z.ZodOptional<z.ZodArray<z.ZodEnum<{
639
701
  code: "code";
@@ -642,11 +704,12 @@ declare const oauthClientMetadataSchema: z.ZodObject<{
642
704
  web: "web";
643
705
  native: "native";
644
706
  }>>;
707
+ dpop_bound_access_tokens: z.ZodOptional<z.ZodBoolean>;
645
708
  subject_type: z.ZodOptional<z.ZodEnum<{
646
709
  public: "public";
647
710
  pairwise: "pairwise";
648
711
  }>>;
649
- dpop_bound_access_tokens: z.ZodOptional<z.ZodBoolean>;
712
+ resources: z.ZodOptional<z.ZodArray<z.ZodString>>;
650
713
  client_id: z.ZodString;
651
714
  client_secret: z.ZodOptional<z.ZodString>;
652
715
  client_secret_expires_at: z.ZodOptional<z.ZodNumber>;
@@ -666,6 +729,55 @@ type ClientRegistrationRequest = z.infer<typeof clientRegistrationRequestSchema>
666
729
  //#endregion
667
730
  //#region src/types/index.d.ts
668
731
  type StoreTokenType = "access_token" | "refresh_token" | "authorization_code" | (string & {});
732
+ /**
733
+ * The authentication context the provider asserts in ID tokens
734
+ * (OIDC Core 1.0 §2).
735
+ */
736
+ interface OAuthAuthenticationContext {
737
+ /**
738
+ * Authentication Context Class Reference the session satisfies. Must be one
739
+ * of `acrValuesSupported`. Defaults to `"0"`.
740
+ */
741
+ acr?: string;
742
+ /**
743
+ * Authentication Methods References used for the session, such as
744
+ * `["pwd", "otp"]` (RFC 8176).
745
+ */
746
+ amr?: string[];
747
+ }
748
+ interface OAuthAuthenticationContextOptions<Scopes extends readonly Scope[] = InternallySupportedScopes[]> {
749
+ /**
750
+ * ACR values this provider can assert, advertised as
751
+ * `acr_values_supported` in discovery. Include `"0"` when `resolve` can
752
+ * return no `acr`.
753
+ */
754
+ acrValuesSupported: string[];
755
+ /**
756
+ * Returns the `acr` and `amr` the current session establishes. Called when
757
+ * the user approves an authorization request or a device code. Return only
758
+ * what the session actually proved; do not raise `acr` to match
759
+ * `requestedAcrValues`.
760
+ *
761
+ * An essential `acr` request (`claims.id_token.acr.essential`) that the
762
+ * returned `acr` does not satisfy fails with `access_denied`. A voluntary
763
+ * request (`acr_values` or a non-essential `acr` claim) never fails.
764
+ *
765
+ * Not called for requests without the `openid` scope, which issue no ID
766
+ * token.
767
+ */
768
+ resolve: (info: {
769
+ user: User & Record<string, unknown>;
770
+ session: Session & Record<string, unknown>;
771
+ client: SchemaClient<Scopes>; /** Scopes being approved */
772
+ scopes: string[]; /** Headers of the request approving the authorization */
773
+ headers: Headers;
774
+ /**
775
+ * ACR values the client requested, from `claims.id_token.acr` and
776
+ * `acr_values`, in order of preference.
777
+ */
778
+ requestedAcrValues: string[];
779
+ }) => Awaitable<OAuthAuthenticationContext | undefined>;
780
+ }
669
781
  type InternallySupportedScopes = "openid" | "profile" | "email" | "offline_access";
670
782
  type Scope = LiteralString | InternallySupportedScopes;
671
783
  /**
@@ -779,6 +891,10 @@ interface OAuthTokenIssueParams {
779
891
  id: string;
780
892
  };
781
893
  authTime?: Date;
894
+ /** The `acr` ID token claim. Defaults to `"0"`. */
895
+ acr?: string;
896
+ /** The `amr` ID token claim. */
897
+ amr?: string[];
782
898
  verificationValue?: VerificationValue;
783
899
  resources?: string[];
784
900
  /** Full original authorized resources for the grant, used to seed refresh tokens. */
@@ -820,6 +936,14 @@ interface OAuthTokenIssueParams {
820
936
  * is stamped after, and cannot be overridden by, contributed claims.
821
937
  */
822
938
  confirmation?: Confirmation;
939
+ /**
940
+ * Latest time the access token may expire. The authorization server issues
941
+ * the earlier of this and its configured lifetime, so a grant derived from
942
+ * another token (for example RFC 8693 token exchange) cannot outlive it.
943
+ * If it is not in the future, issuance fails with `invalid_request`. Refresh
944
+ * and ID tokens are not capped, so such a grant should not issue them.
945
+ */
946
+ maxExpiresAt?: Date;
823
947
  }
824
948
  interface OAuthTokenResponse {
825
949
  access_token: string;
@@ -852,7 +976,10 @@ interface OAuthProviderApi {
852
976
  * or none). For assertion-based methods, the RFC 7523 audience is bound to the
853
977
  * endpoint serving the request, so an assertion cannot be replayed across
854
978
  * endpoints. Returns the authenticated client, plus any `confirmation` an
855
- * assertion strategy proved.
979
+ * assertion strategy proved. A companion endpoint that accepts
980
+ * `application/x-www-form-urlencoded` must set `cloneRequest: true` in its
981
+ * endpoint options because client authentication re-reads the raw form body
982
+ * to enforce credential cardinality and reject mixed authentication methods.
856
983
  */
857
984
  authenticateClient: (request?: OAuthClientAuthenticationRequest) => Awaitable<OAuthAuthenticatedClient>;
858
985
  /**
@@ -869,6 +996,21 @@ interface OAuthProviderApi {
869
996
  * calling it.
870
997
  */
871
998
  issueTokens: (params: OAuthTokenIssueParams) => Awaitable<OAuthTokenResponse>;
999
+ /**
1000
+ * Resolves the sender-constraint the tokens for this request will carry: the
1001
+ * `confirmation` the client proved at authentication, or else the DPoP proof
1002
+ * on this request, verified and required by the same rules `issueTokens`
1003
+ * applies. A grant that consumes a one-time credential (a device code, a CIBA
1004
+ * request) calls this before the claim and passes the result to
1005
+ * `issueTokens` as `confirmation`, so a rejected proof leaves the credential
1006
+ * for a retry with a valid one.
1007
+ */
1008
+ resolveConfirmation: (params: {
1009
+ client: SchemaClient<Scope[]>;
1010
+ scopes: string[];
1011
+ resources?: string[];
1012
+ confirmation?: Confirmation;
1013
+ }) => Promise<Confirmation | undefined>;
872
1014
  /**
873
1015
  * Computes the stored lookup key for a token value (the same hash the
874
1016
  * provider persists), so a caller can find or revoke a previously issued
@@ -998,7 +1140,7 @@ interface OAuthUserInfoExtensionInput {
998
1140
  * `extendOAuthProvider(ctx, extension)` (or the `oauthProvider({ extensions })`
999
1141
  * option).
1000
1142
  *
1001
- * All five kinds live on one object so a single protocol plugin (for example
1143
+ * All seven kinds live on one object so a single protocol plugin (for example
1002
1144
  * RFC 8693 token exchange, which adds a grant, advertises metadata, and emits
1003
1145
  * claims) registers atomically and the host validates the combined surface in
1004
1146
  * one place. Every field is independently optional, so a single-concern plugin
@@ -1006,10 +1148,11 @@ interface OAuthUserInfoExtensionInput {
1006
1148
  * just the one it needs. This is the shape every future OAuth RFC plugin copies.
1007
1149
  *
1008
1150
  * Two contribution disciplines:
1009
- * - Dispatched kinds (`grants`, `clientAuthentication`) must be disjoint across
1010
- * extensions: registering a grant type, auth method, or assertion type that
1011
- * another extension already registered is rejected at setup, since the second
1012
- * would otherwise be silently unreachable.
1151
+ * - Dispatched kinds (`grants`, `clientAuthentication`, `interactionRequests`)
1152
+ * must be disjoint across extensions: registering a grant type, auth method,
1153
+ * assertion type, or interaction parameter that another extension already
1154
+ * registered is rejected at setup, since the second would otherwise be
1155
+ * silently unreachable.
1013
1156
  * - Additive kinds (`metadata`, `claims`) never override authorization-server
1014
1157
  * core; a key already owned by the provider is kept, and a key two extensions
1015
1158
  * both contribute resolves to the first-registered extension.
@@ -1059,6 +1202,117 @@ interface OAuthProviderExtension {
1059
1202
  * registry, an attestation header) contributes it here.
1060
1203
  */
1061
1204
  clientDiscovery?: ClientDiscovery | ClientDiscovery[];
1205
+ /**
1206
+ * Client registration metadata the extension defines, such as CIBA's
1207
+ * `backchannel_token_delivery_mode`. Extension fields live in the client's
1208
+ * `metadata`.
1209
+ */
1210
+ clientMetadata?: {
1211
+ /**
1212
+ * Top-level registration fields the extension defines. Dynamic client
1213
+ * registration (RFC 7591 §2) and client metadata documents (CIMD) both
1214
+ * ignore unrecognized fields; they keep these and store them in the
1215
+ * client's `metadata`, where admin-created clients put them too. Core
1216
+ * and server-owned client fields cannot be claimed.
1217
+ */
1218
+ fields?: string[];
1219
+ /**
1220
+ * Validates the extension's fields when a client is registered through
1221
+ * dynamic registration or a client metadata document, or created or
1222
+ * updated by an admin. Throw an `APIError` with `invalid_client_metadata`
1223
+ * to reject the client.
1224
+ */
1225
+ validate?: (input: OAuthClientMetadataExtensionInput) => Awaitable<void>;
1226
+ };
1227
+ /**
1228
+ * Requests other than an authorization request that users approve through
1229
+ * the `/oauth2/authorize` sign-in, account selection, post-login, and
1230
+ * consent pages, keyed by the query parameter that identifies one, such as
1231
+ * `user_code`. Every interaction page resumes them through
1232
+ * `/oauth2/authorize`.
1233
+ */
1234
+ interactionRequests?: Record<string, OAuthInteractionRequestHandler>;
1235
+ }
1236
+ /**
1237
+ * Parameters signed into each interaction page. An authorization request
1238
+ * carries its `redirect_uri`; other interaction requests have none and add
1239
+ * their own identifying parameter, such as `user_code`.
1240
+ */
1241
+ type OAuthInteractionQuery = Omit<OAuthAuthorizationQuery, "redirect_uri"> & {
1242
+ redirect_uri?: string | undefined;
1243
+ };
1244
+ /**
1245
+ * A request the user reviews through the `/oauth2/authorize` sign-in,
1246
+ * account selection, signup, post-login, and consent pages.
1247
+ */
1248
+ interface OAuthInteractionRequest {
1249
+ /** Signed into each interaction page; carries `prompt` and `max_age`. */
1250
+ query: OAuthInteractionQuery;
1251
+ /** The provider sends the user to the error page when this client is disabled. */
1252
+ client: SchemaClient<Scope[]>;
1253
+ /**
1254
+ * Show the consent page even when consent is stored or the client skips
1255
+ * it, and approve only in the request where the user accepts on that page.
1256
+ */
1257
+ requireConsent?: boolean | undefined;
1258
+ /**
1259
+ * Records the approval once every interaction is complete and returns the
1260
+ * URL to send the user to.
1261
+ */
1262
+ approve: (approval: {
1263
+ query: OAuthInteractionQuery;
1264
+ userId: string;
1265
+ sessionId: string;
1266
+ authTime: number;
1267
+ acr?: string;
1268
+ amr?: string[];
1269
+ referenceId?: string;
1270
+ }) => Promise<string>;
1271
+ }
1272
+ /** Loads and denies one kind of {@link OAuthInteractionRequest}. */
1273
+ interface OAuthInteractionRequestHandler {
1274
+ /**
1275
+ * Loads the request identified by `value`. On a direct `/oauth2/authorize`
1276
+ * request only `value` comes from the caller; when resuming after an
1277
+ * interaction page, `signedQuery` is the query this server signed into it.
1278
+ * Throw an `APIError` when the request can no longer be approved.
1279
+ */
1280
+ load: (input: {
1281
+ ctx: GenericEndpointContext;
1282
+ opts: OAuthOptions<Scope[]>;
1283
+ value: string;
1284
+ signedQuery?: OAuthInteractionQuery | undefined;
1285
+ }) => Promise<OAuthInteractionRequest>;
1286
+ /**
1287
+ * Records a denial from the consent page and returns the URL to send the
1288
+ * user to.
1289
+ */
1290
+ deny: (input: {
1291
+ ctx: GenericEndpointContext;
1292
+ value: string;
1293
+ userId: string;
1294
+ }) => Promise<string>;
1295
+ /**
1296
+ * Where to send the user when the request cannot be loaded, approved, or
1297
+ * denied, such as a page where they can correct it. The provider appends
1298
+ * `error` and `error_description`. Defaults to the provider error page.
1299
+ */
1300
+ errorPage?: (input: {
1301
+ ctx: GenericEndpointContext;
1302
+ value: string;
1303
+ }) => string;
1304
+ }
1305
+ interface OAuthClientMetadataExtensionInput {
1306
+ /**
1307
+ * The client's core registration metadata after provider defaults. Read
1308
+ * extension fields from `metadata`, not from here.
1309
+ */
1310
+ client: Omit<OAuthClientRegistrationMetadata, "metadata">;
1311
+ /**
1312
+ * The client's `metadata` as it will be stored, with reserved client field
1313
+ * names removed. Extension fields are read from here.
1314
+ */
1315
+ metadata: Record<string, unknown>;
1062
1316
  }
1063
1317
  /**
1064
1318
  * Result of authorizing an RFC 7591 initial access token, returned by
@@ -1316,6 +1570,21 @@ interface OAuthOptions<Scopes extends readonly Scope[] = InternallySupportedScop
1316
1570
  * @default 300 (5 minutes)
1317
1571
  */
1318
1572
  assertionMaxLifetime?: number;
1573
+ /**
1574
+ * Lets a confidential `private_key_jwt` client replace its own inline `jwks`
1575
+ * at `POST /oauth2/client/rotate-keys`, authenticated by a client assertion
1576
+ * signed with one of its current keys. No user session is involved.
1577
+ *
1578
+ * Clients that publish their keys at a `jwks_uri` rotate them there, so they
1579
+ * cannot use this endpoint.
1580
+ *
1581
+ * Each rotation assertion must be single-use, so the provider refuses to
1582
+ * start with this enabled on the memory adapter or with
1583
+ * `advanced.database.generateId: "serial"`, neither of which enforces it.
1584
+ *
1585
+ * @default false
1586
+ */
1587
+ allowClientKeyRotation?: boolean;
1319
1588
  /**
1320
1589
  * Allows /oauth2/public-client-prelogin endpoint to be
1321
1590
  * requestable prior to login via a valid oauth_query.
@@ -1434,14 +1703,16 @@ interface OAuthOptions<Scopes extends readonly Scope[] = InternallySupportedScop
1434
1703
  * field.
1435
1704
  *
1436
1705
  * - `"web"`: the OIDC Registration §2 default. Omitted `application_type` is
1437
- * treated as `web`, so custom-scheme redirect URIs are rejected.
1706
+ * treated as `web`, so custom-scheme and loopback redirect URIs are
1707
+ * rejected.
1438
1708
  * - `"native"`: omitted `application_type` is treated as `native`.
1439
1709
  * - `"infer"`: omitted `application_type` is treated as `native` when any
1440
- * `redirect_uris` entry uses a non-http(s) scheme; otherwise `web`. Every
1441
- * redirect URI is then validated against the native rules. Lets native MCP
1442
- * clients that omit `application_type` (for example Cursor, which also
1443
- * registers https and loopback callbacks) register without loosening
1444
- * web-client redirect policy.
1710
+ * `redirect_uris` entry uses a non-http(s) scheme or is `http` on
1711
+ * `localhost`, `127.0.0.1`, or `[::1]`; otherwise `web`. Every redirect URI
1712
+ * of an inferred native client is then validated against the native rules.
1713
+ * Lets native MCP clients that omit `application_type` (for example Cursor,
1714
+ * or older Claude Code releases with an `http://127.0.0.1` callback)
1715
+ * register without loosening web-client redirect policy.
1445
1716
  *
1446
1717
  * An `application_type` the client actually sends is never overridden.
1447
1718
  * Applies only to dynamic client registration; managed clients and Client ID
@@ -1626,7 +1897,8 @@ interface OAuthOptions<Scopes extends readonly Scope[] = InternallySupportedScop
1626
1897
  */
1627
1898
  page: string;
1628
1899
  /**
1629
- * A value to tie to the consent reference_id.
1900
+ * A value to tie to the consent reference_id. Consent is stored
1901
+ * per reference; `undefined` or `""` uses consent given without one.
1630
1902
  *
1631
1903
  * Note that YOU must fail in this function if the requested
1632
1904
  * scope doesn't have a reference id and it should.
@@ -1752,6 +2024,14 @@ interface OAuthOptions<Scopes extends readonly Scope[] = InternallySupportedScop
1752
2024
  */
1753
2025
  requestedClaims: string[];
1754
2026
  }) => Awaitable<Record<string, any>>;
2027
+ /**
2028
+ * Asserts the `acr` and `amr` ID token claims for each approved
2029
+ * authorization request.
2030
+ *
2031
+ * Without this option, ID tokens carry `acr: "0"` (OIDC level 0) and no
2032
+ * `amr`.
2033
+ */
2034
+ authenticationContext?: OAuthAuthenticationContextOptions<Scopes>;
1755
2035
  /**
1756
2036
  * Custom claims attached to OIDC id tokens.
1757
2037
  *
@@ -1937,6 +2217,7 @@ interface OAuthOptions<Scopes extends readonly Scope[] = InternallySupportedScop
1937
2217
  * introspect: { window: 60, max: 100 },
1938
2218
  * revoke: { window: 60, max: 30 },
1939
2219
  * register: { window: 60, max: 5 },
2220
+ * rotateClientKeys: { window: 60, max: 5 },
1940
2221
  * userinfo: { window: 60, max: 60 },
1941
2222
  * }
1942
2223
  * ```
@@ -1982,6 +2263,14 @@ interface OAuthOptions<Scopes extends readonly Scope[] = InternallySupportedScop
1982
2263
  window: number;
1983
2264
  max: number;
1984
2265
  } | false;
2266
+ /**
2267
+ * Rate limit for /oauth2/client/rotate-keys endpoint
2268
+ * @default { window: 60, max: 5 }
2269
+ */
2270
+ rotateClientKeys?: {
2271
+ window: number;
2272
+ max: number;
2273
+ } | false;
1985
2274
  /**
1986
2275
  * Rate limit for /oauth2/userinfo endpoint
1987
2276
  * @default { window: 60, max: 60 }
@@ -2282,6 +2571,8 @@ interface VerificationValue {
2282
2571
  resource?: string[];
2283
2572
  referenceId?: string;
2284
2573
  authTime?: number;
2574
+ acr?: string;
2575
+ amr?: string[];
2285
2576
  }
2286
2577
  /**
2287
2578
  * Client registered values as used within the plugin
@@ -2378,6 +2669,25 @@ interface SchemaClient<Scopes extends readonly Scope[] = InternallySupportedScop
2378
2669
  * @default false
2379
2670
  */
2380
2671
  backchannelLogoutSessionRequired?: boolean;
2672
+ /**
2673
+ * RP URL rendered in a hidden iframe on the OP's logout page when the
2674
+ * end-user's session ends at `/oauth2/end-session`. Registering it is the
2675
+ * per-client opt-in for front-channel logout. Must be absolute, without a
2676
+ * fragment, and share the scheme, host, and port of a registered redirect
2677
+ * URI.
2678
+ *
2679
+ * @see https://openid.net/specs/openid-connect-frontchannel-1_0.html#RPLogout
2680
+ */
2681
+ frontchannelLogoutUri?: string;
2682
+ /**
2683
+ * When true, the RP requires `iss` and `sid` query parameters on its
2684
+ * front-channel logout URI. The OP includes both whenever it notifies a
2685
+ * front-channel client, so this flag is stored but does not change
2686
+ * delivery.
2687
+ *
2688
+ * @default false
2689
+ */
2690
+ frontchannelLogoutSessionRequired?: boolean;
2381
2691
  tokenEndpointAuthMethod?: TokenEndpointAuthMethod;
2382
2692
  grantTypes?: GrantType[];
2383
2693
  responseTypes?: "code"[];
@@ -2410,6 +2720,12 @@ interface SchemaClient<Scopes extends readonly Scope[] = InternallySupportedScop
2410
2720
  enableEndSession?: boolean;
2411
2721
  /** Subject identifier type: "public" (default) or "pairwise" */
2412
2722
  subjectType?: "public" | "pairwise";
2723
+ /**
2724
+ * Pairwise sector, set by the server when the client is created. `null`
2725
+ * for clients created before sectors were stored; those keep the sector
2726
+ * derived from their first redirect URI host.
2727
+ */
2728
+ sectorIdentifier?: string | null;
2413
2729
  /** Reference to the owner of this client. Eg. Organization, Team, Profile */
2414
2730
  referenceId?: string;
2415
2731
  /**
@@ -2526,6 +2842,10 @@ interface OAuthRefreshToken<Scopes extends readonly Scope[] = InternallySupporte
2526
2842
  * Persisted so refreshed ID tokens can include a correct `auth_time` claim.
2527
2843
  */
2528
2844
  authTime?: Date;
2845
+ /** The `acr` asserted at authorization, carried forward on rotation. */
2846
+ acr?: string;
2847
+ /** The `amr` asserted at authorization, carried forward on rotation. */
2848
+ amr?: string[];
2529
2849
  /**
2530
2850
  * Scopes granted for this refresh token.
2531
2851
  *
@@ -2791,6 +3111,27 @@ interface AuthServerMetadata {
2791
3111
  * @see https://datatracker.ietf.org/doc/html/rfc9449
2792
3112
  */
2793
3113
  dpop_signing_alg_values_supported?: JWSAlgorithms[];
3114
+ /**
3115
+ * Boolean value specifying whether the OP supports HTTP-based (front-channel)
3116
+ * logout, with true indicating support.
3117
+ *
3118
+ * Registered in the "OAuth Authorization Server Metadata" IANA registry
3119
+ * under OpenID Connect Front-Channel Logout 1.0, so this may appear at both
3120
+ * `.well-known/oauth-authorization-server` and `.well-known/openid-configuration`.
3121
+ *
3122
+ * @default false
3123
+ * @see https://openid.net/specs/openid-connect-frontchannel-1_0.html#OPLogout
3124
+ */
3125
+ frontchannel_logout_supported?: boolean;
3126
+ /**
3127
+ * Boolean value specifying whether the OP can pass `iss` (issuer) and `sid`
3128
+ * (session ID) query parameters to identify the RP session with the OP when
3129
+ * the `frontchannel_logout_uri` is used.
3130
+ *
3131
+ * @default false
3132
+ * @see https://openid.net/specs/openid-connect-frontchannel-1_0.html#OPLogout
3133
+ */
3134
+ frontchannel_logout_session_supported?: boolean;
2794
3135
  }
2795
3136
  /**
2796
3137
  * Metadata returned by the openid-configuration endpoint:
@@ -2930,6 +3271,25 @@ interface OAuthClient {
2930
3271
  * @see https://openid.net/specs/openid-connect-backchannel-1_0.html#RPMetadata
2931
3272
  */
2932
3273
  backchannel_logout_session_required?: boolean;
3274
+ /**
3275
+ * RP URL that the OP renders in a hidden iframe on its logout page so the
3276
+ * RP can log itself out when the end-user's OP session ends at
3277
+ * `/oauth2/end-session`. Must share the scheme, host, and port of one of
3278
+ * the client's `redirect_uris`.
3279
+ *
3280
+ * @see https://openid.net/specs/openid-connect-frontchannel-1_0.html#RPLogout
3281
+ */
3282
+ frontchannel_logout_uri?: string;
3283
+ /**
3284
+ * When true, the RP requires `iss` and `sid` query parameters on its
3285
+ * `frontchannel_logout_uri`. The OP includes both whenever it notifies a
3286
+ * front-channel client, so this flag is stored but does not change
3287
+ * delivery.
3288
+ *
3289
+ * @default false
3290
+ * @see https://openid.net/specs/openid-connect-frontchannel-1_0.html#RPLogout
3291
+ */
3292
+ frontchannel_logout_session_required?: boolean;
2933
3293
  token_endpoint_auth_method?: TokenEndpointAuthMethod;
2934
3294
  grant_types?: GrantType[];
2935
3295
  response_types?: "code"[];
@@ -3007,4 +3367,4 @@ interface ResourceServerMetadata {
3007
3367
  dpop_bound_access_tokens_required?: boolean;
3008
3368
  }
3009
3369
  //#endregion
3010
- export { OAuthOpaqueAccessToken as A, Prompt as B, OAuthClientAuthenticationStrategy as C, OAuthExtensionGrantHandler as D, OAuthConsent as E, OAuthResource as F, VerificationValue as G, Scope as H, OAuthResourceInput as I, ResourceUriSchema as J, ClientRegistrationRequest as K, OAuthTokenIssueParams as L, OAuthProviderApi as M, OAuthProviderExtension as N, OAuthExtensionGrantHandlerInput as O, OAuthRefreshToken as P, OAuthTokenResponse as R, OAuthClientAuthenticationResult as S, OAuthClientResource as T, StoreTokenType as U, SchemaClient as V, StoredAuthorizationQuery as W, oauthClientMetadataSchema as Y, OAuthAuthorizationQuery as _, GrantType as a, OAuthClientAuthenticationInput as b, ResourceServerMetadata as c, ActiveAccessTokenPayload as d, AuthorizePrompt as f, OAuthAuthenticatedClient as g, InitialAccessTokenAuthorization as h, Confirmation as i, OAuthOptions as j, OAuthMetadataExtensionInput as k, TokenEndpointAuthMethod as l, ClientMetadataResourceFetch as m, AuthServerMetadata as n, OAuthClient as o, ClientDiscovery as p, OAuthClientMetadata as q, BearerMethodsSupported as r, OIDCMetadata as s, AuthMethod as t, TokenType as u, OAuthClaimExtensionInput as v, OAuthClientRegistrationResponse as w, OAuthClientAuthenticationRequest as x, OAuthClientAdministrativeResponse as y, OAuthUserInfoExtensionInput as z };
3370
+ export { OAuthClientMetadata as $, OAuthExtensionGrantHandler as A, OAuthRefreshToken as B, OAuthClientAuthenticationRequest as C, OAuthClientRegistrationResponse as D, OAuthClientMetadataExtensionInput as E, OAuthMetadataExtensionInput as F, OAuthUserInfoExtensionInput as G, OAuthResourceInput as H, OAuthOpaqueAccessToken as I, Scope as J, Prompt as K, OAuthOptions as L, OAuthInteractionQuery as M, OAuthInteractionRequest as N, OAuthClientResource as O, OAuthInteractionRequestHandler as P, ClientRegistrationRequest as Q, OAuthProviderApi as R, OAuthClientAuthenticationInput as S, OAuthClientAuthenticationStrategy as T, OAuthTokenIssueParams as U, OAuthResource as V, OAuthTokenResponse as W, StoredAuthorizationQuery as X, StoreTokenType as Y, VerificationValue as Z, OAuthAuthenticationContext as _, GrantType as a, OAuthClientRegistrationResult as at, OAuthClaimExtensionInput as b, ResourceServerMetadata as c, registerClientMetadataDocument as ct, ActiveAccessTokenPayload as d, ResourceUriSchema as et, AuthorizePrompt as f, OAuthAuthenticatedClient as g, InitialAccessTokenAuthorization as h, Confirmation as i, OAuthClientRegistrationMetadata as it, OAuthExtensionGrantHandlerInput as j, OAuthConsent as k, TokenEndpointAuthMethod as l, ClientMetadataResourceFetch as m, AuthServerMetadata as n, oauthClientMetadataSchema as nt, OAuthClient as o, RegisterClientMetadataDocumentInput as ot, ClientDiscovery as p, SchemaClient as q, BearerMethodsSupported as r, Awaitable as rt, OIDCMetadata as s, assertPublicRoutableHttpsUri as st, AuthMethod as t, clientRegistrationRequestSchema as tt, TokenType as u, OAuthAuthenticationContextOptions as v, OAuthClientAuthenticationResult as w, OAuthClientAdministrativeResponse as x, OAuthAuthorizationQuery as y, OAuthProviderExtension as z };