@better-auth/oauth-provider 1.7.0-beta.8 → 1.7.0-rc.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,4 +1,4 @@
1
- import { C as OAuthConsent, F as OAuthTokenResponse, L as Prompt, M as OAuthResource, O as OAuthOptions, a as GrantType, l as TokenEndpointAuthMethod, n as AuthServerMetadata, o as OAuthClient, z as Scope } from "./oauth-CPWY2Few.mjs";
1
+ import { C as OAuthConsent, L as Prompt, M as OAuthResource, O as OAuthOptions, a as GrantType, l as TokenEndpointAuthMethod, n as AuthServerMetadata, o as OAuthClient, u as TokenType, z as Scope } from "./oauth-ScTJEcFV.mjs";
2
2
  import * as better_call0 from "better-call";
3
3
  import * as z from "zod";
4
4
  import * as jose from "jose";
@@ -140,10 +140,13 @@ declare const oauthProvider: <O extends OAuthOptions<Scope[]>>(options: O) => {
140
140
  }, {
141
141
  jwks_uri?: string | undefined;
142
142
  userinfo_endpoint: string;
143
- acr_values_supported: string[];
143
+ acr_values_supported?: string[] | undefined;
144
144
  subject_types_supported: ("public" | "pairwise")[];
145
145
  claims_supported: string[];
146
+ claims_parameter_supported?: boolean | undefined;
146
147
  end_session_endpoint: string;
148
+ request_parameter_supported?: boolean | undefined;
149
+ request_uri_parameter_supported?: boolean | undefined;
147
150
  prompt_values_supported: Prompt[];
148
151
  issuer: string;
149
152
  authorization_endpoint: string;
@@ -174,41 +177,11 @@ declare const oauthProvider: <O extends OAuthOptions<Scope[]>>(options: O) => {
174
177
  id_token_signing_alg_values_supported: better_auth_plugins0.JWSAlgorithms[] | ["HS256"];
175
178
  }>;
176
179
  oauth2Authorize: better_call0.StrictEndpoint<"/oauth2/authorize", {
177
- method: "GET";
178
- query: z.ZodObject<{
179
- response_type: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodEnum<{
180
- code: "code";
181
- }>>>;
182
- request_uri: z.ZodOptional<z.ZodString>;
183
- redirect_uri: z.ZodOptional<z.ZodURL>;
184
- scope: z.ZodOptional<z.ZodString>;
185
- state: z.ZodOptional<z.ZodString>;
186
- client_id: z.ZodString;
187
- prompt: z.ZodOptional<z.ZodString>;
188
- display: z.ZodOptional<z.ZodString>;
189
- ui_locales: z.ZodOptional<z.ZodString>;
190
- max_age: z.ZodOptional<z.ZodPipe<z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>, z.ZodTransform<number, string | number>>>;
191
- acr_values: z.ZodOptional<z.ZodString>;
192
- login_hint: z.ZodOptional<z.ZodString>;
193
- id_token_hint: z.ZodOptional<z.ZodString>;
194
- code_challenge: z.ZodOptional<z.ZodString>;
195
- code_challenge_method: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodEnum<{
196
- S256: "S256";
197
- }>>>;
198
- nonce: z.ZodOptional<z.ZodString>;
199
- dpop_jkt: z.ZodOptional<z.ZodString>;
200
- resource: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
201
- }, z.core.$loose>;
180
+ method: ("GET" | "POST")[];
181
+ body: z.ZodObject<{}, z.core.$loose>;
202
182
  redirectOnError: OAuthRedirectOnError<GenericEndpointContext, OAuthRedirectResult>;
203
- errorCodesByField: {
204
- response_type: {
205
- invalid: "unsupported_response_type";
206
- };
207
- resource: {
208
- invalid: "invalid_target";
209
- };
210
- };
211
183
  metadata: {
184
+ allowedMediaTypes: string[];
212
185
  openapi: {
213
186
  description: string;
214
187
  parameters: ({
@@ -313,6 +286,7 @@ declare const oauthProvider: <O extends OAuthOptions<Scope[]>>(options: O) => {
313
286
  body: z.ZodObject<{
314
287
  accept: z.ZodBoolean;
315
288
  scope: z.ZodOptional<z.ZodString>;
289
+ claims: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnknown>]>>;
316
290
  oauth_query: z.ZodOptional<z.ZodString>;
317
291
  }, z.core.$strip>;
318
292
  use: ((inputContext: better_call0.MiddlewareInputContext<better_call0.MiddlewareOptions>) => Promise<{
@@ -587,7 +561,15 @@ declare const oauthProvider: <O extends OAuthOptions<Scope[]>>(options: O) => {
587
561
  };
588
562
  };
589
563
  };
590
- }, OAuthTokenResponse>;
564
+ }, {
565
+ expires_in: number;
566
+ access_token: string;
567
+ expires_at: number;
568
+ token_type: TokenType;
569
+ refresh_token: string | undefined;
570
+ scope: string;
571
+ id_token: string | undefined;
572
+ }>;
591
573
  oauth2Introspect: better_call0.StrictEndpoint<"/oauth2/introspect", {
592
574
  method: "POST";
593
575
  body: z.ZodObject<{
@@ -803,8 +785,12 @@ declare const oauthProvider: <O extends OAuthOptions<Scope[]>>(options: O) => {
803
785
  }, null | undefined>;
804
786
  oauth2UserInfo: better_call0.StrictEndpoint<"/oauth2/userinfo", {
805
787
  method: ("GET" | "POST")[];
788
+ body: z.ZodOptional<z.ZodObject<{
789
+ access_token: z.ZodOptional<z.ZodString>;
790
+ }, z.core.$loose>>;
806
791
  metadata: {
807
792
  noStore: boolean;
793
+ allowedMediaTypes: string[];
808
794
  openapi: {
809
795
  description: string;
810
796
  security: ({
@@ -915,13 +901,7 @@ declare const oauthProvider: <O extends OAuthOptions<Scope[]>>(options: O) => {
915
901
  };
916
902
  };
917
903
  }, {
918
- sub: string;
919
- email?: string | undefined;
920
- email_verified?: boolean | undefined;
921
- name?: string | undefined;
922
- picture?: string | undefined;
923
- given_name?: string | undefined;
924
- family_name?: string | undefined;
904
+ sub: unknown;
925
905
  }>;
926
906
  oauth2EndSession: better_call0.StrictEndpoint<"/oauth2/end-session", {
927
907
  method: "GET";
@@ -2306,10 +2286,19 @@ declare const oauthProvider: <O extends OAuthOptions<Scope[]>>(options: O) => {
2306
2286
  type: "string";
2307
2287
  required: false;
2308
2288
  };
2289
+ authorizationCodeId: {
2290
+ type: "string";
2291
+ required: false;
2292
+ index: true;
2293
+ };
2309
2294
  resources: {
2310
2295
  type: "string[]";
2311
2296
  required: false;
2312
2297
  };
2298
+ requestedUserInfoClaims: {
2299
+ type: "string[]";
2300
+ required: false;
2301
+ };
2313
2302
  expiresAt: {
2314
2303
  type: "date";
2315
2304
  };
@@ -2320,6 +2309,18 @@ declare const oauthProvider: <O extends OAuthOptions<Scope[]>>(options: O) => {
2320
2309
  type: "date";
2321
2310
  required: false;
2322
2311
  };
2312
+ rotatedAt: {
2313
+ type: "date";
2314
+ required: false;
2315
+ };
2316
+ rotationReplayResponse: {
2317
+ type: "string";
2318
+ required: false;
2319
+ };
2320
+ rotationReplayExpiresAt: {
2321
+ type: "date";
2322
+ required: false;
2323
+ };
2323
2324
  authTime: {
2324
2325
  type: "date";
2325
2326
  required: false;
@@ -2373,10 +2374,19 @@ declare const oauthProvider: <O extends OAuthOptions<Scope[]>>(options: O) => {
2373
2374
  type: "string";
2374
2375
  required: false;
2375
2376
  };
2377
+ authorizationCodeId: {
2378
+ type: "string";
2379
+ required: false;
2380
+ index: true;
2381
+ };
2376
2382
  resources: {
2377
2383
  type: "string[]";
2378
2384
  required: false;
2379
2385
  };
2386
+ requestedUserInfoClaims: {
2387
+ type: "string[]";
2388
+ required: false;
2389
+ };
2380
2390
  refreshId: {
2381
2391
  type: "string";
2382
2392
  required: false;
@@ -2435,6 +2445,10 @@ declare const oauthProvider: <O extends OAuthOptions<Scope[]>>(options: O) => {
2435
2445
  type: "string[]";
2436
2446
  required: false;
2437
2447
  };
2448
+ requestedUserInfoClaims: {
2449
+ type: "string[]";
2450
+ required: false;
2451
+ };
2438
2452
  scopes: {
2439
2453
  type: "string[]";
2440
2454
  required: true;
@@ -335,10 +335,19 @@ declare const schema: {
335
335
  type: "string";
336
336
  required: false;
337
337
  };
338
+ authorizationCodeId: {
339
+ type: "string";
340
+ required: false;
341
+ index: true;
342
+ };
338
343
  resources: {
339
344
  type: "string[]";
340
345
  required: false;
341
346
  };
347
+ requestedUserInfoClaims: {
348
+ type: "string[]";
349
+ required: false;
350
+ };
342
351
  expiresAt: {
343
352
  type: "date";
344
353
  };
@@ -349,6 +358,18 @@ declare const schema: {
349
358
  type: "date";
350
359
  required: false;
351
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
+ };
352
373
  authTime: {
353
374
  type: "date";
354
375
  required: false;
@@ -414,10 +435,19 @@ declare const schema: {
414
435
  type: "string";
415
436
  required: false;
416
437
  };
438
+ authorizationCodeId: {
439
+ type: "string";
440
+ required: false;
441
+ index: true;
442
+ };
417
443
  resources: {
418
444
  type: "string[]";
419
445
  required: false;
420
446
  };
447
+ requestedUserInfoClaims: {
448
+ type: "string[]";
449
+ required: false;
450
+ };
421
451
  refreshId: {
422
452
  type: "string";
423
453
  required: false;
@@ -476,6 +506,10 @@ declare const schema: {
476
506
  type: "string[]";
477
507
  required: false;
478
508
  };
509
+ requestedUserInfoClaims: {
510
+ type: "string[]";
511
+ required: false;
512
+ };
479
513
  scopes: {
480
514
  type: "string[]";
481
515
  required: true;
@@ -670,6 +704,13 @@ interface OAuthTokenIssueParams {
670
704
  resources?: string[];
671
705
  /** Full original authorized resources for the grant, used to seed refresh tokens. */
672
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[];
673
714
  /**
674
715
  * Additional JWT access-token claims for this single issuance.
675
716
  *
@@ -867,6 +908,11 @@ interface OAuthUserInfoExtensionInput {
867
908
  scopes: string[];
868
909
  jwt: JWTPayload;
869
910
  client?: SchemaClient<Scope[]>;
911
+ /**
912
+ * Claim names explicitly requested through the OIDC `claims.userinfo`
913
+ * authorization request parameter.
914
+ */
915
+ requestedClaims: string[];
870
916
  }
871
917
  /**
872
918
  * What a companion plugin contributes to the OAuth Provider, registered through
@@ -1084,6 +1130,18 @@ interface OAuthOptions<Scopes extends readonly Scope[] = InternallySupportedScop
1084
1130
  * @default 2592000 (30 days)
1085
1131
  */
1086
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;
1087
1145
  /**
1088
1146
  * The amount of time in seconds that the authorization code is valid for.
1089
1147
  *
@@ -1121,8 +1179,9 @@ interface OAuthOptions<Scopes extends readonly Scope[] = InternallySupportedScop
1121
1179
  * Allow unauthenticated dynamic client registration.
1122
1180
  *
1123
1181
  * When enabled, the `/oauth2/register` endpoint accepts requests
1124
- * without a session, but only for public clients
1125
- * (`token_endpoint_auth_method: "none"`).
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.
1126
1185
  *
1127
1186
  * For verified client discovery (MCP), consider installing the
1128
1187
  * `@better-auth/cimd` plugin, which verifies client identity through
@@ -1139,8 +1198,8 @@ interface OAuthOptions<Scopes extends readonly Scope[] = InternallySupportedScop
1139
1198
  * - session-backed: a logged-in user with client-create privileges.
1140
1199
  * - token-backed: a valid initial access token, when
1141
1200
  * {@link OAuthOptions.validateInitialAccessToken} is defined.
1142
- * - open public-only: unauthenticated registration constrained to public
1143
- * clients, when {@link OAuthOptions.allowUnauthenticatedClientRegistration}
1201
+ * - open: unauthenticated registration, when
1202
+ * {@link OAuthOptions.allowUnauthenticatedClientRegistration}
1144
1203
  * is enabled.
1145
1204
  *
1146
1205
  * @default false
@@ -1209,6 +1268,17 @@ interface OAuthOptions<Scopes extends readonly Scope[] = InternallySupportedScop
1209
1268
  * @default - clientRegistrationDefaultScopes
1210
1269
  */
1211
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;
1212
1282
  /**
1213
1283
  * How long a dynamically created confidential client
1214
1284
  * should last for.
@@ -1294,11 +1364,16 @@ interface OAuthOptions<Scopes extends readonly Scope[] = InternallySupportedScop
1294
1364
  *
1295
1365
  * - `client_id` - The ID of the client.
1296
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.
1297
1370
  * - `code` - The authorization code.
1298
1371
  *
1299
1372
  * once the user consents, you need to call the `/oauth2/consent` endpoint
1300
- * with the code and `accept: true` to complete the authorization. Which will
1301
- * then return the client to the `redirect_uri` with the authorization code.
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.
1302
1377
  *
1303
1378
  * @example
1304
1379
  * ```ts
@@ -1492,6 +1567,11 @@ interface OAuthOptions<Scopes extends readonly Scope[] = InternallySupportedScop
1492
1567
  * in the /userinfo request (matches jwt.scopes) */
1493
1568
  scopes: Scopes; /** The access token payload used in the /userinfo request */
1494
1569
  jwt: JWTPayload;
1570
+ /**
1571
+ * Claim names explicitly requested through the OIDC `claims.userinfo`
1572
+ * authorization request parameter.
1573
+ */
1574
+ requestedClaims: string[];
1495
1575
  }) => Awaitable<Record<string, any>>;
1496
1576
  /**
1497
1577
  * Custom claims attached to OIDC id tokens.
@@ -1501,6 +1581,11 @@ interface OAuthOptions<Scopes extends readonly Scope[] = InternallySupportedScop
1501
1581
  * example.com should namespace an organization at
1502
1582
  * https://example.com/organization.
1503
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
+ *
1504
1589
  * @param info - context that may be useful when creating custom claims
1505
1590
  */
1506
1591
  customIdTokenClaims?: (info: {
@@ -1797,6 +1882,13 @@ interface OAuthAuthorizationQuery {
1797
1882
  * Optional in the query when using request_uri (PAR) — resolved from stored params.
1798
1883
  */
1799
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;
1800
1892
  /**
1801
1893
  * PAR request_uri. When present, other params are resolved from the stored request.
1802
1894
  */
@@ -1904,6 +1996,14 @@ interface OAuthAuthorizationQuery {
1904
1996
  * with the Claim Value being the nonce value sent in the Authentication Request.
1905
1997
  */
1906
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>;
1907
2007
  /**
1908
2008
  * RFC 9449 authorization request parameter. When present, the authorization
1909
2009
  * code is bound to this JWK thumbprint and the token request must present a
@@ -1998,6 +2098,17 @@ interface OAuthClientResource {
1998
2098
  metadata?: Record<string, unknown> | null;
1999
2099
  createdAt: Date;
2000
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;
2111
+ }
2001
2112
  /**
2002
2113
  * Stored within the verification.value field
2003
2114
  * in JSON format.
@@ -2007,7 +2118,7 @@ interface OAuthClientResource {
2007
2118
  */
2008
2119
  interface VerificationValue {
2009
2120
  type: "authorization_code";
2010
- query: OAuthAuthorizationQuery;
2121
+ query: StoredAuthorizationQuery;
2011
2122
  sessionId: string;
2012
2123
  userId: string;
2013
2124
  resource?: string[];
@@ -2098,7 +2209,7 @@ interface SchemaClient<Scopes extends readonly Scope[] = InternallySupportedScop
2098
2209
  tokenEndpointAuthMethod?: TokenEndpointAuthMethod;
2099
2210
  grantTypes?: GrantType[];
2100
2211
  responseTypes?: "code"[];
2101
- /** Client's JSON Web Key Set for `private_key_jwt` authentication. Mutually exclusive with `jwksUri`. */
2212
+ /** Client's JSON Web Key Set metadata. Mutually exclusive with `jwksUri`. */
2102
2213
  jwks?: string;
2103
2214
  /** URI for the client's JSON Web Key Set. Mutually exclusive with `jwks`. Must be HTTPS. */
2104
2215
  jwksUri?: string;
@@ -2181,6 +2292,11 @@ interface OAuthOpaqueAccessToken<Scopes extends readonly Scope[] = InternallySup
2181
2292
  * where no user is involved.
2182
2293
  */
2183
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;
2184
2300
  /**
2185
2301
  * The refresh token the access token is associated with.
2186
2302
  *
@@ -2207,6 +2323,11 @@ interface OAuthOpaqueAccessToken<Scopes extends readonly Scope[] = InternallySup
2207
2323
  * Resources allowed for this access token.
2208
2324
  */
2209
2325
  resources?: string[];
2326
+ /**
2327
+ * OIDC UserInfo claim names requested by the authorization request's
2328
+ * `claims.userinfo` object.
2329
+ */
2330
+ requestedUserInfoClaims?: string[];
2210
2331
  /**
2211
2332
  * RFC 7800 `cnf` confirmation that sender-constrains this access token (for
2212
2333
  * example DPoP `{ jkt }`). Surfaced as the `cnf` claim at introspection.
@@ -2221,13 +2342,30 @@ interface OAuthRefreshToken<Scopes extends readonly Scope[] = InternallySupporte
2221
2342
  sessionId?: string;
2222
2343
  userId: string;
2223
2344
  referenceId?: string;
2345
+ authorizationCodeId?: string;
2224
2346
  clientId?: string;
2225
2347
  expiresAt: Date;
2226
2348
  createdAt: Date;
2227
2349
  /**
2228
- * When token was revoked. If set, token is considered a replay attack.
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.
2229
2354
  */
2230
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;
2231
2369
  /**
2232
2370
  * The time the user originally authenticated.
2233
2371
  * Persisted so refreshed ID tokens can include a correct `auth_time` claim.
@@ -2243,6 +2381,11 @@ interface OAuthRefreshToken<Scopes extends readonly Scope[] = InternallySupporte
2243
2381
  * Resources allowed for this refresh token
2244
2382
  */
2245
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[];
2246
2389
  /**
2247
2390
  * RFC 7800 `cnf` confirmation that sender-constrains this refresh-token
2248
2391
  * family (for example DPoP `{ jkt }`). Carried forward on rotation.
@@ -2258,6 +2401,11 @@ type OAuthConsent<Scopes extends readonly Scope[] = InternallySupportedScopes[]>
2258
2401
  userId: string;
2259
2402
  resources?: string[];
2260
2403
  referenceId?: string;
2404
+ /**
2405
+ * OIDC UserInfo claim names consented from the authorization request's
2406
+ * `claims.userinfo` object.
2407
+ */
2408
+ requestedUserInfoClaims?: string[];
2261
2409
  scopes: Scopes;
2262
2410
  createdAt: Date;
2263
2411
  updatedAt: Date;
@@ -2506,19 +2654,16 @@ interface OIDCMetadata extends AuthServerMetadata {
2506
2654
  */
2507
2655
  userinfo_endpoint: string;
2508
2656
  /**
2509
- * acr_values supported.
2510
- *
2511
- * - `urn:mace:incommon:iap:silver`: Silver level of assurance
2512
- * - `urn:mace:incommon:iap:bronze`: Bronze level of assurance
2657
+ * Authentication Context Class Reference values supported.
2513
2658
  *
2514
- * Determination of acr_value is considered bronze by default.
2515
- * Silver level determination coming soon.
2659
+ * Better Auth does not advertise this field by default because it does not
2660
+ * currently evaluate requested Authentication Context Class References.
2516
2661
  *
2517
2662
  * @default
2518
- * ["urn:mace:incommon:iap:bronze"]
2519
- * @see https://incommon.org/federation/attributes.html
2663
+ * undefined
2664
+ * @see https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata
2520
2665
  */
2521
- acr_values_supported: string[];
2666
+ acr_values_supported?: string[];
2522
2667
  /**
2523
2668
  * Supported subject types.
2524
2669
  *
@@ -2546,12 +2691,36 @@ interface OIDCMetadata extends AuthServerMetadata {
2546
2691
  * ["sub", "iss", "aud", "exp", "nbf", "iat", "jti", "email", "email_verified", "name", "family_name", "given_name", "sid", "scope", "azp"]
2547
2692
  */
2548
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;
2549
2701
  /**
2550
2702
  * RP-Initiated Logout Endpoint
2551
2703
  *
2552
2704
  * @see https://openid.net/specs/openid-connect-rpinitiated-1_0.html
2553
2705
  */
2554
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;
2555
2724
  /**
2556
2725
  * Prompt values supported by this OIDC server
2557
2726
  *
@@ -2619,8 +2788,9 @@ interface OAuthClient {
2619
2788
  *
2620
2789
  * @default true
2621
2790
  *
2622
- * Note: PKCE is always required for public clients and when
2623
- * requesting offline_access scope, regardless of this setting.
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`.
2624
2794
  */
2625
2795
  require_pkce?: boolean;
2626
2796
  /**
@@ -2676,4 +2846,4 @@ interface ResourceServerMetadata {
2676
2846
  dpop_bound_access_tokens_required?: boolean;
2677
2847
  }
2678
2848
  //#endregion
2679
- export { OAuthProviderExtension as A, StoreTokenType as B, OAuthConsent as C, OAuthOpaqueAccessToken as D, OAuthMetadataExtensionInput as E, OAuthTokenResponse as F, ClientRegistrationRequest 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, ResourceUriSchema as U, VerificationValue as V, 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 };
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 };
@@ -1,4 +1,4 @@
1
- import { n as canonicalizeOAuthQueryParams } from "./signed-query-CFv2jNMT.mjs";
1
+ import { n as canonicalizeOAuthQueryParams } from "./signed-query-Df1MNiSH.mjs";
2
2
  import { constantTimeEqual, makeSignature, symmetricDecrypt, symmetricEncrypt } from "better-auth/crypto";
3
3
  import { APIError } from "better-call";
4
4
  import { logger } from "@better-auth/core/env";
@@ -631,7 +631,7 @@ async function extractClientCredentials(ctx, opts, expectedAudience) {
631
631
  confirmation: result.confirmation
632
632
  };
633
633
  }
634
- const { verifyClientAssertion: verify } = await import("./client-assertion-CctbJywV.mjs").then((n) => n.t);
634
+ const { verifyClientAssertion: verify } = await import("./client-assertion-D-tAYsKC.mjs").then((n) => n.t);
635
635
  return {
636
636
  kind: "pre_verified",
637
637
  method: "private_key_jwt",
@@ -736,27 +736,32 @@ function removeMaxAgeFromQuery(query) {
736
736
  }
737
737
  var PKCERequirementErrors = /* @__PURE__ */ function(PKCERequirementErrors) {
738
738
  PKCERequirementErrors["PUBLIC_CLIENT"] = "pkce is required for public clients";
739
- PKCERequirementErrors["OFFLINE_ACCESS_SCOPE"] = "pkce is required when requesting offline_access scope";
739
+ PKCERequirementErrors["OFFLINE_ACCESS_SCOPE"] = "pkce or OIDC nonce is required when requesting offline_access scope";
740
740
  PKCERequirementErrors["CLIENT_REQUIRE_PKCE"] = "pkce is required for this client";
741
741
  return PKCERequirementErrors;
742
742
  }(PKCERequirementErrors || {});
743
743
  /**
744
- * Determines if PKCE is required for a given client and scope.
744
+ * Determines if PKCE is required for a given client and authorization request.
745
745
  *
746
746
  * PKCE is always required for:
747
747
  * 1. Public clients (cannot securely store client_secret)
748
- * 2. Requests with offline_access scope (refresh token security)
748
+ * 2. Requests with offline_access scope unless a confidential OIDC request
749
+ * already uses nonce as its authorization-code injection countermeasure.
749
750
  *
750
- * For confidential clients without offline_access:
751
+ * For confidential clients:
751
752
  * - Uses client.requirePKCE if set (defaults to true)
752
753
  *
753
754
  * Returns false if PKCE is not required, or the reason it is required.
754
755
  *
755
756
  * @internal
756
757
  */
757
- function isPKCERequired(client, requestedScopes) {
758
+ function isPKCERequired(client, request) {
758
759
  if (client.tokenEndpointAuthMethod === "none" || client.type === "native" || client.type === "user-agent-based" || client.public === true) return PKCERequirementErrors.PUBLIC_CLIENT;
759
- if (requestedScopes?.includes("offline_access")) return PKCERequirementErrors.OFFLINE_ACCESS_SCOPE;
760
+ const requestScopes = request?.scopes ?? [];
761
+ const isOpenIdRequest = requestScopes.includes("openid");
762
+ const hasNonce = typeof request?.nonce === "string" && request.nonce.length > 0;
763
+ const hasOidcNonce = isOpenIdRequest && hasNonce;
764
+ if (requestScopes.includes("offline_access") && !hasOidcNonce) return PKCERequirementErrors.OFFLINE_ACCESS_SCOPE;
760
765
  if (client.requirePKCE ?? true) return PKCERequirementErrors.CLIENT_REQUIRE_PKCE;
761
766
  return false;
762
767
  }
@@ -1,5 +1,5 @@
1
1
  //#endregion
2
2
  //#region src/version.ts
3
- const PACKAGE_VERSION = "1.7.0-beta.8";
3
+ const PACKAGE_VERSION = "1.7.0-rc.0";
4
4
  //#endregion
5
5
  export { PACKAGE_VERSION as t };