@lunora/auth 1.0.0-alpha.8 → 1.0.0-alpha.81

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