@lunora/auth 1.0.0-alpha.9 → 1.0.0-alpha.91

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.
Files changed (69) hide show
  1. package/LICENSE.md +38 -0
  2. package/README.md +56 -1
  3. package/dist/adapter.d.mts +4 -43
  4. package/dist/adapter.d.ts +4 -43
  5. package/dist/adapter.mjs +1 -47
  6. package/dist/audit.d.mts +131 -0
  7. package/dist/audit.d.ts +131 -0
  8. package/dist/audit.mjs +12 -0
  9. package/dist/email-guard.d.mts +125 -0
  10. package/dist/email-guard.d.ts +125 -0
  11. package/dist/email-guard.mjs +1 -0
  12. package/dist/index.d.mts +713 -147
  13. package/dist/index.d.ts +713 -147
  14. package/dist/index.mjs +1 -12
  15. package/dist/middleware.d.mts +157 -156
  16. package/dist/middleware.d.ts +157 -156
  17. package/dist/middleware.mjs +1 -53
  18. package/dist/packem_shared/AUTH_DO_AUDIT_PATH-D-RB2XYs.mjs +1 -0
  19. package/dist/packem_shared/DEFAULT_AUTH_BASE_PATH-DneiLGpv.mjs +1 -0
  20. package/dist/packem_shared/LunoraAuthAdminError-DtAKa22S.mjs +1 -0
  21. package/dist/packem_shared/adapter-DA8DdALX.mjs +1 -0
  22. package/dist/packem_shared/adapter.d-2a61HAY2.d.ts +76 -0
  23. package/dist/packem_shared/adapter.d-DrD3bb1u.d.mts +76 -0
  24. package/dist/packem_shared/authAuditHook-tG8gdR77.mjs +1 -0
  25. package/dist/packem_shared/authDoColumnAdditions-BCSs7qaN.mjs +1 -0
  26. package/dist/packem_shared/compileMigrationsSql-Y1YB3maO.mjs +1 -0
  27. package/dist/packem_shared/create-auth.d-De6IOirt.d.mts +128 -0
  28. package/dist/packem_shared/create-auth.d-De6IOirt.d.ts +128 -0
  29. package/dist/packem_shared/createAuth-DYFhkI1U.mjs +1 -0
  30. package/dist/packem_shared/createDoAuthWiring-C8H_SGCq.mjs +1 -0
  31. package/dist/packem_shared/createLunoraAuthClient-DhjhCwmM.mjs +1 -0
  32. package/dist/packem_shared/emailGateDatabaseHooks-CAygR3iq.mjs +1 -0
  33. package/dist/packem_shared/sessionPresets-C867Mlo4.mjs +1 -0
  34. package/dist/packem_shared/uiConfig-B8pN6pks.mjs +1 -0
  35. package/dist/plugins-client.d.mts +165 -1
  36. package/dist/plugins-client.d.ts +165 -1
  37. package/dist/plugins-client.mjs +1 -2
  38. package/dist/plugins-enterprise-client.d.mts +15 -0
  39. package/dist/plugins-enterprise-client.d.ts +15 -0
  40. package/dist/plugins-enterprise-client.mjs +1 -0
  41. package/dist/plugins-enterprise.d.mts +1670 -0
  42. package/dist/plugins-enterprise.d.ts +1670 -0
  43. package/dist/plugins-enterprise.mjs +1 -0
  44. package/dist/plugins.d.mts +102 -2
  45. package/dist/plugins.d.ts +102 -2
  46. package/dist/plugins.mjs +1 -22
  47. package/dist/schema.d.mts +39 -39
  48. package/dist/schema.d.ts +39 -39
  49. package/dist/schema.mjs +1 -62
  50. package/dist/sql-store.d.mts +28 -28
  51. package/dist/sql-store.d.ts +28 -28
  52. package/dist/sql-store.mjs +1 -162
  53. package/dist/store.d.mts +49 -31
  54. package/dist/store.d.ts +49 -31
  55. package/dist/store.mjs +1 -170
  56. package/dist/turnstile-middleware.d.mts +55 -55
  57. package/dist/turnstile-middleware.d.ts +55 -55
  58. package/dist/turnstile-middleware.mjs +1 -45
  59. package/dist/turnstile.d.mts +42 -59
  60. package/dist/turnstile.d.ts +42 -59
  61. package/dist/turnstile.mjs +1 -61
  62. package/package.json +39 -5
  63. package/dist/packem_shared/DEFAULT_AUTH_BASE_PATH-DjcUWEQl.mjs +0 -11
  64. package/dist/packem_shared/LunoraAuthAdminError-BxrfEeA_.mjs +0 -249
  65. package/dist/packem_shared/compileMigrationsSql-wZH3oXDu.mjs +0 -28
  66. package/dist/packem_shared/create-auth.d-M36jwG_Y.d.mts +0 -58
  67. package/dist/packem_shared/create-auth.d-M36jwG_Y.d.ts +0 -58
  68. package/dist/packem_shared/createAuth-B-tvsvQU.mjs +0 -56
  69. package/dist/packem_shared/sessionPresets-B95rXrd8.mjs +0 -35
