@startino/better-auth-oidc 0.1.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.
@@ -0,0 +1,936 @@
1
+ import * as z$1 from "zod/v4";
2
+ import z from "zod/v4";
3
+ import * as better_auth9 from "better-auth";
4
+ import { Awaitable, OAuth2Tokens, User } from "better-auth";
5
+ import * as better_call6 from "better-call";
6
+
7
+ //#region src/types.d.ts
8
+ interface OIDCMapping {
9
+ id?: string | undefined;
10
+ email?: string | undefined;
11
+ emailVerified?: string | undefined;
12
+ name?: string | undefined;
13
+ image?: string | undefined;
14
+ extraFields?: Record<string, string> | undefined;
15
+ }
16
+ interface OIDCConfig {
17
+ issuer: string;
18
+ pkce: boolean;
19
+ clientId: string;
20
+ clientSecret: string;
21
+ authorizationEndpoint?: string | undefined;
22
+ discoveryEndpoint: string;
23
+ userInfoEndpoint?: string | undefined;
24
+ scopes?: string[] | undefined;
25
+ overrideUserInfo?: boolean | undefined;
26
+ tokenEndpoint?: string | undefined;
27
+ tokenEndpointAuthentication?: ("client_secret_post" | "client_secret_basic") | undefined;
28
+ jwksEndpoint?: string | undefined;
29
+ mapping?: OIDCMapping | undefined;
30
+ }
31
+ type BaseSSOProvider = {
32
+ issuer: string;
33
+ oidcConfig?: OIDCConfig | undefined;
34
+ userId: string;
35
+ providerId: string;
36
+ organizationId?: string | undefined;
37
+ domain: string;
38
+ };
39
+ type SSOProvider<O extends SSOOptions> = O["domainVerification"] extends {
40
+ enabled: true;
41
+ } ? {
42
+ domainVerified: boolean;
43
+ } & BaseSSOProvider : BaseSSOProvider;
44
+ interface SSOOptions {
45
+ /**
46
+ * custom function to provision a user when they sign in with an SSO provider.
47
+ */
48
+ provisionUser?: ((data: {
49
+ /**
50
+ * The user object from the database
51
+ */
52
+ user: User & Record<string, any>;
53
+ /**
54
+ * The user info object from the provider
55
+ */
56
+ userInfo: Record<string, any>;
57
+ /**
58
+ * The OAuth2 tokens from the provider
59
+ */
60
+ token?: OAuth2Tokens;
61
+ /**
62
+ * The SSO provider
63
+ */
64
+ provider: SSOProvider<SSOOptions>;
65
+ }) => Awaitable<void>) | undefined;
66
+ /**
67
+ * Organization provisioning options
68
+ */
69
+ organizationProvisioning?: {
70
+ disabled?: boolean;
71
+ defaultRole?: "member" | "admin";
72
+ getRole?: (data: {
73
+ /**
74
+ * The user object from the database
75
+ */
76
+ user: User & Record<string, any>;
77
+ /**
78
+ * The user info object from the provider
79
+ */
80
+ userInfo: Record<string, any>;
81
+ /**
82
+ * The OAuth2 tokens from the provider
83
+ */
84
+ token?: OAuth2Tokens;
85
+ /**
86
+ * The SSO provider
87
+ */
88
+ provider: SSOProvider<SSOOptions>;
89
+ }) => Promise<"member" | "admin">;
90
+ } | undefined;
91
+ /**
92
+ * Default SSO provider configurations for testing.
93
+ * These will take the precedence over the database providers.
94
+ */
95
+ defaultSSO?: Array<{
96
+ /**
97
+ * The domain to match for this default provider.
98
+ * This is only used to match incoming requests to this default provider.
99
+ */
100
+ domain: string;
101
+ /**
102
+ * The provider ID to use
103
+ */
104
+ providerId: string;
105
+ /**
106
+ * OIDC configuration
107
+ */
108
+ oidcConfig?: OIDCConfig;
109
+ }> | undefined;
110
+ /**
111
+ * Override user info with the provider info.
112
+ * @default false
113
+ */
114
+ defaultOverrideUserInfo?: boolean | undefined;
115
+ /**
116
+ * Disable implicit sign up for new users. When set to true for the provider,
117
+ * sign-in need to be called with with requestSignUp as true to create new users.
118
+ */
119
+ disableImplicitSignUp?: boolean | undefined;
120
+ /**
121
+ * The model name for the SSO provider table. Defaults to "ssoProvider".
122
+ */
123
+ modelName?: string;
124
+ /**
125
+ * Map fields
126
+ */
127
+ fields?: {
128
+ issuer?: string | undefined;
129
+ oidcConfig?: string | undefined;
130
+ userId?: string | undefined;
131
+ providerId?: string | undefined;
132
+ organizationId?: string | undefined;
133
+ domain?: string | undefined;
134
+ };
135
+ /**
136
+ * Configure the maximum number of SSO providers a user can register.
137
+ * You can also pass a function that returns a number.
138
+ * Set to 0 to disable SSO provider registration.
139
+ *
140
+ * @default 10
141
+ */
142
+ providersLimit?: (number | ((user: User) => Awaitable<number>)) | undefined;
143
+ /**
144
+ * Trust the email verified flag from the provider.
145
+ *
146
+ * @default false
147
+ *
148
+ * @deprecated This option is discouraged for new projects. Relying on provider-level `email_verified` is a weaker
149
+ * trust signal compared to using `trustedProviders` in `accountLinking` or enabling `domainVerification` for SSO.
150
+ */
151
+ trustEmailVerified?: boolean | undefined;
152
+ /**
153
+ * Enable domain verification on SSO providers
154
+ */
155
+ domainVerification?: {
156
+ /**
157
+ * Enables or disables the domain verification feature
158
+ */
159
+ enabled?: boolean;
160
+ /**
161
+ * Prefix used to generate the domain verification token.
162
+ * An underscore is automatically prepended to follow DNS
163
+ * infrastructure subdomain conventions (RFC 8552), so do
164
+ * not include a leading underscore.
165
+ *
166
+ * @default "better-auth-token"
167
+ */
168
+ tokenPrefix?: string;
169
+ };
170
+ }
171
+ //#endregion
172
+ //#region src/routes/domain-verification.d.ts
173
+ declare const requestDomainVerification: (options: SSOOptions) => better_call6.StrictEndpoint<"/sso/request-domain-verification", {
174
+ method: "POST";
175
+ body: z$1.ZodObject<{
176
+ providerId: z$1.ZodString;
177
+ }, z$1.core.$strip>;
178
+ metadata: {
179
+ openapi: {
180
+ summary: string;
181
+ description: string;
182
+ responses: {
183
+ "404": {
184
+ description: string;
185
+ };
186
+ "409": {
187
+ description: string;
188
+ };
189
+ "201": {
190
+ description: string;
191
+ };
192
+ };
193
+ };
194
+ };
195
+ use: ((inputContext: better_auth9.MiddlewareInputContext<better_auth9.MiddlewareOptions>) => Promise<{
196
+ session: {
197
+ session: Record<string, any> & {
198
+ id: string;
199
+ createdAt: Date;
200
+ updatedAt: Date;
201
+ userId: string;
202
+ expiresAt: Date;
203
+ token: string;
204
+ ipAddress?: string | null | undefined;
205
+ userAgent?: string | null | undefined;
206
+ };
207
+ user: Record<string, any> & {
208
+ id: string;
209
+ createdAt: Date;
210
+ updatedAt: Date;
211
+ email: string;
212
+ emailVerified: boolean;
213
+ name: string;
214
+ image?: string | null | undefined;
215
+ };
216
+ };
217
+ }>)[];
218
+ }, {
219
+ domainVerificationToken: string;
220
+ }>;
221
+ declare const verifyDomain: (options: SSOOptions) => better_call6.StrictEndpoint<"/sso/verify-domain", {
222
+ method: "POST";
223
+ body: z$1.ZodObject<{
224
+ providerId: z$1.ZodString;
225
+ }, z$1.core.$strip>;
226
+ metadata: {
227
+ openapi: {
228
+ summary: string;
229
+ description: string;
230
+ responses: {
231
+ "404": {
232
+ description: string;
233
+ };
234
+ "409": {
235
+ description: string;
236
+ };
237
+ "502": {
238
+ description: string;
239
+ };
240
+ "204": {
241
+ description: string;
242
+ };
243
+ };
244
+ };
245
+ };
246
+ use: ((inputContext: better_auth9.MiddlewareInputContext<better_auth9.MiddlewareOptions>) => Promise<{
247
+ session: {
248
+ session: Record<string, any> & {
249
+ id: string;
250
+ createdAt: Date;
251
+ updatedAt: Date;
252
+ userId: string;
253
+ expiresAt: Date;
254
+ token: string;
255
+ ipAddress?: string | null | undefined;
256
+ userAgent?: string | null | undefined;
257
+ };
258
+ user: Record<string, any> & {
259
+ id: string;
260
+ createdAt: Date;
261
+ updatedAt: Date;
262
+ email: string;
263
+ emailVerified: boolean;
264
+ name: string;
265
+ image?: string | null | undefined;
266
+ };
267
+ };
268
+ }>)[];
269
+ }, void>;
270
+ //# sourceMappingURL=domain-verification.d.ts.map
271
+ //#endregion
272
+ //#region src/routes/providers.d.ts
273
+ declare const listSSOProviders: () => better_call6.StrictEndpoint<"/sso/providers", {
274
+ method: "GET";
275
+ use: ((inputContext: better_auth9.MiddlewareInputContext<better_auth9.MiddlewareOptions>) => Promise<{
276
+ session: {
277
+ session: Record<string, any> & {
278
+ id: string;
279
+ createdAt: Date;
280
+ updatedAt: Date;
281
+ userId: string;
282
+ expiresAt: Date;
283
+ token: string;
284
+ ipAddress?: string | null | undefined;
285
+ userAgent?: string | null | undefined;
286
+ };
287
+ user: Record<string, any> & {
288
+ id: string;
289
+ createdAt: Date;
290
+ updatedAt: Date;
291
+ email: string;
292
+ emailVerified: boolean;
293
+ name: string;
294
+ image?: string | null | undefined;
295
+ };
296
+ };
297
+ }>)[];
298
+ metadata: {
299
+ openapi: {
300
+ operationId: string;
301
+ summary: string;
302
+ description: string;
303
+ responses: {
304
+ "200": {
305
+ description: string;
306
+ };
307
+ };
308
+ };
309
+ };
310
+ }, {
311
+ providers: {
312
+ providerId: string;
313
+ type: "oidc";
314
+ issuer: string;
315
+ domain: string;
316
+ organizationId: string | null;
317
+ domainVerified: boolean;
318
+ oidcConfig: {
319
+ discoveryEndpoint: string;
320
+ clientIdLastFour: string;
321
+ pkce: boolean;
322
+ authorizationEndpoint: string | undefined;
323
+ tokenEndpoint: string | undefined;
324
+ userInfoEndpoint: string | undefined;
325
+ jwksEndpoint: string | undefined;
326
+ scopes: string[] | undefined;
327
+ tokenEndpointAuthentication: "client_secret_post" | "client_secret_basic" | undefined;
328
+ } | undefined;
329
+ }[];
330
+ }>;
331
+ declare const getSSOProvider: () => better_call6.StrictEndpoint<"/sso/get-provider", {
332
+ method: "GET";
333
+ use: ((inputContext: better_auth9.MiddlewareInputContext<better_auth9.MiddlewareOptions>) => Promise<{
334
+ session: {
335
+ session: Record<string, any> & {
336
+ id: string;
337
+ createdAt: Date;
338
+ updatedAt: Date;
339
+ userId: string;
340
+ expiresAt: Date;
341
+ token: string;
342
+ ipAddress?: string | null | undefined;
343
+ userAgent?: string | null | undefined;
344
+ };
345
+ user: Record<string, any> & {
346
+ id: string;
347
+ createdAt: Date;
348
+ updatedAt: Date;
349
+ email: string;
350
+ emailVerified: boolean;
351
+ name: string;
352
+ image?: string | null | undefined;
353
+ };
354
+ };
355
+ }>)[];
356
+ query: z.ZodObject<{
357
+ providerId: z.ZodString;
358
+ }, z.core.$strip>;
359
+ metadata: {
360
+ openapi: {
361
+ operationId: string;
362
+ summary: string;
363
+ description: string;
364
+ responses: {
365
+ "200": {
366
+ description: string;
367
+ };
368
+ "404": {
369
+ description: string;
370
+ };
371
+ "403": {
372
+ description: string;
373
+ };
374
+ };
375
+ };
376
+ };
377
+ }, {
378
+ providerId: string;
379
+ type: "oidc";
380
+ issuer: string;
381
+ domain: string;
382
+ organizationId: string | null;
383
+ domainVerified: boolean;
384
+ oidcConfig: {
385
+ discoveryEndpoint: string;
386
+ clientIdLastFour: string;
387
+ pkce: boolean;
388
+ authorizationEndpoint: string | undefined;
389
+ tokenEndpoint: string | undefined;
390
+ userInfoEndpoint: string | undefined;
391
+ jwksEndpoint: string | undefined;
392
+ scopes: string[] | undefined;
393
+ tokenEndpointAuthentication: "client_secret_post" | "client_secret_basic" | undefined;
394
+ } | undefined;
395
+ }>;
396
+ declare const updateSSOProvider: (options: SSOOptions) => better_call6.StrictEndpoint<"/sso/update-provider", {
397
+ method: "POST";
398
+ use: ((inputContext: better_auth9.MiddlewareInputContext<better_auth9.MiddlewareOptions>) => Promise<{
399
+ session: {
400
+ session: Record<string, any> & {
401
+ id: string;
402
+ createdAt: Date;
403
+ updatedAt: Date;
404
+ userId: string;
405
+ expiresAt: Date;
406
+ token: string;
407
+ ipAddress?: string | null | undefined;
408
+ userAgent?: string | null | undefined;
409
+ };
410
+ user: Record<string, any> & {
411
+ id: string;
412
+ createdAt: Date;
413
+ updatedAt: Date;
414
+ email: string;
415
+ emailVerified: boolean;
416
+ name: string;
417
+ image?: string | null | undefined;
418
+ };
419
+ };
420
+ }>)[];
421
+ body: z.ZodObject<{
422
+ issuer: z.ZodOptional<z.ZodString>;
423
+ domain: z.ZodOptional<z.ZodString>;
424
+ oidcConfig: z.ZodOptional<z.ZodObject<{
425
+ clientId: z.ZodOptional<z.ZodString>;
426
+ clientSecret: z.ZodOptional<z.ZodString>;
427
+ authorizationEndpoint: z.ZodOptional<z.ZodString>;
428
+ tokenEndpoint: z.ZodOptional<z.ZodString>;
429
+ userInfoEndpoint: z.ZodOptional<z.ZodString>;
430
+ tokenEndpointAuthentication: z.ZodOptional<z.ZodEnum<{
431
+ client_secret_post: "client_secret_post";
432
+ client_secret_basic: "client_secret_basic";
433
+ }>>;
434
+ jwksEndpoint: z.ZodOptional<z.ZodString>;
435
+ discoveryEndpoint: z.ZodOptional<z.ZodString>;
436
+ scopes: z.ZodOptional<z.ZodArray<z.ZodString>>;
437
+ pkce: z.ZodOptional<z.ZodBoolean>;
438
+ overrideUserInfo: z.ZodOptional<z.ZodBoolean>;
439
+ mapping: z.ZodOptional<z.ZodObject<{
440
+ id: z.ZodOptional<z.ZodString>;
441
+ email: z.ZodOptional<z.ZodString>;
442
+ emailVerified: z.ZodOptional<z.ZodString>;
443
+ name: z.ZodOptional<z.ZodString>;
444
+ image: z.ZodOptional<z.ZodString>;
445
+ extraFields: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
446
+ }, z.core.$strip>>;
447
+ }, z.core.$strip>>;
448
+ providerId: z.ZodString;
449
+ }, z.core.$strip>;
450
+ metadata: {
451
+ openapi: {
452
+ operationId: string;
453
+ summary: string;
454
+ description: string;
455
+ responses: {
456
+ "200": {
457
+ description: string;
458
+ };
459
+ "404": {
460
+ description: string;
461
+ };
462
+ "403": {
463
+ description: string;
464
+ };
465
+ };
466
+ };
467
+ };
468
+ }, {
469
+ providerId: string;
470
+ type: "oidc";
471
+ issuer: string;
472
+ domain: string;
473
+ organizationId: string | null;
474
+ domainVerified: boolean;
475
+ oidcConfig: {
476
+ discoveryEndpoint: string;
477
+ clientIdLastFour: string;
478
+ pkce: boolean;
479
+ authorizationEndpoint: string | undefined;
480
+ tokenEndpoint: string | undefined;
481
+ userInfoEndpoint: string | undefined;
482
+ jwksEndpoint: string | undefined;
483
+ scopes: string[] | undefined;
484
+ tokenEndpointAuthentication: "client_secret_post" | "client_secret_basic" | undefined;
485
+ } | undefined;
486
+ }>;
487
+ declare const deleteSSOProvider: () => better_call6.StrictEndpoint<"/sso/delete-provider", {
488
+ method: "POST";
489
+ use: ((inputContext: better_auth9.MiddlewareInputContext<better_auth9.MiddlewareOptions>) => Promise<{
490
+ session: {
491
+ session: Record<string, any> & {
492
+ id: string;
493
+ createdAt: Date;
494
+ updatedAt: Date;
495
+ userId: string;
496
+ expiresAt: Date;
497
+ token: string;
498
+ ipAddress?: string | null | undefined;
499
+ userAgent?: string | null | undefined;
500
+ };
501
+ user: Record<string, any> & {
502
+ id: string;
503
+ createdAt: Date;
504
+ updatedAt: Date;
505
+ email: string;
506
+ emailVerified: boolean;
507
+ name: string;
508
+ image?: string | null | undefined;
509
+ };
510
+ };
511
+ }>)[];
512
+ body: z.ZodObject<{
513
+ providerId: z.ZodString;
514
+ }, z.core.$strip>;
515
+ metadata: {
516
+ openapi: {
517
+ operationId: string;
518
+ summary: string;
519
+ description: string;
520
+ responses: {
521
+ "200": {
522
+ description: string;
523
+ };
524
+ "404": {
525
+ description: string;
526
+ };
527
+ "403": {
528
+ description: string;
529
+ };
530
+ };
531
+ };
532
+ };
533
+ }, {
534
+ success: boolean;
535
+ }>;
536
+ //# sourceMappingURL=providers.d.ts.map
537
+ //#endregion
538
+ //#region src/routes/sso.d.ts
539
+ declare const registerSSOProvider: <O extends SSOOptions>(options: O) => better_call6.StrictEndpoint<"/sso/register", {
540
+ method: "POST";
541
+ body: z.ZodObject<{
542
+ providerId: z.ZodString;
543
+ issuer: z.ZodString;
544
+ domain: z.ZodString;
545
+ oidcConfig: z.ZodObject<{
546
+ clientId: z.ZodString;
547
+ clientSecret: z.ZodString;
548
+ authorizationEndpoint: z.ZodOptional<z.ZodString>;
549
+ tokenEndpoint: z.ZodOptional<z.ZodString>;
550
+ userInfoEndpoint: z.ZodOptional<z.ZodString>;
551
+ tokenEndpointAuthentication: z.ZodOptional<z.ZodEnum<{
552
+ client_secret_post: "client_secret_post";
553
+ client_secret_basic: "client_secret_basic";
554
+ }>>;
555
+ jwksEndpoint: z.ZodOptional<z.ZodString>;
556
+ discoveryEndpoint: z.ZodOptional<z.ZodString>;
557
+ skipDiscovery: z.ZodOptional<z.ZodBoolean>;
558
+ scopes: z.ZodOptional<z.ZodArray<z.ZodString>>;
559
+ pkce: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
560
+ mapping: z.ZodOptional<z.ZodObject<{
561
+ id: z.ZodString;
562
+ email: z.ZodString;
563
+ emailVerified: z.ZodOptional<z.ZodString>;
564
+ name: z.ZodString;
565
+ image: z.ZodOptional<z.ZodString>;
566
+ extraFields: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
567
+ }, z.core.$strip>>;
568
+ }, z.core.$strip>;
569
+ organizationId: z.ZodOptional<z.ZodString>;
570
+ overrideUserInfo: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
571
+ }, z.core.$strip>;
572
+ use: ((inputContext: better_auth9.MiddlewareInputContext<better_auth9.MiddlewareOptions>) => Promise<{
573
+ session: {
574
+ session: Record<string, any> & {
575
+ id: string;
576
+ createdAt: Date;
577
+ updatedAt: Date;
578
+ userId: string;
579
+ expiresAt: Date;
580
+ token: string;
581
+ ipAddress?: string | null | undefined;
582
+ userAgent?: string | null | undefined;
583
+ };
584
+ user: Record<string, any> & {
585
+ id: string;
586
+ createdAt: Date;
587
+ updatedAt: Date;
588
+ email: string;
589
+ emailVerified: boolean;
590
+ name: string;
591
+ image?: string | null | undefined;
592
+ };
593
+ };
594
+ }>)[];
595
+ metadata: {
596
+ openapi: {
597
+ operationId: string;
598
+ summary: string;
599
+ description: string;
600
+ responses: {
601
+ "200": {
602
+ description: string;
603
+ };
604
+ };
605
+ };
606
+ };
607
+ }, O["domainVerification"] extends {
608
+ enabled: true;
609
+ } ? {
610
+ redirectURI: string;
611
+ oidcConfig: OIDCConfig | null;
612
+ } & Omit<SSOProvider<O>, "oidcConfig"> & {
613
+ domainVerified: boolean;
614
+ domainVerificationToken: string;
615
+ } : {
616
+ redirectURI: string;
617
+ oidcConfig: OIDCConfig | null;
618
+ } & Omit<SSOProvider<O>, "oidcConfig">>;
619
+ declare const signInSSO: (options?: SSOOptions) => better_call6.StrictEndpoint<"/sign-in/sso", {
620
+ method: "POST";
621
+ body: z.ZodObject<{
622
+ email: z.ZodOptional<z.ZodString>;
623
+ organizationSlug: z.ZodOptional<z.ZodString>;
624
+ providerId: z.ZodOptional<z.ZodString>;
625
+ domain: z.ZodOptional<z.ZodString>;
626
+ callbackURL: z.ZodString;
627
+ errorCallbackURL: z.ZodOptional<z.ZodString>;
628
+ newUserCallbackURL: z.ZodOptional<z.ZodString>;
629
+ scopes: z.ZodOptional<z.ZodArray<z.ZodString>>;
630
+ loginHint: z.ZodOptional<z.ZodString>;
631
+ requestSignUp: z.ZodOptional<z.ZodBoolean>;
632
+ }, z.core.$strip>;
633
+ metadata: {
634
+ openapi: {
635
+ operationId: string;
636
+ summary: string;
637
+ description: string;
638
+ responses: {
639
+ "200": {
640
+ description: string;
641
+ };
642
+ };
643
+ };
644
+ };
645
+ }, {
646
+ url: string;
647
+ redirect: boolean;
648
+ }>;
649
+ declare const callbackSSO: (options?: SSOOptions) => better_call6.StrictEndpoint<"/sso/callback/:providerId", {
650
+ method: "GET";
651
+ query: z.ZodObject<{
652
+ code: z.ZodOptional<z.ZodString>;
653
+ state: z.ZodString;
654
+ error: z.ZodOptional<z.ZodString>;
655
+ error_description: z.ZodOptional<z.ZodString>;
656
+ }, z.core.$strip>;
657
+ allowedMediaTypes: string[];
658
+ metadata: {
659
+ openapi: {
660
+ operationId: string;
661
+ summary: string;
662
+ description: string;
663
+ responses: {
664
+ "302": {
665
+ description: string;
666
+ };
667
+ };
668
+ };
669
+ scope: "server";
670
+ };
671
+ }, never>;
672
+ //# sourceMappingURL=sso.d.ts.map
673
+ //#endregion
674
+ //#region src/oidc/types.d.ts
675
+ /**
676
+ * OIDC Discovery Types
677
+ *
678
+ * Types for the OIDC discovery document and hydrated configuration.
679
+ * Based on OpenID Connect Discovery 1.0 specification.
680
+ *
681
+ * @see https://openid.net/specs/openid-connect-discovery-1_0.html
682
+ */
683
+ /**
684
+ * Raw OIDC Discovery Document as returned by the IdP's
685
+ * .well-known/openid-configuration endpoint.
686
+ *
687
+ * Required fields for Better Auth's OIDC support:
688
+ * - issuer
689
+ * - authorization_endpoint
690
+ * - token_endpoint
691
+ * - jwks_uri (required for ID token validation)
692
+ *
693
+ */
694
+ interface OIDCDiscoveryDocument {
695
+ /** REQUIRED. URL using the https scheme that the OP asserts as its Issuer Identifier. */
696
+ issuer: string;
697
+ /** REQUIRED. URL of the OP's OAuth 2.0 Authorization Endpoint. */
698
+ authorization_endpoint: string;
699
+ /**
700
+ * REQUIRED (spec says "unless only implicit flow is used").
701
+ * URL of the OP's OAuth 2.0 Token Endpoint.
702
+ * We only support authorization code flow.
703
+ */
704
+ token_endpoint: string;
705
+ /** REQUIRED. URL of the OP's JSON Web Key Set document for ID token validation. */
706
+ jwks_uri: string;
707
+ /** RECOMMENDED. URL of the OP's UserInfo Endpoint. */
708
+ userinfo_endpoint?: string;
709
+ /**
710
+ * OPTIONAL. JSON array containing a list of Client Authentication methods
711
+ * supported by this Token Endpoint.
712
+ * Default: ["client_secret_basic"]
713
+ */
714
+ token_endpoint_auth_methods_supported?: string[];
715
+ /** OPTIONAL. JSON array containing a list of the OAuth 2.0 scope values that this server supports. */
716
+ scopes_supported?: string[];
717
+ /** OPTIONAL. JSON array containing a list of the OAuth 2.0 response_type values that this OP supports. */
718
+ response_types_supported?: string[];
719
+ /** OPTIONAL. JSON array containing a list of the Subject Identifier types that this OP supports. */
720
+ subject_types_supported?: string[];
721
+ /** OPTIONAL. JSON array containing a list of the JWS signing algorithms supported by the OP. */
722
+ id_token_signing_alg_values_supported?: string[];
723
+ /** OPTIONAL. JSON array containing a list of the claim names that the OP may supply values for. */
724
+ claims_supported?: string[];
725
+ /** OPTIONAL. URL of a page containing human-readable information about the OP. */
726
+ service_documentation?: string;
727
+ /** OPTIONAL. Boolean value specifying whether the OP supports use of the claims parameter. */
728
+ claims_parameter_supported?: boolean;
729
+ /** OPTIONAL. Boolean value specifying whether the OP supports use of the request parameter. */
730
+ request_parameter_supported?: boolean;
731
+ /** OPTIONAL. Boolean value specifying whether the OP supports use of the request_uri parameter. */
732
+ request_uri_parameter_supported?: boolean;
733
+ /** OPTIONAL. Boolean value specifying whether the OP requires any request_uri values to be pre-registered. */
734
+ require_request_uri_registration?: boolean;
735
+ /** OPTIONAL. URL of the OP's end session endpoint. */
736
+ end_session_endpoint?: string;
737
+ /** OPTIONAL. URL of the OP's revocation endpoint. */
738
+ revocation_endpoint?: string;
739
+ /** OPTIONAL. URL of the OP's introspection endpoint. */
740
+ introspection_endpoint?: string;
741
+ /** OPTIONAL. JSON array of PKCE code challenge methods supported (e.g., "S256", "plain"). */
742
+ code_challenge_methods_supported?: string[];
743
+ /** Allow additional fields from the discovery document */
744
+ [key: string]: unknown;
745
+ }
746
+ /**
747
+ * Error codes for OIDC discovery operations.
748
+ */
749
+ type DiscoveryErrorCode = /** Request to discovery endpoint timed out */
750
+ "discovery_timeout"
751
+ /** Discovery endpoint returned 404 or similar */ | "discovery_not_found"
752
+ /** Discovery endpoint returned invalid JSON */ | "discovery_invalid_json"
753
+ /** Discovery URL is invalid or malformed */ | "discovery_invalid_url"
754
+ /** Discovery URL is not trusted by the trusted origins configuration */ | "discovery_untrusted_origin"
755
+ /** Discovery document issuer doesn't match configured issuer */ | "issuer_mismatch"
756
+ /** Discovery document is missing required fields */ | "discovery_incomplete"
757
+ /** IdP only advertises token auth methods that Better Auth doesn't currently support */ | "unsupported_token_auth_method"
758
+ /** Catch-all for unexpected errors */ | "discovery_unexpected_error";
759
+ /**
760
+ * Custom error class for OIDC discovery failures.
761
+ * Can be caught and mapped to APIError at the edge.
762
+ */
763
+ declare class DiscoveryError extends Error {
764
+ readonly code: DiscoveryErrorCode;
765
+ readonly details?: Record<string, unknown>;
766
+ constructor(code: DiscoveryErrorCode, message: string, details?: Record<string, unknown>, options?: {
767
+ cause?: unknown;
768
+ });
769
+ }
770
+ /**
771
+ * Hydrated OIDC configuration after discovery.
772
+ * This is the normalized shape that gets persisted to the database
773
+ * or merged into provider config at runtime.
774
+ *
775
+ * Field names are camelCase to match Better Auth conventions.
776
+ */
777
+ interface HydratedOIDCConfig {
778
+ /** The issuer URL (validated to match configured issuer) */
779
+ issuer: string;
780
+ /** The discovery endpoint URL */
781
+ discoveryEndpoint: string;
782
+ /** URL of the authorization endpoint */
783
+ authorizationEndpoint: string;
784
+ /** URL of the token endpoint */
785
+ tokenEndpoint: string;
786
+ /** URL of the JWKS endpoint */
787
+ jwksEndpoint: string;
788
+ /** URL of the userinfo endpoint (optional) */
789
+ userInfoEndpoint?: string;
790
+ /** Token endpoint authentication method */
791
+ tokenEndpointAuthentication?: "client_secret_basic" | "client_secret_post";
792
+ /** Scopes supported by the IdP */
793
+ scopesSupported?: string[];
794
+ }
795
+ /**
796
+ * Parameters for the discoverOIDCConfig function.
797
+ */
798
+ interface DiscoverOIDCConfigParams {
799
+ /** The issuer URL to discover configuration from */
800
+ issuer: string;
801
+ /**
802
+ * Optional existing configuration.
803
+ * Values provided here will override discovered values.
804
+ */
805
+ existingConfig?: Partial<HydratedOIDCConfig>;
806
+ /**
807
+ * Optional custom discovery endpoint URL.
808
+ * If not provided, defaults to <issuer>/.well-known/openid-configuration
809
+ */
810
+ discoveryEndpoint?: string;
811
+ /**
812
+ * Optional timeout in milliseconds for the discovery request.
813
+ * @default 10000 (10 seconds)
814
+ */
815
+ timeout?: number;
816
+ /**
817
+ * Trusted origin predicate. See "trustedOrigins" option
818
+ * @param url the url to test
819
+ * @returns {boolean} return true for urls that belong to a trusted origin and false otherwise
820
+ */
821
+ isTrustedOrigin: (url: string) => boolean;
822
+ }
823
+ /**
824
+ * Required fields that must be present in a valid discovery document.
825
+ */
826
+ declare const REQUIRED_DISCOVERY_FIELDS: readonly ["issuer", "authorization_endpoint", "token_endpoint", "jwks_uri"];
827
+ type RequiredDiscoveryField = (typeof REQUIRED_DISCOVERY_FIELDS)[number];
828
+ //# sourceMappingURL=types.d.ts.map
829
+ //#endregion
830
+ //#region src/oidc/discovery.d.ts
831
+ /**
832
+ * Main entry point: Discover and hydrate OIDC configuration from an issuer.
833
+ *
834
+ * This function:
835
+ * 1. Computes the discovery URL from the issuer
836
+ * 2. Validates the discovery URL
837
+ * 3. Fetches the discovery document
838
+ * 4. Validates the discovery document (issuer match + required fields)
839
+ * 5. Normalizes URLs
840
+ * 6. Selects token endpoint auth method
841
+ * 7. Merges with existing config (existing values take precedence)
842
+ *
843
+ * @param params - Discovery parameters
844
+ * @param isTrustedOrigin - Origin verification tester function
845
+ * @returns Hydrated OIDC configuration ready for persistence
846
+ * @throws DiscoveryError on any failure
847
+ */
848
+ declare function discoverOIDCConfig(params: DiscoverOIDCConfigParams): Promise<HydratedOIDCConfig>;
849
+ /**
850
+ * Compute the discovery URL from an issuer URL.
851
+ *
852
+ * Per OIDC Discovery spec, the discovery document is located at:
853
+ * <issuer>/.well-known/openid-configuration
854
+ *
855
+ * Handles trailing slashes correctly.
856
+ */
857
+ declare function computeDiscoveryUrl(issuer: string): string;
858
+ /**
859
+ * Validate a discovery URL before fetching.
860
+ *
861
+ * @param url - The discovery URL to validate
862
+ * @param isTrustedOrigin - Origin verification tester function
863
+ * @throws DiscoveryError if URL is invalid
864
+ */
865
+ declare function validateDiscoveryUrl(url: string, isTrustedOrigin: DiscoverOIDCConfigParams["isTrustedOrigin"]): void;
866
+ /**
867
+ * Fetch the OIDC discovery document from the IdP.
868
+ *
869
+ * @param url - The discovery endpoint URL
870
+ * @param timeout - Request timeout in milliseconds
871
+ * @returns The parsed discovery document
872
+ * @throws DiscoveryError on network errors, timeouts, or invalid responses
873
+ */
874
+ declare function fetchDiscoveryDocument(url: string, timeout?: number): Promise<OIDCDiscoveryDocument>;
875
+ /**
876
+ * Validate a discovery document.
877
+ *
878
+ * Checks:
879
+ * 1. All required fields are present
880
+ * 2. Issuer matches the configured issuer (case-sensitive, exact match)
881
+ *
882
+ * Invariant: If this function returns without throwing, the document is safe
883
+ * to use for hydrating OIDC config (required fields present, issuer matches
884
+ * configured value, basic structural sanity verified).
885
+ *
886
+ * @param doc - The discovery document to validate
887
+ * @param configuredIssuer - The expected issuer value
888
+ * @throws DiscoveryError if validation fails
889
+ */
890
+ declare function validateDiscoveryDocument(doc: OIDCDiscoveryDocument, configuredIssuer: string): void;
891
+ /**
892
+ * Normalize URLs in the discovery document.
893
+ *
894
+ * @param document - The discovery document
895
+ * @param issuer - The base issuer URL
896
+ * @param isTrustedOrigin - Origin verification tester function
897
+ * @returns The normalized discovery document
898
+ */
899
+ declare function normalizeDiscoveryUrls(document: OIDCDiscoveryDocument, issuer: string, isTrustedOrigin: DiscoverOIDCConfigParams["isTrustedOrigin"]): OIDCDiscoveryDocument;
900
+ /**
901
+ * Normalize a single URL endpoint.
902
+ *
903
+ * @param name - The endpoint name (e.g token_endpoint)
904
+ * @param endpoint - The endpoint URL to normalize
905
+ * @param issuer - The base issuer URL
906
+ * @returns The normalized endpoint URL
907
+ */
908
+ declare function normalizeUrl(name: string, endpoint: string, issuer: string): string;
909
+ /**
910
+ * Select the token endpoint authentication method.
911
+ *
912
+ * @param doc - The discovery document
913
+ * @param existing - Existing authentication method from config
914
+ * @returns The selected authentication method
915
+ */
916
+ declare function selectTokenEndpointAuthMethod(doc: OIDCDiscoveryDocument, existing?: "client_secret_basic" | "client_secret_post"): "client_secret_basic" | "client_secret_post";
917
+ /**
918
+ * Check if a provider configuration needs runtime discovery.
919
+ *
920
+ * Returns true if we need discovery at runtime to complete the token exchange
921
+ * and validation. Specifically checks for:
922
+ * - `tokenEndpoint` - required for exchanging authorization code for tokens
923
+ * - `jwksEndpoint` - required for validating ID token signatures
924
+ *
925
+ * Note: `authorizationEndpoint` is handled separately in the sign-in flow,
926
+ * so it's not checked here.
927
+ *
928
+ * @param config - Partial OIDC config from the provider
929
+ * @returns true if runtime discovery should be performed
930
+ */
931
+ declare function needsRuntimeDiscovery(config: Partial<HydratedOIDCConfig> | undefined): boolean;
932
+ //# sourceMappingURL=discovery.d.ts.map
933
+
934
+ //#endregion
935
+ export { updateSSOProvider as C, SSOOptions as D, OIDCConfig as E, SSOProvider as O, listSSOProviders as S, verifyDomain as T, callbackSSO as _, normalizeDiscoveryUrls as a, deleteSSOProvider as b, validateDiscoveryDocument as c, DiscoveryError as d, DiscoveryErrorCode as f, RequiredDiscoveryField as g, REQUIRED_DISCOVERY_FIELDS as h, needsRuntimeDiscovery as i, validateDiscoveryUrl as l, OIDCDiscoveryDocument as m, discoverOIDCConfig as n, normalizeUrl as o, HydratedOIDCConfig as p, fetchDiscoveryDocument as r, selectTokenEndpointAuthMethod as s, computeDiscoveryUrl as t, DiscoverOIDCConfigParams as u, registerSSOProvider as v, requestDomainVerification as w, getSSOProvider as x, signInSSO as y };
936
+ //# sourceMappingURL=discovery.d.ts.map