@@ -0,0 +1,1670 @@
1
+ import * as z from 'zod';
2
+ import { DBFieldAttribute, RemoveFieldsWithReturnedFalse, FieldAttributeToObject, InferAdditionalFieldsFromPluginOptions } from 'better-auth/db';
3
+ import { DBTransactionAdapter, Awaitable, User, OAuth2Tokens } from 'better-auth';
4
+ import * as _$better_call0 from 'better-call';
5
+ type DeprecatedAlgorithmBehavior = "reject" | "warn" | "allow";
6
+ interface AlgorithmValidationOptions {
7
+ onDeprecated?: DeprecatedAlgorithmBehavior;
8
+ allowedSignatureAlgorithms?: string[];
9
+ allowedDigestAlgorithms?: string[];
10
+ allowedKeyEncryptionAlgorithms?: string[];
11
+ allowedDataEncryptionAlgorithms?: string[];
12
+ }
13
+ //#endregion
14
+ //#region src/types.d.ts
15
+ interface OIDCMapping {
16
+ email?: string | undefined;
17
+ emailVerified?: string | undefined;
18
+ name?: string | undefined;
19
+ image?: string | undefined;
20
+ extraFields?: Record<string, string> | undefined;
21
+ }
22
+ interface SAMLMapping {
23
+ email?: string | undefined;
24
+ emailVerified?: string | undefined;
25
+ name?: string | undefined;
26
+ firstName?: string | undefined;
27
+ lastName?: string | undefined;
28
+ extraFields?: Record<string, string> | undefined;
29
+ }
30
+ interface OIDCConfig {
31
+ issuer: string;
32
+ pkce: boolean;
33
+ clientId: string;
34
+ /** Required for client_secret_basic/client_secret_post. Optional for private_key_jwt. */
35
+ clientSecret?: string;
36
+ authorizationEndpoint?: string | undefined;
37
+ discoveryEndpoint: string;
38
+ userInfoEndpoint?: string | undefined;
39
+ scopes?: string[] | undefined;
40
+ overrideUserInfo?: boolean | undefined;
41
+ tokenEndpoint?: string | undefined;
42
+ tokenEndpointAuthentication?: ("client_secret_post" | "client_secret_basic" | "private_key_jwt") | undefined;
43
+ /** Key ID for private_key_jwt key resolution */
44
+ privateKeyId?: string | undefined;
45
+ /** Signing algorithm for private_key_jwt. @default "RS256" */
46
+ privateKeyAlgorithm?: string | undefined;
47
+ jwksEndpoint?: string | undefined;
48
+ mapping?: OIDCMapping | undefined;
49
+ /**
50
+ * Accept callbacks from OIDC providers that initiate the OAuth flow
51
+ * without sending a `state` parameter. When enabled, stateless callbacks
52
+ * restart the OAuth flow server-side with a fresh `state` and PKCE
53
+ * verifier. See the SSO docs for details.
54
+ *
55
+ * @default false
56
+ */
57
+ allowIdpInitiated?: boolean | undefined;
58
+ }
59
+ interface SAMLIdentityProviderMetadataBase {
60
+ /**
61
+ * IdP signing certificate(s). Pass a single PEM string or an array for
62
+ * rolling rotation. Takes precedence over the top-level `cert` when both
63
+ * are set. Omit when `metadata` XML is supplied.
64
+ */
65
+ cert?: string | string[] | undefined;
66
+ privateKey?: string | undefined;
67
+ privateKeyPass?: string | undefined;
68
+ isAssertionEncrypted?: boolean | undefined;
69
+ encPrivateKey?: string | undefined;
70
+ encPrivateKeyPass?: string | undefined;
71
+ singleSignOnService?: Array<{
72
+ Binding: string;
73
+ Location: string;
74
+ }> | undefined;
75
+ singleLogoutService?: Array<{
76
+ Binding: string;
77
+ Location: string;
78
+ }> | undefined;
79
+ }
80
+ /**
81
+ * The trusted identity-provider authority for a SAML connection.
82
+ *
83
+ * Metadata XML carries the IdP entity ID. Manual configurations must declare
84
+ * `entityID` explicitly so the service provider's issuer is never mistaken
85
+ * for the identity provider's authority.
86
+ */
87
+ type SAMLIdentityProviderMetadata = SAMLIdentityProviderMetadataBase & ({
88
+ metadata: string;
89
+ entityID?: string | undefined;
90
+ } | {
91
+ metadata?: undefined;
92
+ entityID: string;
93
+ });
94
+ interface SAMLConfig {
95
+ /**
96
+ * SP Entity ID. Used as the `entityID` in SP metadata when
97
+ * `spMetadata.entityID` is not set. Also used as the expected
98
+ * audience for SAML assertion validation when `audience` is not set.
99
+ */
100
+ issuer: string;
101
+ /**
102
+ * IdP SSO URL. Used as the redirect destination when
103
+ * `idpMetadata.metadata` is not provided. Ignored when
104
+ * IdP metadata XML is set (the SSO URL is extracted from the XML).
105
+ */
106
+ entryPoint: string;
107
+ /**
108
+ * IdP signing certificate(s). Used to verify SAML response signatures when
109
+ * `idpMetadata.metadata` is not provided. Ignored when IdP metadata XML is
110
+ * set (the certificate is extracted from the XML). When both this and
111
+ * `idpMetadata.cert` are set, `idpMetadata.cert` takes precedence. Pass an
112
+ * array of PEM strings for rolling rotation; responses signed by any
113
+ * listed cert are accepted.
114
+ */
115
+ cert?: string | string[];
116
+ audience?: string | undefined;
117
+ /**
118
+ * Provider-level post-auth redirect URL for IdP-initiated or fallback SAML
119
+ * flows when no RelayState callback URL is available.
120
+ */
121
+ callbackUrl?: string | undefined;
122
+ /**
123
+ * Fallback absolute URL or same-origin relative path for IdP-initiated SAML
124
+ * responses when RelayState has no safe callback, including error redirects.
125
+ */
126
+ idpInitiatedCallbackUrl?: string | undefined;
127
+ idpMetadata: SAMLIdentityProviderMetadata;
128
+ /**
129
+ * SP metadata configuration. All fields are optional; when omitted,
130
+ * SP metadata is auto-generated from `issuer`, `wantAssertionsSigned`,
131
+ * `authnRequestsSigned`, and `identifierFormat`.
132
+ */
133
+ spMetadata?: {
134
+ metadata?: string | undefined;
135
+ entityID?: string | undefined;
136
+ binding?: string | undefined;
137
+ privateKey?: string | undefined;
138
+ privateKeyPass?: string | undefined;
139
+ isAssertionEncrypted?: boolean | undefined;
140
+ encPrivateKey?: string | undefined;
141
+ encPrivateKeyPass?: string | undefined;
142
+ };
143
+ /**
144
+ * Request and require signed assertions from the IdP. When true, generated
145
+ * SP metadata advertises `WantAssertionsSigned="true"` and the ACS rejects
146
+ * unsigned assertions. Custom SP metadata supplies the effective policy and
147
+ * accepts the XML Schema boolean forms `true`, `false`, `1`, and `0`.
148
+ */
149
+ wantAssertionsSigned?: boolean | undefined;
150
+ authnRequestsSigned?: boolean | undefined;
151
+ signatureAlgorithm?: string | undefined;
152
+ digestAlgorithm?: string | undefined;
153
+ identifierFormat?: string | undefined;
154
+ privateKey?: string | undefined;
155
+ mapping?: SAMLMapping | undefined;
156
+ }
157
+ type BaseSSOProvider = {
158
+ issuer: string;
159
+ oidcConfig?: OIDCConfig | undefined;
160
+ samlConfig?: SAMLConfig | undefined;
161
+ userId: string;
162
+ providerId: string;
163
+ organizationId?: string | undefined;
164
+ domain: string;
165
+ };
166
+ type SSOProviderAdditionalFields<O extends SSOOptions, IsClientSide extends boolean> = O["schema"] extends {
167
+ ssoProvider?: {
168
+ additionalFields: infer Field extends Record<string, DBFieldAttribute>;
169
+ };
170
+ } ? IsClientSide extends true ? FieldAttributeToObject<RemoveFieldsWithReturnedFalse<Field>> : FieldAttributeToObject<Field> : {};
171
+ type SSOProviderAdditionalFieldsInput<O extends SSOOptions, IsClientSide extends boolean = true> = InferAdditionalFieldsFromPluginOptions<"ssoProvider", O, IsClientSide>;
172
+ type InferSSOProvider<O extends SSOOptions, IsClientSide extends boolean = true> = (O["domainVerification"] extends {
173
+ enabled: true;
174
+ } ? {
175
+ domainVerified: boolean;
176
+ } & BaseSSOProvider : BaseSSOProvider) & SSOProviderAdditionalFields<O, IsClientSide>;
177
+ type SSOProvider<O extends SSOOptions> = O["domainVerification"] extends {
178
+ enabled: true;
179
+ } ? {
180
+ domainVerified: boolean;
181
+ } & BaseSSOProvider & SSOProviderAdditionalFields<O, false> : BaseSSOProvider & SSOProviderAdditionalFields<O, false>;
182
+ type SSOProviderSchema<O extends SSOOptions> = {
183
+ ssoProvider: {
184
+ modelName: string;
185
+ fields: Record<string, DBFieldAttribute> & (O["schema"] extends {
186
+ ssoProvider?: {
187
+ additionalFields: infer Field extends Record<string, DBFieldAttribute>;
188
+ };
189
+ } ? Field : {});
190
+ };
191
+ };
192
+ /** Decision returned by an SSO user resolver. */
193
+ type SSOUserResolution = {
194
+ action: "continue";
195
+ } | {
196
+ action: "link";
197
+ userId: string;
198
+ profile: "preserve" | "update";
199
+ } | {
200
+ action: "reject";
201
+ code: string;
202
+ message?: string | undefined;
203
+ };
204
+ /** Normalized provider attributes available to an SSO user resolver. */
205
+ type SSOProviderUserProfile = {
206
+ email: string;
207
+ emailVerified: boolean;
208
+ name: string;
209
+ image?: string | null | undefined;
210
+ } & Record<string, unknown>;
211
+ /**
212
+ * Opaque reference to the SSO provider configuration accepted for the current
213
+ * authentication flow.
214
+ *
215
+ * This reference is a transient authentication fence. Applications must not
216
+ * persist it as a tenant or user binding.
217
+ */
218
+ interface SSOProviderReference {
219
+ providerId: string;
220
+ source: {
221
+ type: "configured";
222
+ } | {
223
+ type: "persisted";
224
+ recordId: string;
225
+ };
226
+ authenticationConfigurationFingerprint: string;
227
+ }
228
+ interface BaseSSOUserResolutionInput {
229
+ providerId: string;
230
+ accountKey: {
231
+ issuer: string;
232
+ accountId: string;
233
+ };
234
+ providerUser: SSOProviderUserProfile;
235
+ providerReference: SSOProviderReference;
236
+ }
237
+ /** OIDC identity and profile data available to an application's SSO resolver. */
238
+ interface SSOOIDCUserResolutionInput extends BaseSSOUserResolutionInput {
239
+ protocol: "oidc";
240
+ /** Raw claims from UserInfo, or the verified ID Token when UserInfo is absent. */
241
+ providerClaims: Record<string, unknown>;
242
+ /** Claims from the cryptographically verified ID Token. */
243
+ verifiedIdTokenClaims: Record<string, unknown>;
244
+ }
245
+ /** SAML identity and assertion data available to an application's SSO resolver. */
246
+ interface SSOSAMLUserResolutionInput extends BaseSSOUserResolutionInput {
247
+ protocol: "saml";
248
+ /**
249
+ * Attributes from the verified assertion. Multi-valued attributes remain
250
+ * arrays and all scalar values remain strings.
251
+ */
252
+ providerAttributes: Record<string, string | readonly string[]>;
253
+ }
254
+ /** Verified SSO identity and provider data available to an application resolver. */
255
+ type SSOUserResolutionInput = SSOOIDCUserResolutionInput | SSOSAMLUserResolutionInput;
256
+ /** Transaction-bound capabilities available while resolving an SSO user. */
257
+ interface SSOUserResolutionContext {
258
+ database: DBTransactionAdapter;
259
+ }
260
+ interface BaseSSOProviderMutationGuardInput {
261
+ provider: {
262
+ id: string;
263
+ providerId: string;
264
+ organizationId: string | null;
265
+ };
266
+ /**
267
+ * Opaque reference to the exact locked provider configuration.
268
+ *
269
+ * This value is transient and must not be persisted as a tenant binding.
270
+ */
271
+ providerReference: SSOProviderReference;
272
+ }
273
+ /** Mutation attempted against one exact persisted SSO provider row. */
274
+ type SSOProviderMutationGuardInput = (BaseSSOProviderMutationGuardInput & {
275
+ action: "update";
276
+ /**
277
+ * True when the validated proposal changes provider identity,
278
+ * routing, or verification policy used to authenticate accounts.
279
+ */
280
+ isAuthenticationBoundaryChange: boolean;
281
+ }) | (BaseSSOProviderMutationGuardInput & {
282
+ action: "delete";
283
+ });
284
+ /** Transaction-bound context for guarding a persisted provider mutation. */
285
+ interface SSOProviderMutationGuardContext {
286
+ database: DBTransactionAdapter;
287
+ }
288
+ interface SSOOptions {
289
+ /**
290
+ * Resolve a verified provider identity to a Better Auth user.
291
+ *
292
+ * For OIDC, `accountKey` is derived from the validated ID Token. For SAML,
293
+ * it contains the verified IdP entity ID and signed NameID. Profile fields,
294
+ * raw OIDC claims, and SAML assertion attributes are protocol-accepted
295
+ * provider data and may require application-level validation.
296
+ *
297
+ * The callback runs on every SSO sign-in inside the same native database
298
+ * transaction as account finalization and session creation.
299
+ */
300
+ resolveUser?: ((input: SSOUserResolutionInput, context: SSOUserResolutionContext) => Awaitable<SSOUserResolution>) | undefined;
301
+ /**
302
+ * Guards updates and deletion of an exact persisted SSO provider.
303
+ *
304
+ * The callback runs after the provider row is locked and before any provider
305
+ * or linked Account mutation. Update inputs disclose only whether the
306
+ * validated proposal changes the authentication boundary; proposed secrets
307
+ * and configuration values are never exposed. Throw to reject the mutation.
308
+ * Better Auth converts callback failures into a stable conflict response.
309
+ */
310
+ guardProviderMutation?: ((input: SSOProviderMutationGuardInput, context: SSOProviderMutationGuardContext) => Awaitable<void>) | undefined;
311
+ /**
312
+ * custom function to provision a user when they sign in with an SSO provider.
313
+ */
314
+ provisionUser?: ((data: {
315
+ /**
316
+ * The user object from the database
317
+ */
318
+ user: User & Record<string, any>;
319
+ /**
320
+ * The user info object from the provider
321
+ */
322
+ userInfo: Record<string, any>;
323
+ /**
324
+ * The OAuth2 tokens from the provider
325
+ */
326
+ token?: OAuth2Tokens;
327
+ /**
328
+ * The SSO provider
329
+ */
330
+ provider: SSOProvider<SSOOptions>;
331
+ }) => Awaitable<void>) | undefined;
332
+ /**
333
+ * If true, the `provisionUser` callback will be called on every login,
334
+ * not just when a new user is registered. This is useful when you need
335
+ * to sync upstream identity provider profile changes on each sign-in.
336
+ *
337
+ * The `provisionUser` callback should be idempotent when this is enabled.
338
+ *
339
+ * @default false
340
+ */
341
+ provisionUserOnEveryLogin?: boolean;
342
+ /**
343
+ * Organization provisioning options
344
+ */
345
+ organizationProvisioning?: {
346
+ disabled?: boolean;
347
+ defaultRole?: "member" | "admin";
348
+ getRole?: (data: {
349
+ /**
350
+ * The user object from the database
351
+ */
352
+ user: User & Record<string, any>;
353
+ /**
354
+ * The user info object from the provider
355
+ */
356
+ userInfo: Record<string, any>;
357
+ /**
358
+ * The OAuth2 tokens from the provider
359
+ */
360
+ token?: OAuth2Tokens;
361
+ /**
362
+ * The SSO provider
363
+ */
364
+ provider: SSOProvider<SSOOptions>;
365
+ }) => Promise<"member" | "admin">;
366
+ } | undefined;
367
+ /**
368
+ * Default SSO provider configurations for testing.
369
+ * These will take the precedence over the database providers.
370
+ */
371
+ defaultSSO?: Array<{
372
+ /**
373
+ * The domain to match for this default provider.
374
+ * This is only used to match incoming requests to this default provider.
375
+ */
376
+ domain: string;
377
+ /**
378
+ * The provider ID to use
379
+ */
380
+ providerId: string;
381
+ /**
382
+ * SAML configuration
383
+ */
384
+ samlConfig?: SAMLConfig;
385
+ /**
386
+ * OIDC configuration
387
+ */
388
+ oidcConfig?: OIDCConfig;
389
+ /**
390
+ * Private key for `private_key_jwt` authentication.
391
+ * Only used with defaultSSO — not stored in DB.
392
+ */
393
+ privateKey?: {
394
+ privateKeyJwk?: JsonWebKey;
395
+ privateKeyPem?: string;
396
+ };
397
+ }> | undefined;
398
+ /**
399
+ * Override user info with the provider info.
400
+ * @default false
401
+ */
402
+ defaultOverrideUserInfo?: boolean | undefined;
403
+ /**
404
+ * Disable implicit sign up for new users. When set to true for the provider,
405
+ * sign-in need to be called with with requestSignUp as true to create new users.
406
+ */
407
+ disableImplicitSignUp?: boolean | undefined;
408
+ /**
409
+ * The model name for the SSO provider table. Defaults to "ssoProvider".
410
+ */
411
+ modelName?: string;
412
+ /**
413
+ * Map fields
414
+ *
415
+ * @example
416
+ * ```ts
417
+ * {
418
+ * samlConfig: "saml_config"
419
+ * }
420
+ * ```
421
+ */
422
+ fields?: {
423
+ issuer?: string | undefined;
424
+ oidcConfig?: string | undefined;
425
+ samlConfig?: string | undefined;
426
+ userId?: string | undefined;
427
+ providerId?: string | undefined;
428
+ organizationId?: string | undefined;
429
+ domain?: string | undefined;
430
+ };
431
+ /**
432
+ * The schema for the SSO plugin.
433
+ */
434
+ schema?: {
435
+ ssoProvider?: {
436
+ modelName?: string | undefined;
437
+ fields?: {
438
+ issuer?: string | undefined;
439
+ oidcConfig?: string | undefined;
440
+ samlConfig?: string | undefined;
441
+ userId?: string | undefined;
442
+ providerId?: string | undefined;
443
+ organizationId?: string | undefined;
444
+ domain?: string | undefined;
445
+ domainVerified?: string | undefined;
446
+ };
447
+ additionalFields?: { [key in string]: DBFieldAttribute; };
448
+ };
449
+ } | undefined;
450
+ /**
451
+ * Configure the maximum number of SSO providers a user can register.
452
+ * You can also pass a function that returns a number.
453
+ * Set to 0 to disable SSO provider registration.
454
+ *
455
+ * @example
456
+ * ```ts
457
+ * providersLimit: async (user) => {
458
+ * const plan = await getUserPlan(user);
459
+ * return plan.name === "pro" ? 10 : 1;
460
+ * }
461
+ * ```
462
+ * @default 10
463
+ */
464
+ providersLimit?: (number | ((user: User) => Awaitable<number>)) | undefined;
465
+ /**
466
+ * Trust the email verified flag from the provider.
467
+ *
468
+ * ⚠️ Use this with caution — it can lead to account takeover if misused. Only enable it if users **cannot freely register new providers**. You can
469
+ * prevent that by using `disabledPaths` or other safeguards to block provider registration from the client.
470
+ *
471
+ * If you want to allow account linking for specific trusted providers, enable the `accountLinking` option in your auth config and specify those
472
+ * providers in the `trustedProviders` list.
473
+ *
474
+ * @default false
475
+ *
476
+ * @deprecated This option is discouraged for new projects. Relying on provider-level `email_verified` is a weaker
477
+ * trust signal compared to using `trustedProviders` in `accountLinking` or enabling `domainVerification` for SSO.
478
+ * Existing configurations will continue to work, but new integrations should use explicit trust mechanisms.
479
+ * This option may be removed in a future major version.
480
+ */
481
+ trustEmailVerified?: boolean | undefined;
482
+ /**
483
+ * Enable domain verification on SSO providers
484
+ *
485
+ * When this option is enabled, new SSO providers will require the associated domain to be verified by the owner
486
+ * prior to allowing sign-ins.
487
+ */
488
+ domainVerification?: {
489
+ /**
490
+ * Enables or disables the domain verification feature
491
+ */
492
+ enabled?: boolean;
493
+ /**
494
+ * Prefix used to generate the domain verification token.
495
+ * An underscore is automatically prepended to follow DNS
496
+ * infrastructure subdomain conventions (RFC 8552), so do
497
+ * not include a leading underscore.
498
+ *
499
+ * @default "better-auth-token"
500
+ */
501
+ tokenPrefix?: string;
502
+ };
503
+ /**
504
+ * A shared redirect URI used by all OIDC providers instead of
505
+ * per-provider callback URLs. Can be a path or a full URL.
506
+ */
507
+ redirectURI?: string;
508
+ /**
509
+ * Callback to resolve private key material for private_key_jwt authentication.
510
+ * Called during token exchange when a provider uses tokenEndpointAuthentication: "private_key_jwt".
511
+ * Keeps private keys out of the database — supports HSM/KMS/Vault integration.
512
+ */
513
+ resolvePrivateKey?: (params: {
514
+ providerId: string;
515
+ keyId?: string;
516
+ issuer: string;
517
+ }) => Promise<{
518
+ privateKeyJwk?: JsonWebKey;
519
+ privateKeyPem?: string;
520
+ kid?: string;
521
+ algorithm?: string;
522
+ }>;
523
+ /**
524
+ * SAML security options for AuthnRequest/InResponseTo validation.
525
+ * This prevents unsolicited responses, replay attacks, and cross-provider injection.
526
+ */
527
+ saml?: {
528
+ /**
529
+ * Enable InResponseTo validation for SP-initiated SAML flows.
530
+ * When enabled, AuthnRequest IDs are tracked and validated against SAML responses.
531
+ *
532
+ * Storage behavior:
533
+ * - Uses `secondaryStorage` (e.g., Redis) if configured in your auth options
534
+ * - Falls back to the verification table in the database otherwise
535
+ *
536
+ * This works correctly in serverless environments without any additional configuration.
537
+ *
538
+ * @default true
539
+ */
540
+ enableInResponseToValidation?: boolean;
541
+ /**
542
+ * Allow IdP-initiated SSO (unsolicited SAML responses).
543
+ * When true, responses without InResponseTo are accepted.
544
+ * When false, all responses must correlate to a stored AuthnRequest.
545
+ *
546
+ * IdP-initiated SSO is a known attack vector — the SAML2Int
547
+ * interoperability profile recommends against it. Only enable
548
+ * this if your IdP requires it and you understand the risks.
549
+ *
550
+ * Only applies when InResponseTo validation is enabled.
551
+ *
552
+ * @default false
553
+ */
554
+ allowIdpInitiated?: boolean;
555
+ /**
556
+ * TTL for AuthnRequest records in milliseconds.
557
+ * Requests older than this will be rejected.
558
+ *
559
+ * Only applies when InResponseTo validation is enabled.
560
+ *
561
+ * @default 300000 (5 minutes)
562
+ */
563
+ requestTTL?: number;
564
+ /**
565
+ * Clock skew tolerance for SAML assertion timestamp validation in milliseconds.
566
+ * Allows for minor time differences between IdP and SP servers.
567
+ *
568
+ * Defaults to 300000 (5 minutes) to accommodate:
569
+ * - Network latency and processing time
570
+ * - Clock synchronization differences (NTP drift)
571
+ * - Distributed systems across timezones
572
+ *
573
+ * For stricter security, reduce to 1-2 minutes (60000-120000).
574
+ * For highly distributed systems, increase up to 10 minutes (600000).
575
+ *
576
+ * @default 300000 (5 minutes)
577
+ */
578
+ clockSkew?: number;
579
+ /**
580
+ * Require timestamp conditions (NotBefore/NotOnOrAfter) in SAML assertions.
581
+ * When enabled, assertions without timestamp conditions will be rejected.
582
+ *
583
+ * When disabled (default), assertions without timestamps are accepted
584
+ * but a warning is logged.
585
+ *
586
+ * **SAML Spec Notes:**
587
+ * - SAML 2.0 Core: Timestamps are OPTIONAL
588
+ * - SAML2Int (enterprise profile): Timestamps are REQUIRED
589
+ *
590
+ * **Recommendation:** Enable for enterprise/production deployments
591
+ * where your IdP follows SAML2Int (Okta, Azure AD, OneLogin, etc.)
592
+ *
593
+ * @default false
594
+ */
595
+ requireTimestamps?: boolean;
596
+ /**
597
+ * Algorithm validation options for SAML responses.
598
+ *
599
+ * Controls behavior when deprecated algorithms (SHA-1, RSA1_5, 3DES)
600
+ * are detected in SAML responses.
601
+ *
602
+ * @example
603
+ * ```ts
604
+ * algorithms: {
605
+ * onDeprecated: "reject" // Reject deprecated algorithms
606
+ * }
607
+ * ```
608
+ */
609
+ algorithms?: AlgorithmValidationOptions;
610
+ /**
611
+ * Maximum allowed size for SAML responses in bytes.
612
+ *
613
+ * @default 262144 (256KB)
614
+ */
615
+ maxResponseSize?: number;
616
+ /**
617
+ * Maximum allowed size for IdP or SP metadata XML in bytes.
618
+ *
619
+ * @default 102400 (100KB)
620
+ */
621
+ maxMetadataSize?: number;
622
+ /**
623
+ * Enable SAML Single Logout
624
+ * @default false
625
+ */
626
+ enableSingleLogout?: boolean;
627
+ /**
628
+ * TTL for LogoutRequest records in milliseconds
629
+ * @default 300000 (5 minutes)
630
+ */
631
+ logoutRequestTTL?: number;
632
+ /**
633
+ * Require signed LogoutRequests from IdP
634
+ * @default false
635
+ */
636
+ wantLogoutRequestSigned?: boolean;
637
+ /**
638
+ * Require signed LogoutResponses from IdP
639
+ * @default false
640
+ */
641
+ wantLogoutResponseSigned?: boolean;
642
+ /**
643
+ * Global fallback absolute URL or same-origin relative path for
644
+ * IdP-initiated SAML responses when the provider has no safe callback.
645
+ */
646
+ idpInitiatedCallbackUrl?: string | undefined;
647
+ };
648
+ }
649
+ //#endregion
650
+ //#region src/routes/domain-verification.d.ts
651
+ declare const requestDomainVerification: (options: SSOOptions) => _$better_call0.StrictEndpoint<"/sso/request-domain-verification", {
652
+ method: "POST";
653
+ body: z.ZodObject<{
654
+ providerId: z.ZodString;
655
+ }, z.core.$strip>;
656
+ metadata: {
657
+ openapi: {
658
+ summary: string;
659
+ description: string;
660
+ responses: {
661
+ "404": {
662
+ description: string;
663
+ };
664
+ "409": {
665
+ description: string;
666
+ };
667
+ "201": {
668
+ description: string;
669
+ };
670
+ };
671
+ };
672
+ };
673
+ use: _$better_call0.Middleware<_$better_call0.MiddlewareOptions, (inputContext: _$better_call0.MiddlewareInputContext<_$better_call0.MiddlewareOptions>) => Promise<{
674
+ session: {
675
+ session: Record<string, any> & {
676
+ id: string;
677
+ createdAt: Date;
678
+ updatedAt: Date;
679
+ userId: string;
680
+ expiresAt: Date;
681
+ token: string;
682
+ ipAddress?: string | null | undefined;
683
+ userAgent?: string | null | undefined;
684
+ };
685
+ user: Record<string, any> & {
686
+ id: string;
687
+ createdAt: Date;
688
+ updatedAt: Date;
689
+ email: string;
690
+ emailVerified: boolean;
691
+ name: string;
692
+ image?: string | null | undefined;
693
+ };
694
+ };
695
+ }>>[];
696
+ }, {
697
+ domainVerificationToken: string;
698
+ }>;
699
+ declare const verifyDomain: (options: SSOOptions) => _$better_call0.StrictEndpoint<"/sso/verify-domain", {
700
+ method: "POST";
701
+ body: z.ZodObject<{
702
+ providerId: z.ZodString;
703
+ }, z.core.$strip>;
704
+ metadata: {
705
+ openapi: {
706
+ summary: string;
707
+ description: string;
708
+ responses: {
709
+ "404": {
710
+ description: string;
711
+ };
712
+ "409": {
713
+ description: string;
714
+ };
715
+ "502": {
716
+ description: string;
717
+ };
718
+ "204": {
719
+ description: string;
720
+ };
721
+ };
722
+ };
723
+ };
724
+ use: _$better_call0.Middleware<_$better_call0.MiddlewareOptions, (inputContext: _$better_call0.MiddlewareInputContext<_$better_call0.MiddlewareOptions>) => Promise<{
725
+ session: {
726
+ session: Record<string, any> & {
727
+ id: string;
728
+ createdAt: Date;
729
+ updatedAt: Date;
730
+ userId: string;
731
+ expiresAt: Date;
732
+ token: string;
733
+ ipAddress?: string | null | undefined;
734
+ userAgent?: string | null | undefined;
735
+ };
736
+ user: Record<string, any> & {
737
+ id: string;
738
+ createdAt: Date;
739
+ updatedAt: Date;
740
+ email: string;
741
+ emailVerified: boolean;
742
+ name: string;
743
+ image?: string | null | undefined;
744
+ };
745
+ };
746
+ }>>[];
747
+ }, void>;
748
+ //#endregion
749
+ //#region src/utils.d.ts
750
+ declare function parseCertificate(certPem: string): {
751
+ fingerprintSha256: string;
752
+ notBefore: string;
753
+ notAfter: string;
754
+ publicKeyAlgorithm: string;
755
+ };
756
+ //#endregion
757
+ //#region src/routes/providers.d.ts
758
+ type ParsedCert = ReturnType<typeof parseCertificate>;
759
+ type SanitizedCert = ParsedCert | {
760
+ error: string;
761
+ };
762
+ declare const listSSOProviders: (options?: SSOOptions) => _$better_call0.StrictEndpoint<"/sso/providers", {
763
+ method: "GET";
764
+ use: _$better_call0.Middleware<_$better_call0.MiddlewareOptions, (inputContext: _$better_call0.MiddlewareInputContext<_$better_call0.MiddlewareOptions>) => Promise<{
765
+ session: {
766
+ session: Record<string, any> & {
767
+ id: string;
768
+ createdAt: Date;
769
+ updatedAt: Date;
770
+ userId: string;
771
+ expiresAt: Date;
772
+ token: string;
773
+ ipAddress?: string | null | undefined;
774
+ userAgent?: string | null | undefined;
775
+ };
776
+ user: Record<string, any> & {
777
+ id: string;
778
+ createdAt: Date;
779
+ updatedAt: Date;
780
+ email: string;
781
+ emailVerified: boolean;
782
+ name: string;
783
+ image?: string | null | undefined;
784
+ };
785
+ };
786
+ }>>[];
787
+ metadata: {
788
+ openapi: {
789
+ operationId: string;
790
+ summary: string;
791
+ description: string;
792
+ responses: {
793
+ "200": {
794
+ description: string;
795
+ };
796
+ };
797
+ };
798
+ };
799
+ }, {
800
+ providers: {
801
+ providerId: string;
802
+ type: string;
803
+ issuer: string;
804
+ domain: string;
805
+ organizationId: string | null;
806
+ domainVerified: boolean;
807
+ oidcConfig: {
808
+ discoveryEndpoint: string;
809
+ clientIdLastFour: string;
810
+ pkce: boolean;
811
+ authorizationEndpoint: string | undefined;
812
+ tokenEndpoint: string | undefined;
813
+ userInfoEndpoint: string | undefined;
814
+ jwksEndpoint: string | undefined;
815
+ scopes: string[] | undefined;
816
+ tokenEndpointAuthentication: "client_secret_post" | "client_secret_basic" | "private_key_jwt" | undefined;
817
+ } | undefined;
818
+ samlConfig: {
819
+ entryPoint: string;
820
+ callbackUrl: string | undefined;
821
+ idpInitiatedCallbackUrl: string | undefined;
822
+ audience: string | undefined;
823
+ wantAssertionsSigned: boolean | undefined;
824
+ authnRequestsSigned: boolean | undefined;
825
+ identifierFormat: string | undefined;
826
+ signatureAlgorithm: string | undefined;
827
+ digestAlgorithm: string | undefined;
828
+ certificate: SanitizedCert[] | undefined;
829
+ } | undefined;
830
+ spMetadataUrl: string;
831
+ }[];
832
+ }>;
833
+ declare const getSSOProvider: (options?: SSOOptions) => _$better_call0.StrictEndpoint<"/sso/get-provider", {
834
+ method: "GET";
835
+ use: _$better_call0.Middleware<_$better_call0.MiddlewareOptions, (inputContext: _$better_call0.MiddlewareInputContext<_$better_call0.MiddlewareOptions>) => Promise<{
836
+ session: {
837
+ session: Record<string, any> & {
838
+ id: string;
839
+ createdAt: Date;
840
+ updatedAt: Date;
841
+ userId: string;
842
+ expiresAt: Date;
843
+ token: string;
844
+ ipAddress?: string | null | undefined;
845
+ userAgent?: string | null | undefined;
846
+ };
847
+ user: Record<string, any> & {
848
+ id: string;
849
+ createdAt: Date;
850
+ updatedAt: Date;
851
+ email: string;
852
+ emailVerified: boolean;
853
+ name: string;
854
+ image?: string | null | undefined;
855
+ };
856
+ };
857
+ }>>[];
858
+ query: z.ZodObject<{
859
+ providerId: z.ZodString;
860
+ }, z.core.$strip>;
861
+ metadata: {
862
+ openapi: {
863
+ operationId: string;
864
+ summary: string;
865
+ description: string;
866
+ responses: {
867
+ "200": {
868
+ description: string;
869
+ };
870
+ "404": {
871
+ description: string;
872
+ };
873
+ "403": {
874
+ description: string;
875
+ };
876
+ };
877
+ };
878
+ };
879
+ }, {
880
+ providerId: string;
881
+ type: string;
882
+ issuer: string;
883
+ domain: string;
884
+ organizationId: string | null;
885
+ domainVerified: boolean;
886
+ oidcConfig: {
887
+ discoveryEndpoint: string;
888
+ clientIdLastFour: string;
889
+ pkce: boolean;
890
+ authorizationEndpoint: string | undefined;
891
+ tokenEndpoint: string | undefined;
892
+ userInfoEndpoint: string | undefined;
893
+ jwksEndpoint: string | undefined;
894
+ scopes: string[] | undefined;
895
+ tokenEndpointAuthentication: "client_secret_post" | "client_secret_basic" | "private_key_jwt" | undefined;
896
+ } | undefined;
897
+ samlConfig: {
898
+ entryPoint: string;
899
+ callbackUrl: string | undefined;
900
+ idpInitiatedCallbackUrl: string | undefined;
901
+ audience: string | undefined;
902
+ wantAssertionsSigned: boolean | undefined;
903
+ authnRequestsSigned: boolean | undefined;
904
+ identifierFormat: string | undefined;
905
+ signatureAlgorithm: string | undefined;
906
+ digestAlgorithm: string | undefined;
907
+ certificate: SanitizedCert[] | undefined;
908
+ } | undefined;
909
+ spMetadataUrl: string;
910
+ }>;
911
+ declare const updateSSOProvider: (options: SSOOptions) => _$better_call0.StrictEndpoint<"/sso/update-provider", {
912
+ method: "POST";
913
+ use: _$better_call0.Middleware<_$better_call0.MiddlewareOptions, (inputContext: _$better_call0.MiddlewareInputContext<_$better_call0.MiddlewareOptions>) => Promise<{
914
+ session: {
915
+ session: Record<string, any> & {
916
+ id: string;
917
+ createdAt: Date;
918
+ updatedAt: Date;
919
+ userId: string;
920
+ expiresAt: Date;
921
+ token: string;
922
+ ipAddress?: string | null | undefined;
923
+ userAgent?: string | null | undefined;
924
+ };
925
+ user: Record<string, any> & {
926
+ id: string;
927
+ createdAt: Date;
928
+ updatedAt: Date;
929
+ email: string;
930
+ emailVerified: boolean;
931
+ name: string;
932
+ image?: string | null | undefined;
933
+ };
934
+ };
935
+ }>>[];
936
+ body: z.ZodObject<{
937
+ issuer: z.ZodOptional<z.ZodString>;
938
+ domain: z.ZodOptional<z.ZodString>;
939
+ oidcConfig: z.ZodOptional<z.ZodObject<{
940
+ clientId: z.ZodOptional<z.ZodString>;
941
+ clientSecret: z.ZodOptional<z.ZodOptional<z.ZodString>>;
942
+ authorizationEndpoint: z.ZodOptional<z.ZodOptional<z.ZodString>>;
943
+ tokenEndpoint: z.ZodOptional<z.ZodOptional<z.ZodString>>;
944
+ userInfoEndpoint: z.ZodOptional<z.ZodOptional<z.ZodString>>;
945
+ tokenEndpointAuthentication: z.ZodOptional<z.ZodOptional<z.ZodEnum<{
946
+ client_secret_post: "client_secret_post";
947
+ client_secret_basic: "client_secret_basic";
948
+ private_key_jwt: "private_key_jwt";
949
+ }>>>;
950
+ privateKeyId: z.ZodOptional<z.ZodOptional<z.ZodString>>;
951
+ privateKeyAlgorithm: z.ZodOptional<z.ZodOptional<z.ZodString>>;
952
+ jwksEndpoint: z.ZodOptional<z.ZodOptional<z.ZodString>>;
953
+ discoveryEndpoint: z.ZodOptional<z.ZodOptional<z.ZodString>>;
954
+ skipDiscovery: z.ZodOptional<z.ZodOptional<z.ZodBoolean>>;
955
+ scopes: z.ZodOptional<z.ZodOptional<z.ZodArray<z.ZodString>>>;
956
+ pkce: z.ZodOptional<z.ZodOptional<z.ZodDefault<z.ZodBoolean>>>;
957
+ overrideUserInfo: z.ZodOptional<z.ZodOptional<z.ZodBoolean>>;
958
+ mapping: z.ZodOptional<z.ZodOptional<z.ZodObject<{
959
+ email: z.ZodString;
960
+ emailVerified: z.ZodOptional<z.ZodString>;
961
+ name: z.ZodString;
962
+ image: z.ZodOptional<z.ZodString>;
963
+ extraFields: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
964
+ }, z.core.$strict>>>;
965
+ }, z.core.$strip>>;
966
+ samlConfig: z.ZodOptional<z.ZodObject<{
967
+ audience: z.ZodOptional<z.ZodOptional<z.ZodString>>;
968
+ mapping: z.ZodOptional<z.ZodOptional<z.ZodObject<{
969
+ email: z.ZodString;
970
+ emailVerified: z.ZodOptional<z.ZodString>;
971
+ name: z.ZodString;
972
+ firstName: z.ZodOptional<z.ZodString>;
973
+ lastName: z.ZodOptional<z.ZodString>;
974
+ extraFields: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
975
+ }, z.core.$strict>>>;
976
+ privateKey: z.ZodOptional<z.ZodOptional<z.ZodString>>;
977
+ spMetadata: z.ZodOptional<z.ZodOptional<z.ZodObject<{
978
+ metadata: z.ZodOptional<z.ZodString>;
979
+ entityID: z.ZodOptional<z.ZodString>;
980
+ binding: z.ZodOptional<z.ZodString>;
981
+ privateKey: z.ZodOptional<z.ZodString>;
982
+ privateKeyPass: z.ZodOptional<z.ZodString>;
983
+ isAssertionEncrypted: z.ZodOptional<z.ZodBoolean>;
984
+ encPrivateKey: z.ZodOptional<z.ZodString>;
985
+ encPrivateKeyPass: z.ZodOptional<z.ZodString>;
986
+ }, z.core.$strip>>>;
987
+ cert: z.ZodOptional<z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>>;
988
+ entryPoint: z.ZodOptional<z.ZodString>;
989
+ callbackUrl: z.ZodOptional<z.ZodOptional<z.ZodString>>;
990
+ wantAssertionsSigned: z.ZodOptional<z.ZodOptional<z.ZodBoolean>>;
991
+ authnRequestsSigned: z.ZodOptional<z.ZodOptional<z.ZodBoolean>>;
992
+ signatureAlgorithm: z.ZodOptional<z.ZodOptional<z.ZodString>>;
993
+ digestAlgorithm: z.ZodOptional<z.ZodOptional<z.ZodString>>;
994
+ identifierFormat: z.ZodOptional<z.ZodOptional<z.ZodString>>;
995
+ idpInitiatedCallbackUrl: z.ZodOptional<z.ZodNullable<z.ZodString>>;
996
+ idpMetadata: z.ZodOptional<z.ZodObject<{
997
+ cert: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
998
+ privateKey: z.ZodOptional<z.ZodString>;
999
+ privateKeyPass: z.ZodOptional<z.ZodString>;
1000
+ isAssertionEncrypted: z.ZodOptional<z.ZodBoolean>;
1001
+ encPrivateKey: z.ZodOptional<z.ZodString>;
1002
+ encPrivateKeyPass: z.ZodOptional<z.ZodString>;
1003
+ singleSignOnService: z.ZodOptional<z.ZodArray<z.ZodObject<{
1004
+ Binding: z.ZodString;
1005
+ Location: z.ZodString;
1006
+ }, z.core.$strip>>>;
1007
+ singleLogoutService: z.ZodOptional<z.ZodArray<z.ZodObject<{
1008
+ Binding: z.ZodString;
1009
+ Location: z.ZodString;
1010
+ }, z.core.$strip>>>;
1011
+ metadata: z.ZodOptional<z.ZodString>;
1012
+ entityID: z.ZodOptional<z.ZodString>;
1013
+ }, z.core.$strip>>;
1014
+ }, z.core.$strip>>;
1015
+ providerId: z.ZodString;
1016
+ }, z.core.$strip>;
1017
+ metadata: {
1018
+ openapi: {
1019
+ operationId: string;
1020
+ summary: string;
1021
+ description: string;
1022
+ responses: {
1023
+ "200": {
1024
+ description: string;
1025
+ };
1026
+ "404": {
1027
+ description: string;
1028
+ };
1029
+ "403": {
1030
+ description: string;
1031
+ };
1032
+ };
1033
+ };
1034
+ };
1035
+ }, {
1036
+ providerId: string;
1037
+ type: string;
1038
+ issuer: string;
1039
+ domain: string;
1040
+ organizationId: string | null;
1041
+ domainVerified: boolean;
1042
+ oidcConfig: {
1043
+ discoveryEndpoint: string;
1044
+ clientIdLastFour: string;
1045
+ pkce: boolean;
1046
+ authorizationEndpoint: string | undefined;
1047
+ tokenEndpoint: string | undefined;
1048
+ userInfoEndpoint: string | undefined;
1049
+ jwksEndpoint: string | undefined;
1050
+ scopes: string[] | undefined;
1051
+ tokenEndpointAuthentication: "client_secret_post" | "client_secret_basic" | "private_key_jwt" | undefined;
1052
+ } | undefined;
1053
+ samlConfig: {
1054
+ entryPoint: string;
1055
+ callbackUrl: string | undefined;
1056
+ idpInitiatedCallbackUrl: string | undefined;
1057
+ audience: string | undefined;
1058
+ wantAssertionsSigned: boolean | undefined;
1059
+ authnRequestsSigned: boolean | undefined;
1060
+ identifierFormat: string | undefined;
1061
+ signatureAlgorithm: string | undefined;
1062
+ digestAlgorithm: string | undefined;
1063
+ certificate: SanitizedCert[] | undefined;
1064
+ } | undefined;
1065
+ spMetadataUrl: string;
1066
+ }>;
1067
+ declare const deleteSSOProvider: (options?: SSOOptions) => _$better_call0.StrictEndpoint<"/sso/delete-provider", {
1068
+ method: "POST";
1069
+ use: _$better_call0.Middleware<_$better_call0.MiddlewareOptions, (inputContext: _$better_call0.MiddlewareInputContext<_$better_call0.MiddlewareOptions>) => Promise<{
1070
+ session: {
1071
+ session: Record<string, any> & {
1072
+ id: string;
1073
+ createdAt: Date;
1074
+ updatedAt: Date;
1075
+ userId: string;
1076
+ expiresAt: Date;
1077
+ token: string;
1078
+ ipAddress?: string | null | undefined;
1079
+ userAgent?: string | null | undefined;
1080
+ };
1081
+ user: Record<string, any> & {
1082
+ id: string;
1083
+ createdAt: Date;
1084
+ updatedAt: Date;
1085
+ email: string;
1086
+ emailVerified: boolean;
1087
+ name: string;
1088
+ image?: string | null | undefined;
1089
+ };
1090
+ };
1091
+ }>>[];
1092
+ body: z.ZodObject<{
1093
+ providerId: z.ZodString;
1094
+ }, z.core.$strip>;
1095
+ metadata: {
1096
+ openapi: {
1097
+ operationId: string;
1098
+ summary: string;
1099
+ description: string;
1100
+ responses: {
1101
+ "200": {
1102
+ description: string;
1103
+ };
1104
+ "404": {
1105
+ description: string;
1106
+ };
1107
+ "403": {
1108
+ description: string;
1109
+ };
1110
+ };
1111
+ };
1112
+ };
1113
+ }, {
1114
+ success: boolean;
1115
+ }>;
1116
+ //#endregion
1117
+ //#region src/routes/sso.d.ts
1118
+ declare const spMetadata: (options?: SSOOptions) => _$better_call0.StrictEndpoint<"/sso/saml2/sp/metadata", {
1119
+ method: "GET";
1120
+ query: z.ZodObject<{
1121
+ providerId: z.ZodString;
1122
+ }, z.core.$strip>;
1123
+ metadata: {
1124
+ openapi: {
1125
+ operationId: string;
1126
+ summary: string;
1127
+ description: string;
1128
+ responses: {
1129
+ "200": {
1130
+ description: string;
1131
+ };
1132
+ };
1133
+ };
1134
+ };
1135
+ }, Response>;
1136
+ declare const registerSSOProvider: <O extends SSOOptions>(options: O) => _$better_call0.StrictEndpoint<"/sso/register", {
1137
+ method: "POST";
1138
+ body: z.ZodObject<{
1139
+ [x: string]: z.ZodOptional<z.ZodAny>;
1140
+ }, z.core.$strip>;
1141
+ use: _$better_call0.Middleware<_$better_call0.MiddlewareOptions, (inputContext: _$better_call0.MiddlewareInputContext<_$better_call0.MiddlewareOptions>) => Promise<{
1142
+ session: {
1143
+ session: Record<string, any> & {
1144
+ id: string;
1145
+ createdAt: Date;
1146
+ updatedAt: Date;
1147
+ userId: string;
1148
+ expiresAt: Date;
1149
+ token: string;
1150
+ ipAddress?: string | null | undefined;
1151
+ userAgent?: string | null | undefined;
1152
+ };
1153
+ user: Record<string, any> & {
1154
+ id: string;
1155
+ createdAt: Date;
1156
+ updatedAt: Date;
1157
+ email: string;
1158
+ emailVerified: boolean;
1159
+ name: string;
1160
+ image?: string | null | undefined;
1161
+ };
1162
+ };
1163
+ }>>[];
1164
+ metadata: {
1165
+ $Infer: {
1166
+ body: Record<string, any> & SSOProviderAdditionalFieldsInput<O>;
1167
+ };
1168
+ openapi: {
1169
+ operationId: string;
1170
+ summary: string;
1171
+ description: string;
1172
+ responses: {
1173
+ "200": {
1174
+ description: string;
1175
+ content: {
1176
+ "application/json": {
1177
+ schema: {
1178
+ type: "object";
1179
+ properties: {
1180
+ issuer: {
1181
+ type: string;
1182
+ format: string;
1183
+ description: string;
1184
+ };
1185
+ domain: {
1186
+ type: string;
1187
+ description: string;
1188
+ };
1189
+ domainVerified: {
1190
+ type: string;
1191
+ description: string;
1192
+ };
1193
+ domainVerificationToken: {
1194
+ type: string;
1195
+ description: string;
1196
+ };
1197
+ oidcConfig: {
1198
+ type: string;
1199
+ properties: {
1200
+ issuer: {
1201
+ type: string;
1202
+ format: string;
1203
+ description: string;
1204
+ };
1205
+ pkce: {
1206
+ type: string;
1207
+ description: string;
1208
+ };
1209
+ clientId: {
1210
+ type: string;
1211
+ description: string;
1212
+ };
1213
+ clientSecret: {
1214
+ type: string;
1215
+ description: string;
1216
+ };
1217
+ authorizationEndpoint: {
1218
+ type: string;
1219
+ format: string;
1220
+ nullable: boolean;
1221
+ description: string;
1222
+ };
1223
+ discoveryEndpoint: {
1224
+ type: string;
1225
+ format: string;
1226
+ description: string;
1227
+ };
1228
+ userInfoEndpoint: {
1229
+ type: string;
1230
+ format: string;
1231
+ nullable: boolean;
1232
+ description: string;
1233
+ };
1234
+ scopes: {
1235
+ type: string;
1236
+ items: {
1237
+ type: string;
1238
+ };
1239
+ nullable: boolean;
1240
+ description: string;
1241
+ };
1242
+ tokenEndpoint: {
1243
+ type: string;
1244
+ format: string;
1245
+ nullable: boolean;
1246
+ description: string;
1247
+ };
1248
+ tokenEndpointAuthentication: {
1249
+ type: string;
1250
+ enum: string[];
1251
+ nullable: boolean;
1252
+ description: string;
1253
+ };
1254
+ jwksEndpoint: {
1255
+ type: string;
1256
+ format: string;
1257
+ nullable: boolean;
1258
+ description: string;
1259
+ };
1260
+ mapping: {
1261
+ type: string;
1262
+ nullable: boolean;
1263
+ properties: {
1264
+ email: {
1265
+ type: string;
1266
+ description: string;
1267
+ };
1268
+ emailVerified: {
1269
+ type: string;
1270
+ nullable: boolean;
1271
+ description: string;
1272
+ };
1273
+ name: {
1274
+ type: string;
1275
+ description: string;
1276
+ };
1277
+ image: {
1278
+ type: string;
1279
+ nullable: boolean;
1280
+ description: string;
1281
+ };
1282
+ extraFields: {
1283
+ type: string;
1284
+ additionalProperties: {
1285
+ type: string;
1286
+ };
1287
+ nullable: boolean;
1288
+ description: string;
1289
+ };
1290
+ };
1291
+ required: string[];
1292
+ };
1293
+ };
1294
+ required: string[];
1295
+ description: string;
1296
+ };
1297
+ organizationId: {
1298
+ type: string;
1299
+ nullable: boolean;
1300
+ description: string;
1301
+ };
1302
+ userId: {
1303
+ type: string;
1304
+ description: string;
1305
+ };
1306
+ providerId: {
1307
+ type: string;
1308
+ description: string;
1309
+ };
1310
+ redirectURI: {
1311
+ type: string;
1312
+ format: string;
1313
+ description: string;
1314
+ };
1315
+ };
1316
+ required: string[];
1317
+ };
1318
+ };
1319
+ };
1320
+ };
1321
+ };
1322
+ };
1323
+ };
1324
+ }, O["domainVerification"] extends {
1325
+ enabled: true;
1326
+ } ? {
1327
+ redirectURI: string;
1328
+ oidcConfig: OIDCConfig | null;
1329
+ samlConfig: SAMLConfig | null;
1330
+ } & Omit<InferSSOProvider<O>, "samlConfig" | "oidcConfig"> & {
1331
+ domainVerified: boolean;
1332
+ domainVerificationToken: string;
1333
+ } : {
1334
+ redirectURI: string;
1335
+ oidcConfig: OIDCConfig | null;
1336
+ samlConfig: SAMLConfig | null;
1337
+ } & Omit<InferSSOProvider<O>, "samlConfig" | "oidcConfig">>;
1338
+ declare const signInSSO: (options?: SSOOptions) => _$better_call0.StrictEndpoint<"/sign-in/sso", {
1339
+ method: "POST";
1340
+ body: z.ZodObject<{
1341
+ email: z.ZodOptional<z.ZodString>;
1342
+ organizationSlug: z.ZodOptional<z.ZodString>;
1343
+ providerId: z.ZodOptional<z.ZodString>;
1344
+ domain: z.ZodOptional<z.ZodString>;
1345
+ callbackURL: z.ZodString;
1346
+ errorCallbackURL: z.ZodOptional<z.ZodString>;
1347
+ newUserCallbackURL: z.ZodOptional<z.ZodString>;
1348
+ scopes: z.ZodOptional<z.ZodArray<z.ZodString>>;
1349
+ loginHint: z.ZodOptional<z.ZodString>;
1350
+ additionalParams: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
1351
+ requestSignUp: z.ZodOptional<z.ZodBoolean>;
1352
+ providerType: z.ZodOptional<z.ZodEnum<{
1353
+ saml: "saml";
1354
+ oidc: "oidc";
1355
+ }>>;
1356
+ }, z.core.$strip>;
1357
+ metadata: {
1358
+ openapi: {
1359
+ operationId: string;
1360
+ summary: string;
1361
+ description: string;
1362
+ requestBody: {
1363
+ content: {
1364
+ "application/json": {
1365
+ schema: {
1366
+ type: "object";
1367
+ properties: {
1368
+ email: {
1369
+ type: string;
1370
+ description: string;
1371
+ };
1372
+ organizationSlug: {
1373
+ type: string;
1374
+ description: string;
1375
+ };
1376
+ providerId: {
1377
+ type: string;
1378
+ description: string;
1379
+ };
1380
+ domain: {
1381
+ type: string;
1382
+ description: string;
1383
+ };
1384
+ callbackURL: {
1385
+ type: string;
1386
+ description: string;
1387
+ };
1388
+ errorCallbackURL: {
1389
+ type: string;
1390
+ description: string;
1391
+ };
1392
+ newUserCallbackURL: {
1393
+ type: string;
1394
+ description: string;
1395
+ };
1396
+ scopes: {
1397
+ type: string;
1398
+ items: {
1399
+ type: string;
1400
+ };
1401
+ description: string;
1402
+ };
1403
+ loginHint: {
1404
+ type: string;
1405
+ description: string;
1406
+ };
1407
+ additionalParams: {
1408
+ type: string;
1409
+ additionalProperties: {
1410
+ type: string;
1411
+ };
1412
+ description: string;
1413
+ };
1414
+ requestSignUp: {
1415
+ type: string;
1416
+ description: string;
1417
+ };
1418
+ providerType: {
1419
+ type: string;
1420
+ enum: string[];
1421
+ description: string;
1422
+ };
1423
+ };
1424
+ required: string[];
1425
+ };
1426
+ };
1427
+ };
1428
+ };
1429
+ responses: {
1430
+ "200": {
1431
+ description: string;
1432
+ content: {
1433
+ "application/json": {
1434
+ schema: {
1435
+ type: "object";
1436
+ properties: {
1437
+ url: {
1438
+ type: string;
1439
+ format: string;
1440
+ description: string;
1441
+ };
1442
+ redirect: {
1443
+ type: string;
1444
+ description: string;
1445
+ enum: boolean[];
1446
+ };
1447
+ };
1448
+ required: string[];
1449
+ };
1450
+ };
1451
+ };
1452
+ };
1453
+ };
1454
+ };
1455
+ };
1456
+ }, {
1457
+ url: string;
1458
+ redirect: boolean;
1459
+ }>;
1460
+ declare const callbackSSO: (options?: SSOOptions) => _$better_call0.StrictEndpoint<"/sso/callback/:providerId", {
1461
+ method: "GET";
1462
+ query: z.ZodObject<{
1463
+ code: z.ZodOptional<z.ZodString>;
1464
+ state: z.ZodOptional<z.ZodString>;
1465
+ error: z.ZodOptional<z.ZodString>;
1466
+ error_description: z.ZodOptional<z.ZodString>;
1467
+ }, z.core.$strip>;
1468
+ allowedMediaTypes: readonly ["application/x-www-form-urlencoded", "application/json"];
1469
+ metadata: {
1470
+ openapi: {
1471
+ operationId: string;
1472
+ summary: string;
1473
+ description: string;
1474
+ responses: {
1475
+ "302": {
1476
+ description: string;
1477
+ };
1478
+ };
1479
+ };
1480
+ scope: "server";
1481
+ };
1482
+ }, void>;
1483
+ /**
1484
+ * Shared OIDC callback endpoint (no `:providerId` in path).
1485
+ * Used when `options.redirectURI` is set — the `providerId` is read from
1486
+ * the OAuth state instead of the URL path.
1487
+ */
1488
+ declare const callbackSSOShared: (options?: SSOOptions) => _$better_call0.StrictEndpoint<"/sso/callback", {
1489
+ metadata: {
1490
+ openapi: {
1491
+ operationId: string;
1492
+ summary: string;
1493
+ description: string;
1494
+ responses: {
1495
+ "302": {
1496
+ description: string;
1497
+ };
1498
+ };
1499
+ };
1500
+ scope: "server";
1501
+ };
1502
+ method: "GET";
1503
+ query: z.ZodObject<{
1504
+ code: z.ZodOptional<z.ZodString>;
1505
+ state: z.ZodOptional<z.ZodString>;
1506
+ error: z.ZodOptional<z.ZodString>;
1507
+ error_description: z.ZodOptional<z.ZodString>;
1508
+ }, z.core.$strip>;
1509
+ allowedMediaTypes: readonly ["application/x-www-form-urlencoded", "application/json"];
1510
+ }, void>;
1511
+ declare const acsEndpoint: (options?: SSOOptions) => _$better_call0.StrictEndpoint<"/sso/saml2/sp/acs/:providerId", {
1512
+ method: ("GET" | "POST")[];
1513
+ body: z.ZodOptional<z.ZodObject<{
1514
+ SAMLResponse: z.ZodString;
1515
+ RelayState: z.ZodOptional<z.ZodString>;
1516
+ }, z.core.$strip>>;
1517
+ query: z.ZodOptional<z.ZodObject<{
1518
+ RelayState: z.ZodOptional<z.ZodString>;
1519
+ }, z.core.$strip>>;
1520
+ metadata: {
1521
+ allowedMediaTypes: string[];
1522
+ openapi: {
1523
+ operationId: string;
1524
+ summary: string;
1525
+ description: string;
1526
+ responses: {
1527
+ "302": {
1528
+ description: string;
1529
+ };
1530
+ "400": {
1531
+ description: string;
1532
+ };
1533
+ "404": {
1534
+ description: string;
1535
+ };
1536
+ };
1537
+ };
1538
+ scope: "server";
1539
+ };
1540
+ }, never>;
1541
+ declare const sloEndpoint: (options?: SSOOptions) => _$better_call0.StrictEndpoint<"/sso/saml2/sp/slo/:providerId", {
1542
+ method: ("GET" | "POST")[];
1543
+ body: z.ZodOptional<z.ZodObject<{
1544
+ SAMLRequest: z.ZodOptional<z.ZodString>;
1545
+ SAMLResponse: z.ZodOptional<z.ZodString>;
1546
+ RelayState: z.ZodOptional<z.ZodString>;
1547
+ SigAlg: z.ZodOptional<z.ZodString>;
1548
+ Signature: z.ZodOptional<z.ZodString>;
1549
+ }, z.core.$strip>>;
1550
+ query: z.ZodOptional<z.ZodObject<{
1551
+ SAMLRequest: z.ZodOptional<z.ZodString>;
1552
+ SAMLResponse: z.ZodOptional<z.ZodString>;
1553
+ RelayState: z.ZodOptional<z.ZodString>;
1554
+ SigAlg: z.ZodOptional<z.ZodString>;
1555
+ Signature: z.ZodOptional<z.ZodString>;
1556
+ }, z.core.$strip>>;
1557
+ metadata: {
1558
+ allowedMediaTypes: string[];
1559
+ scope: "server";
1560
+ };
1561
+ }, void | Response>;
1562
+ declare const initiateSLO: (options?: SSOOptions) => _$better_call0.StrictEndpoint<"/sso/saml2/logout/:providerId", {
1563
+ method: "POST";
1564
+ body: z.ZodObject<{
1565
+ callbackURL: z.ZodOptional<z.ZodString>;
1566
+ }, z.core.$strip>;
1567
+ use: _$better_call0.Middleware<_$better_call0.MiddlewareOptions, (inputContext: _$better_call0.MiddlewareInputContext<_$better_call0.MiddlewareOptions>) => Promise<{
1568
+ session: {
1569
+ session: Record<string, any> & {
1570
+ id: string;
1571
+ createdAt: Date;
1572
+ updatedAt: Date;
1573
+ userId: string;
1574
+ expiresAt: Date;
1575
+ token: string;
1576
+ ipAddress?: string | null | undefined;
1577
+ userAgent?: string | null | undefined;
1578
+ };
1579
+ user: Record<string, any> & {
1580
+ id: string;
1581
+ createdAt: Date;
1582
+ updatedAt: Date;
1583
+ email: string;
1584
+ emailVerified: boolean;
1585
+ name: string;
1586
+ image?: string | null | undefined;
1587
+ };
1588
+ };
1589
+ }>>[];
1590
+ metadata: {
1591
+ readonly scope: "server";
1592
+ };
1593
+ }, never>;
1594
+ //#endregion
1595
+ //#region src/index.d.ts
1596
+ declare module "@better-auth/core" {
1597
+ interface BetterAuthPluginRegistry<AuthOptions, Options> {
1598
+ sso: {
1599
+ creator: typeof sso$1;
1600
+ };
1601
+ }
1602
+ }
1603
+ type DomainVerificationEndpoints = {
1604
+ requestDomainVerification: ReturnType<typeof requestDomainVerification>;
1605
+ verifyDomain: ReturnType<typeof verifyDomain>;
1606
+ };
1607
+ type SSOEndpoints<O extends SSOOptions> = {
1608
+ spMetadata: ReturnType<typeof spMetadata>;
1609
+ registerSSOProvider: ReturnType<typeof registerSSOProvider<O>>;
1610
+ signInSSO: ReturnType<typeof signInSSO>;
1611
+ callbackSSO: ReturnType<typeof callbackSSO>;
1612
+ callbackSSOShared: ReturnType<typeof callbackSSOShared>;
1613
+ acsEndpoint: ReturnType<typeof acsEndpoint>;
1614
+ sloEndpoint: ReturnType<typeof sloEndpoint>;
1615
+ initiateSLO: ReturnType<typeof initiateSLO>;
1616
+ listSSOProviders: ReturnType<typeof listSSOProviders>;
1617
+ getSSOProvider: ReturnType<typeof getSSOProvider>;
1618
+ updateSSOProvider: ReturnType<typeof updateSSOProvider>;
1619
+ deleteSSOProvider: ReturnType<typeof deleteSSOProvider>;
1620
+ };
1621
+ declare function sso$1<O extends SSOOptions & {
1622
+ domainVerification?: {
1623
+ enabled: true;
1624
+ };
1625
+ }>(options?: O | undefined): {
1626
+ id: "sso";
1627
+ version: string;
1628
+ endpoints: SSOEndpoints<O> & DomainVerificationEndpoints;
1629
+ schema: SSOProviderSchema<O>;
1630
+ $Infer: {
1631
+ SSOProvider: InferSSOProvider<O>;
1632
+ };
1633
+ options: NoInfer<O>;
1634
+ };
1635
+ declare function sso$1<O extends SSOOptions>(options?: O | undefined): {
1636
+ id: "sso";
1637
+ version: string;
1638
+ endpoints: SSOEndpoints<O>;
1639
+ schema: SSOProviderSchema<O>;
1640
+ $Infer: {
1641
+ SSOProvider: InferSSOProvider<O>;
1642
+ };
1643
+ options: NoInfer<O>;
1644
+ };
1645
+ /**
1646
+ * Enterprise SSO — OIDC / OAuth2 / SAML 2.0 providers registered per email domain or
1647
+ * per organization, with `provisionUser` / `organizationProvisioning` hooks for
1648
+ * just-in-time account creation.
1649
+ *
1650
+ * Two defaults are worth setting deliberately, both documented on the package's docs
1651
+ * page: `domainVerification` is **off**, so an unverified `domain` still routes
1652
+ * sign-in; and `/sso/register` is session-only, so any signed-in user may register a
1653
+ * provider unless you narrow `providersLimit`. This wrapper does not change either
1654
+ * default — it only warns once, at construction, when `domainVerification` is not
1655
+ * explicitly enabled, naming both exposures. Every option is forwarded to
1656
+ * `@better-auth/sso` untouched.
1657
+ *
1658
+ * SAML loads on workerd but its assertion-verify path (pure-JS RSA) has not been
1659
+ * measured against a Worker CPU budget — treat OIDC/OAuth2 as the supported mode.
1660
+ * @experimental
1661
+ */
1662
+ declare const sso: typeof sso$1;
1663
+ export {
1664
+ /**
1665
+ * The OIDC provider configuration accepted by `registerSSOProvider` — exported so a
1666
+ * caller can type the config it builds (from env, a tenant record, …) before handing it
1667
+ * over.
1668
+ * @experimental
1669
+ */
1670
+ type OIDCConfig, sso };