@better-auth/sso 1.8.0-beta.1 → 1.8.0-beta.3

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.
package/dist/client.d.mts CHANGED
@@ -1,6 +1,5 @@
1
- import { t as SSOPlugin } from "./index-CuvoOoW_.mjs";
1
+ import { t as SSOPlugin } from "./index-BvKzNnKP.mjs";
2
2
  import { DBFieldAttribute } from "better-auth/db";
3
-
4
3
  //#region src/client.d.ts
5
4
  interface SSOClientOptions {
6
5
  domainVerification?: {
@@ -14,7 +13,7 @@ interface SSOClientOptions {
14
13
  };
15
14
  } | undefined;
16
15
  }
17
- declare const ssoClient: <CO extends SSOClientOptions>(options?: CO | undefined) => {
16
+ export declare const ssoClient: <CO extends SSOClientOptions>(options?: CO | undefined) => {
18
17
  id: "sso-client";
19
18
  version: string;
20
19
  $InferServerPlugin: SSOPlugin<{
@@ -31,4 +30,4 @@ declare const ssoClient: <CO extends SSOClientOptions>(options?: CO | undefined)
31
30
  };
32
31
  };
33
32
  //#endregion
34
- export { ssoClient };
33
+ export {};
package/dist/client.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { t as PACKAGE_VERSION } from "./version-Bn0HtKjY.mjs";
1
+ import { t as PACKAGE_VERSION } from "./version-HRaJjPrD.mjs";
2
2
  //#region src/client.ts
3
3
  const ssoClient = (options) => {
4
4
  return {
@@ -1,9 +1,11 @@
1
1
  import { APIError } from "better-auth/api";
2
2
  import * as z from "zod";
3
+ import "@better-fetch/fetch";
3
4
  import samlifyDefault from "samlify";
4
5
  import { DBFieldAttribute, FieldAttributeToObject, InferAdditionalFieldsFromPluginOptions, RemoveFieldsWithReturnedFalse } from "better-auth/db";
5
6
  import { Awaitable, DBTransactionAdapter, OAuth2Tokens, User } from "better-auth";
6
- import * as _$better_call0 from "better-call";
7
+ import "@better-auth/core/db/adapter";
8
+ import "@better-auth/core";
7
9
  //#region src/saml/algorithms.d.ts
8
10
  declare const SignatureAlgorithm: {
9
11
  readonly RSA_SHA1: "http://www.w3.org/2000/09/xmldsig#rsa-sha1";
@@ -479,7 +481,7 @@ interface SSOOptions {
479
481
  domain?: string | undefined;
480
482
  domainVerified?: string | undefined;
481
483
  };
482
- additionalFields?: { [key in string]: DBFieldAttribute };
484
+ additionalFields?: { [key in string]: DBFieldAttribute; };
483
485
  };
484
486
  } | undefined;
485
487
  /**
@@ -683,7 +685,7 @@ interface SSOOptions {
683
685
  }
684
686
  //#endregion
685
687
  //#region src/routes/domain-verification.d.ts
686
- declare const requestDomainVerification: (options: SSOOptions) => _$better_call0.StrictEndpoint<"/sso/request-domain-verification", {
688
+ declare const requestDomainVerification: (options: SSOOptions) => import("better-call").StrictEndpoint<"/sso/request-domain-verification", {
687
689
  method: "POST";
688
690
  body: z.ZodObject<{
689
691
  providerId: z.ZodString;
@@ -705,7 +707,7 @@ declare const requestDomainVerification: (options: SSOOptions) => _$better_call0
705
707
  };
706
708
  };
707
709
  };
708
- use: _$better_call0.Middleware<_$better_call0.MiddlewareOptions, (inputContext: _$better_call0.MiddlewareInputContext<_$better_call0.MiddlewareOptions>) => Promise<{
710
+ use: import("better-call").Middleware<import("better-call").MiddlewareOptions, (inputContext: import("better-call").MiddlewareInputContext<import("better-call").MiddlewareOptions>) => Promise<{
709
711
  session: {
710
712
  session: Record<string, any> & {
711
713
  id: string;
@@ -731,7 +733,7 @@ declare const requestDomainVerification: (options: SSOOptions) => _$better_call0
731
733
  }, {
732
734
  domainVerificationToken: string;
733
735
  }>;
734
- declare const verifyDomain: (options: SSOOptions) => _$better_call0.StrictEndpoint<"/sso/verify-domain", {
736
+ declare const verifyDomain: (options: SSOOptions) => import("better-call").StrictEndpoint<"/sso/verify-domain", {
735
737
  method: "POST";
736
738
  body: z.ZodObject<{
737
739
  providerId: z.ZodString;
@@ -756,7 +758,7 @@ declare const verifyDomain: (options: SSOOptions) => _$better_call0.StrictEndpoi
756
758
  };
757
759
  };
758
760
  };
759
- use: _$better_call0.Middleware<_$better_call0.MiddlewareOptions, (inputContext: _$better_call0.MiddlewareInputContext<_$better_call0.MiddlewareOptions>) => Promise<{
761
+ use: import("better-call").Middleware<import("better-call").MiddlewareOptions, (inputContext: import("better-call").MiddlewareInputContext<import("better-call").MiddlewareOptions>) => Promise<{
760
762
  session: {
761
763
  session: Record<string, any> & {
762
764
  id: string;
@@ -794,9 +796,9 @@ type ParsedCert = ReturnType<typeof parseCertificate>;
794
796
  type SanitizedCert = ParsedCert | {
795
797
  error: string;
796
798
  };
797
- declare const listSSOProviders: (options?: SSOOptions) => _$better_call0.StrictEndpoint<"/sso/providers", {
799
+ declare const listSSOProviders: (options?: SSOOptions) => import("better-call").StrictEndpoint<"/sso/providers", {
798
800
  method: "GET";
799
- use: _$better_call0.Middleware<_$better_call0.MiddlewareOptions, (inputContext: _$better_call0.MiddlewareInputContext<_$better_call0.MiddlewareOptions>) => Promise<{
801
+ use: import("better-call").Middleware<import("better-call").MiddlewareOptions, (inputContext: import("better-call").MiddlewareInputContext<import("better-call").MiddlewareOptions>) => Promise<{
800
802
  session: {
801
803
  session: Record<string, any> & {
802
804
  id: string;
@@ -865,9 +867,9 @@ declare const listSSOProviders: (options?: SSOOptions) => _$better_call0.StrictE
865
867
  spMetadataUrl: string;
866
868
  }[];
867
869
  }>;
868
- declare const getSSOProvider: (options?: SSOOptions) => _$better_call0.StrictEndpoint<"/sso/get-provider", {
870
+ declare const getSSOProvider: (options?: SSOOptions) => import("better-call").StrictEndpoint<"/sso/get-provider", {
869
871
  method: "GET";
870
- use: _$better_call0.Middleware<_$better_call0.MiddlewareOptions, (inputContext: _$better_call0.MiddlewareInputContext<_$better_call0.MiddlewareOptions>) => Promise<{
872
+ use: import("better-call").Middleware<import("better-call").MiddlewareOptions, (inputContext: import("better-call").MiddlewareInputContext<import("better-call").MiddlewareOptions>) => Promise<{
871
873
  session: {
872
874
  session: Record<string, any> & {
873
875
  id: string;
@@ -943,9 +945,9 @@ declare const getSSOProvider: (options?: SSOOptions) => _$better_call0.StrictEnd
943
945
  } | undefined;
944
946
  spMetadataUrl: string;
945
947
  }>;
946
- declare const updateSSOProvider: (options: SSOOptions) => _$better_call0.StrictEndpoint<"/sso/update-provider", {
948
+ declare const updateSSOProvider: (options: SSOOptions) => import("better-call").StrictEndpoint<"/sso/update-provider", {
947
949
  method: "POST";
948
- use: _$better_call0.Middleware<_$better_call0.MiddlewareOptions, (inputContext: _$better_call0.MiddlewareInputContext<_$better_call0.MiddlewareOptions>) => Promise<{
950
+ use: import("better-call").Middleware<import("better-call").MiddlewareOptions, (inputContext: import("better-call").MiddlewareInputContext<import("better-call").MiddlewareOptions>) => Promise<{
949
951
  session: {
950
952
  session: Record<string, any> & {
951
953
  id: string;
@@ -999,7 +1001,6 @@ declare const updateSSOProvider: (options: SSOOptions) => _$better_call0.StrictE
999
1001
  }, z.core.$strict>>>;
1000
1002
  }, z.core.$strip>>;
1001
1003
  samlConfig: z.ZodOptional<z.ZodObject<{
1002
- audience: z.ZodOptional<z.ZodOptional<z.ZodString>>;
1003
1004
  mapping: z.ZodOptional<z.ZodOptional<z.ZodObject<{
1004
1005
  email: z.ZodOptional<z.ZodString>;
1005
1006
  emailVerified: z.ZodOptional<z.ZodString>;
@@ -1021,6 +1022,7 @@ declare const updateSSOProvider: (options: SSOOptions) => _$better_call0.StrictE
1021
1022
  }, z.core.$strip>>>;
1022
1023
  cert: z.ZodOptional<z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>>;
1023
1024
  entryPoint: z.ZodOptional<z.ZodString>;
1025
+ audience: z.ZodOptional<z.ZodOptional<z.ZodString>>;
1024
1026
  callbackUrl: z.ZodOptional<z.ZodOptional<z.ZodString>>;
1025
1027
  wantAssertionsSigned: z.ZodOptional<z.ZodOptional<z.ZodBoolean>>;
1026
1028
  authnRequestsSigned: z.ZodOptional<z.ZodOptional<z.ZodBoolean>>;
@@ -1099,9 +1101,9 @@ declare const updateSSOProvider: (options: SSOOptions) => _$better_call0.StrictE
1099
1101
  } | undefined;
1100
1102
  spMetadataUrl: string;
1101
1103
  }>;
1102
- declare const deleteSSOProvider: (options?: SSOOptions) => _$better_call0.StrictEndpoint<"/sso/delete-provider", {
1104
+ declare const deleteSSOProvider: (options?: SSOOptions) => import("better-call").StrictEndpoint<"/sso/delete-provider", {
1103
1105
  method: "POST";
1104
- use: _$better_call0.Middleware<_$better_call0.MiddlewareOptions, (inputContext: _$better_call0.MiddlewareInputContext<_$better_call0.MiddlewareOptions>) => Promise<{
1106
+ use: import("better-call").Middleware<import("better-call").MiddlewareOptions, (inputContext: import("better-call").MiddlewareInputContext<import("better-call").MiddlewareOptions>) => Promise<{
1105
1107
  session: {
1106
1108
  session: Record<string, any> & {
1107
1109
  id: string;
@@ -1150,7 +1152,7 @@ declare const deleteSSOProvider: (options?: SSOOptions) => _$better_call0.Strict
1150
1152
  }>;
1151
1153
  //#endregion
1152
1154
  //#region src/routes/sso.d.ts
1153
- declare const spMetadata: (options?: SSOOptions) => _$better_call0.StrictEndpoint<"/sso/saml2/sp/metadata", {
1155
+ declare const spMetadata: (options?: SSOOptions) => import("better-call").StrictEndpoint<"/sso/saml2/sp/metadata", {
1154
1156
  method: "GET";
1155
1157
  query: z.ZodObject<{
1156
1158
  providerId: z.ZodString;
@@ -1168,12 +1170,12 @@ declare const spMetadata: (options?: SSOOptions) => _$better_call0.StrictEndpoin
1168
1170
  };
1169
1171
  };
1170
1172
  }, Response>;
1171
- declare const registerSSOProvider: <O extends SSOOptions>(options: O) => _$better_call0.StrictEndpoint<"/sso/register", {
1173
+ declare const registerSSOProvider: <O extends SSOOptions>(options: O) => import("better-call").StrictEndpoint<"/sso/register", {
1172
1174
  method: "POST";
1173
1175
  body: z.ZodObject<{
1174
1176
  [x: string]: z.ZodOptional<z.ZodAny>;
1175
1177
  }, z.core.$strip>;
1176
- use: _$better_call0.Middleware<_$better_call0.MiddlewareOptions, (inputContext: _$better_call0.MiddlewareInputContext<_$better_call0.MiddlewareOptions>) => Promise<{
1178
+ use: import("better-call").Middleware<import("better-call").MiddlewareOptions, (inputContext: import("better-call").MiddlewareInputContext<import("better-call").MiddlewareOptions>) => Promise<{
1177
1179
  session: {
1178
1180
  session: Record<string, any> & {
1179
1181
  id: string;
@@ -1369,7 +1371,7 @@ declare const registerSSOProvider: <O extends SSOOptions>(options: O) => _$bette
1369
1371
  oidcConfig: OIDCConfig | null;
1370
1372
  samlConfig: SAMLConfig | null;
1371
1373
  } & Omit<InferSSOProvider<O>, "samlConfig" | "oidcConfig">>;
1372
- declare const signInSSO: (options?: SSOOptions) => _$better_call0.StrictEndpoint<"/sign-in/sso", {
1374
+ declare const signInSSO: (options?: SSOOptions) => import("better-call").StrictEndpoint<"/sign-in/sso", {
1373
1375
  method: "POST";
1374
1376
  body: z.ZodObject<{
1375
1377
  email: z.ZodOptional<z.ZodString>;
@@ -1491,7 +1493,7 @@ declare const signInSSO: (options?: SSOOptions) => _$better_call0.StrictEndpoint
1491
1493
  url: string;
1492
1494
  redirect: boolean;
1493
1495
  }>;
1494
- declare const callbackSSO: (options?: SSOOptions) => _$better_call0.StrictEndpoint<"/sso/callback/:providerId", {
1496
+ declare const callbackSSO: (options?: SSOOptions) => import("better-call").StrictEndpoint<"/sso/callback/:providerId", {
1495
1497
  method: "GET";
1496
1498
  query: z.ZodObject<{
1497
1499
  code: z.ZodOptional<z.ZodString>;
@@ -1519,7 +1521,7 @@ declare const callbackSSO: (options?: SSOOptions) => _$better_call0.StrictEndpoi
1519
1521
  * Used when `options.redirectURI` is set — the `providerId` is read from
1520
1522
  * the OAuth state instead of the URL path.
1521
1523
  */
1522
- declare const callbackSSOShared: (options?: SSOOptions) => _$better_call0.StrictEndpoint<"/sso/callback", {
1524
+ declare const callbackSSOShared: (options?: SSOOptions) => import("better-call").StrictEndpoint<"/sso/callback", {
1523
1525
  metadata: {
1524
1526
  openapi: {
1525
1527
  operationId: string;
@@ -1542,7 +1544,7 @@ declare const callbackSSOShared: (options?: SSOOptions) => _$better_call0.Strict
1542
1544
  }, z.core.$strip>;
1543
1545
  allowedMediaTypes: readonly ["application/x-www-form-urlencoded", "application/json"];
1544
1546
  }, never>;
1545
- declare const acsEndpoint: (options?: SSOOptions) => _$better_call0.StrictEndpoint<"/sso/saml2/sp/acs/:providerId", {
1547
+ declare const acsEndpoint: (options?: SSOOptions) => import("better-call").StrictEndpoint<"/sso/saml2/sp/acs/:providerId", {
1546
1548
  method: ("GET" | "POST")[];
1547
1549
  body: z.ZodOptional<z.ZodObject<{
1548
1550
  SAMLResponse: z.ZodString;
@@ -1572,7 +1574,7 @@ declare const acsEndpoint: (options?: SSOOptions) => _$better_call0.StrictEndpoi
1572
1574
  scope: "server";
1573
1575
  };
1574
1576
  }, never>;
1575
- declare const sloEndpoint: (options?: SSOOptions) => _$better_call0.StrictEndpoint<"/sso/saml2/sp/slo/:providerId", {
1577
+ declare const sloEndpoint: (options?: SSOOptions) => import("better-call").StrictEndpoint<"/sso/saml2/sp/slo/:providerId", {
1576
1578
  method: ("GET" | "POST")[];
1577
1579
  body: z.ZodOptional<z.ZodObject<{
1578
1580
  SAMLRequest: z.ZodOptional<z.ZodString>;
@@ -1593,12 +1595,12 @@ declare const sloEndpoint: (options?: SSOOptions) => _$better_call0.StrictEndpoi
1593
1595
  scope: "server";
1594
1596
  };
1595
1597
  }, void | Response>;
1596
- declare const initiateSLO: (options?: SSOOptions) => _$better_call0.StrictEndpoint<"/sso/saml2/logout/:providerId", {
1598
+ declare const initiateSLO: (options?: SSOOptions) => import("better-call").StrictEndpoint<"/sso/saml2/logout/:providerId", {
1597
1599
  method: "POST";
1598
1600
  body: z.ZodObject<{
1599
1601
  callbackURL: z.ZodOptional<z.ZodString>;
1600
1602
  }, z.core.$strip>;
1601
- use: _$better_call0.Middleware<_$better_call0.MiddlewareOptions, (inputContext: _$better_call0.MiddlewareInputContext<_$better_call0.MiddlewareOptions>) => Promise<{
1603
+ use: import("better-call").Middleware<import("better-call").MiddlewareOptions, (inputContext: import("better-call").MiddlewareInputContext<import("better-call").MiddlewareOptions>) => Promise<{
1602
1604
  session: {
1603
1605
  session: Record<string, any> & {
1604
1606
  id: string;
@@ -1762,7 +1764,29 @@ interface OIDCDiscoveryDocument {
1762
1764
  /**
1763
1765
  * Error codes for OIDC discovery operations.
1764
1766
  */
1765
- type DiscoveryErrorCode = /** Request to discovery endpoint timed out */"discovery_timeout" /** Discovery endpoint returned 404 or similar */ | "discovery_not_found" /** Discovery endpoint returned invalid JSON */ | "discovery_invalid_json" /** OIDC endpoint URL (discovery or per-endpoint: authorization, token, userinfo, jwks) is invalid, malformed, or uses a non-`http(s)` scheme */ | "discovery_invalid_url" /** OIDC endpoint URL is not trusted by the trusted origins configuration */ | "discovery_untrusted_origin" /** OIDC endpoint URL (discovery or per-endpoint) points to a host that is not publicly routable (loopback, RFC 1918, link-local, cloud metadata FQDN, etc.) */ | "discovery_private_host" /** Server-side OIDC endpoint fetch received an HTTP redirect response */ | "oidc_endpoint_redirect" /** Discovery document issuer doesn't match configured issuer */ | "issuer_mismatch" /** Discovery document is missing required fields */ | "discovery_incomplete" /** IdP only advertises token auth methods that Better Auth doesn't currently support */ | "unsupported_token_auth_method" /** Catch-all for unexpected errors */ | "discovery_unexpected_error";
1767
+ type DiscoveryErrorCode =
1768
+ /** Request to discovery endpoint timed out */
1769
+ "discovery_timeout" |
1770
+ /** Discovery endpoint returned 404 or similar */
1771
+ "discovery_not_found" |
1772
+ /** Discovery endpoint returned invalid JSON */
1773
+ "discovery_invalid_json" |
1774
+ /** OIDC endpoint URL (discovery or per-endpoint: authorization, token, userinfo, jwks) is invalid, malformed, or uses a non-`http(s)` scheme */
1775
+ "discovery_invalid_url" |
1776
+ /** OIDC endpoint URL is not trusted by the trusted origins configuration */
1777
+ "discovery_untrusted_origin" |
1778
+ /** OIDC endpoint URL (discovery or per-endpoint) points to a host that is not publicly routable (loopback, RFC 1918, link-local, cloud metadata FQDN, etc.) */
1779
+ "discovery_private_host" |
1780
+ /** Server-side OIDC endpoint fetch received an HTTP redirect response */
1781
+ "oidc_endpoint_redirect" |
1782
+ /** Discovery document issuer doesn't match configured issuer */
1783
+ "issuer_mismatch" |
1784
+ /** Discovery document is missing required fields */
1785
+ "discovery_incomplete" |
1786
+ /** IdP only advertises token auth methods that Better Auth doesn't currently support */
1787
+ "unsupported_token_auth_method" |
1788
+ /** Catch-all for unexpected errors */
1789
+ "discovery_unexpected_error";
1766
1790
  /**
1767
1791
  * Custom error class for OIDC discovery failures.
1768
1792
  * Can be caught and mapped to APIError at the edge.
package/dist/index.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- import { A as SAMLIdentityProviderMetadata, B as SSOUserResolutionContext, C as deriveSAMLIdentityProviderEntityID, D as DEFAULT_MAX_SAML_RESPONSE_SIZE, E as DEFAULT_MAX_SAML_METADATA_SIZE, F as SSOProviderMutationGuardInput, G as DigestAlgorithm, H as AlgorithmValidationOptions, I as SSOProviderReference, K as KeyEncryptionAlgorithm, L as SSOProviderUserProfile, M as SSOOptions, N as SSOProvider, O as OIDCConfig, P as SSOProviderMutationGuardContext, R as SSOSAMLUserResolutionInput, S as SAMLServiceProviderPolicy, T as DEFAULT_CLOCK_SKEW_MS, U as DataEncryptionAlgorithm, V as SSOUserResolutionInput, W as DeprecatedAlgorithmBehavior, _ as REQUIRED_DISCOVERY_FIELDS, a as fetchDiscoveryDocument, b as TimestampValidationOptions, c as normalizeUrl, d as validateDiscoveryUrl, f as DiscoverOIDCConfigParams, g as OIDCDiscoveryDocument, h as HydratedOIDCConfig, i as discoverOIDCConfig, j as SSOOIDCUserResolutionInput, k as SAMLConfig, l as selectTokenEndpointAuthMethod, m as DiscoveryErrorCode, n as sso, o as needsRuntimeDiscovery, p as DiscoveryError, q as SignatureAlgorithm, r as computeDiscoveryUrl, s as normalizeDiscoveryUrls, t as SSOPlugin, u as validateDiscoveryDocument, v as RequiredDiscoveryField, w as deriveSAMLServiceProviderPolicy, x as validateSAMLTimestamp, y as SAMLConditions, z as SSOUserResolution } from "./index-CuvoOoW_.mjs";
2
- export { AlgorithmValidationOptions, DEFAULT_CLOCK_SKEW_MS, DEFAULT_MAX_SAML_METADATA_SIZE, DEFAULT_MAX_SAML_RESPONSE_SIZE, DataEncryptionAlgorithm, DeprecatedAlgorithmBehavior, DigestAlgorithm, DiscoverOIDCConfigParams, DiscoveryError, DiscoveryErrorCode, HydratedOIDCConfig, KeyEncryptionAlgorithm, OIDCConfig, OIDCDiscoveryDocument, REQUIRED_DISCOVERY_FIELDS, RequiredDiscoveryField, SAMLConditions, SAMLConfig, SAMLIdentityProviderMetadata, SAMLServiceProviderPolicy, SSOOIDCUserResolutionInput, SSOOptions, SSOPlugin, SSOProvider, SSOProviderMutationGuardContext, SSOProviderMutationGuardInput, SSOProviderReference, SSOProviderUserProfile, SSOSAMLUserResolutionInput, SSOUserResolution, SSOUserResolutionContext, SSOUserResolutionInput, SignatureAlgorithm, TimestampValidationOptions, computeDiscoveryUrl, deriveSAMLIdentityProviderEntityID, deriveSAMLServiceProviderPolicy, discoverOIDCConfig, fetchDiscoveryDocument, needsRuntimeDiscovery, normalizeDiscoveryUrls, normalizeUrl, selectTokenEndpointAuthMethod, sso, validateDiscoveryDocument, validateDiscoveryUrl, validateSAMLTimestamp };
1
+ import { A as SAMLIdentityProviderMetadata, B as SSOUserResolutionContext, C as deriveSAMLIdentityProviderEntityID, D as DEFAULT_MAX_SAML_RESPONSE_SIZE, E as DEFAULT_MAX_SAML_METADATA_SIZE, F as SSOProviderMutationGuardInput, G as DigestAlgorithm, H as AlgorithmValidationOptions, I as SSOProviderReference, K as KeyEncryptionAlgorithm, L as SSOProviderUserProfile, M as SSOOptions, N as SSOProvider, O as OIDCConfig, P as SSOProviderMutationGuardContext, R as SSOSAMLUserResolutionInput, S as SAMLServiceProviderPolicy, T as DEFAULT_CLOCK_SKEW_MS, U as DataEncryptionAlgorithm, V as SSOUserResolutionInput, W as DeprecatedAlgorithmBehavior, _ as REQUIRED_DISCOVERY_FIELDS, a as fetchDiscoveryDocument, b as TimestampValidationOptions, c as normalizeUrl, d as validateDiscoveryUrl, f as DiscoverOIDCConfigParams, g as OIDCDiscoveryDocument, h as HydratedOIDCConfig, i as discoverOIDCConfig, j as SSOOIDCUserResolutionInput, k as SAMLConfig, l as selectTokenEndpointAuthMethod, m as DiscoveryErrorCode, n as sso, o as needsRuntimeDiscovery, p as DiscoveryError, q as SignatureAlgorithm, r as computeDiscoveryUrl, s as normalizeDiscoveryUrls, t as SSOPlugin, u as validateDiscoveryDocument, v as RequiredDiscoveryField, w as deriveSAMLServiceProviderPolicy, x as validateSAMLTimestamp, y as SAMLConditions, z as SSOUserResolution } from "./index-BvKzNnKP.mjs";
2
+ export { type AlgorithmValidationOptions, DEFAULT_CLOCK_SKEW_MS, DEFAULT_MAX_SAML_METADATA_SIZE, DEFAULT_MAX_SAML_RESPONSE_SIZE, DataEncryptionAlgorithm, type DeprecatedAlgorithmBehavior, DigestAlgorithm, type DiscoverOIDCConfigParams, DiscoveryError, type DiscoveryErrorCode, type HydratedOIDCConfig, KeyEncryptionAlgorithm, type OIDCConfig, type OIDCDiscoveryDocument, REQUIRED_DISCOVERY_FIELDS, type RequiredDiscoveryField, type SAMLConditions, type SAMLConfig, type SAMLIdentityProviderMetadata, type SAMLServiceProviderPolicy, type SSOOIDCUserResolutionInput, type SSOOptions, SSOPlugin, type SSOProvider, type SSOProviderMutationGuardContext, type SSOProviderMutationGuardInput, type SSOProviderReference, type SSOProviderUserProfile, type SSOSAMLUserResolutionInput, type SSOUserResolution, type SSOUserResolutionContext, type SSOUserResolutionInput, SignatureAlgorithm, type TimestampValidationOptions, computeDiscoveryUrl, deriveSAMLIdentityProviderEntityID, deriveSAMLServiceProviderPolicy, discoverOIDCConfig, fetchDiscoveryDocument, needsRuntimeDiscovery, normalizeDiscoveryUrls, normalizeUrl, selectTokenEndpointAuthMethod, sso, validateDiscoveryDocument, validateDiscoveryUrl, validateSAMLTimestamp };
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { t as PACKAGE_VERSION } from "./version-Bn0HtKjY.mjs";
1
+ import { t as PACKAGE_VERSION } from "./version-HRaJjPrD.mjs";
2
2
  import { APIError, addOAuthServerContext, createAuthEndpoint, createAuthMiddleware, getSessionFromCtx, sessionMiddleware } from "better-auth/api";
3
3
  import { XMLParser, XMLValidator } from "fast-xml-parser";
4
4
  import { X509Certificate } from "node:crypto";
@@ -7,14 +7,14 @@ import { generateRandomString } from "better-auth/crypto";
7
7
  import * as z from "zod";
8
8
  import { getCurrentAdapter, getCurrentDBAdapterAsyncLocalStorage, runWithTransaction } from "@better-auth/core/context";
9
9
  import { filterOutputFields } from "@better-auth/core/utils/db";
10
+ import { verifyIdToken } from "@better-auth/core/oauth2/internal";
10
11
  import { classifyHost, isPublicRoutableHost } from "@better-auth/core/utils/host";
11
12
  import { betterFetch } from "@better-fetch/fetch";
12
- import { createRemoteJWKSet, customFetch, jwtVerify } from "jose";
13
+ import { createRemoteJWKSet, customFetch } from "jose";
13
14
  import { base64, base64Url } from "@better-auth/utils/base64";
14
15
  import { createHash } from "@better-auth/utils/hash";
15
16
  import { DOMParser } from "@xmldom/xmldom";
16
- import * as samlifyNamespace from "samlify";
17
- import samlifyDefault from "samlify";
17
+ import samlifyDefault, * as samlifyNamespace from "samlify";
18
18
  import { defineErrorCodes } from "@better-auth/core/utils/error-codes";
19
19
  import { parseInputData, toZodSchema } from "better-auth/db";
20
20
  import { isAPIError } from "@better-auth/core/utils/is-api-error";
@@ -40,7 +40,7 @@ const LOGOUT_REQUEST_KEY_PREFIX = "saml-logout-request:";
40
40
  * Default TTL for used assertion records (15 minutes).
41
41
  * This should match the maximum expected NotOnOrAfter window plus clock skew.
42
42
  */
43
- const DEFAULT_ASSERTION_TTL_MS = 900 * 1e3;
43
+ const DEFAULT_ASSERTION_TTL_MS = 9e5;
44
44
  /**
45
45
  * Default clock skew tolerance (5 minutes).
46
46
  * Allows for minor time differences between IdP and SP servers.
@@ -50,17 +50,17 @@ const DEFAULT_ASSERTION_TTL_MS = 900 * 1e3;
50
50
  * - Clock synchronization differences (NTP drift)
51
51
  * - Distributed systems across timezones
52
52
  */
53
- const DEFAULT_CLOCK_SKEW_MS = 300 * 1e3;
53
+ const DEFAULT_CLOCK_SKEW_MS = 3e5;
54
54
  /**
55
55
  * Default maximum size for SAML responses (256 KB).
56
56
  * Protects against memory exhaustion from oversized SAML payloads.
57
57
  */
58
- const DEFAULT_MAX_SAML_RESPONSE_SIZE = 256 * 1024;
58
+ const DEFAULT_MAX_SAML_RESPONSE_SIZE = 262144;
59
59
  /**
60
60
  * Default maximum size for IdP metadata (100 KB).
61
61
  * Protects against oversized metadata documents.
62
62
  */
63
- const DEFAULT_MAX_SAML_METADATA_SIZE = 100 * 1024;
63
+ const DEFAULT_MAX_SAML_METADATA_SIZE = 102400;
64
64
  //#endregion
65
65
  //#region src/utils.ts
66
66
  const unsafeSAMLRedirectPathPrefix = /^\/(?:\/|\\|%2f|%5c)/i;
@@ -113,7 +113,8 @@ const validateEmailDomain = (email, domain) => {
113
113
  return domainMatches(emailDomain, domain);
114
114
  };
115
115
  function parseCertificate(certPem) {
116
- const cert = new X509Certificate(certPem.includes("-----BEGIN") ? certPem : `-----BEGIN CERTIFICATE-----\n${certPem}\n-----END CERTIFICATE-----`);
116
+ const normalized = certPem.includes("-----BEGIN") ? certPem : `-----BEGIN CERTIFICATE-----\n${certPem}\n-----END CERTIFICATE-----`;
117
+ const cert = new X509Certificate(normalized);
117
118
  return {
118
119
  fingerprintSha256: cert.fingerprint256,
119
120
  notBefore: cert.validFrom,
@@ -577,11 +578,13 @@ function assertOIDCAuthorizedParty(payload, clientId) {
577
578
  * the SSO OIDC flow.
578
579
  */
579
580
  async function validateOIDCIdToken(token, jwksEndpoint, options, isTrustedOrigin) {
580
- const verified = await jwtVerify(token, createRemoteJWKSet(new URL(jwksEndpoint), { [customFetch]: (url, init) => fetchOIDCEndpointResponse("jwksEndpoint", url, init, isTrustedOrigin) }), {
581
+ const jwks = createRemoteJWKSet(new URL(jwksEndpoint), { [customFetch]: (url, init) => fetchOIDCEndpointResponse("jwksEndpoint", url, init, isTrustedOrigin) });
582
+ const verified = await verifyIdToken(token, {
583
+ jwks,
581
584
  audience: options.audience,
582
585
  issuer: options.issuer
583
586
  });
584
- if (typeof options.audience === "string") assertOIDCAuthorizedParty(verified.payload, options.audience);
587
+ assertOIDCAuthorizedParty(verified.payload, options.audience);
585
588
  return verified;
586
589
  }
587
590
  /**
@@ -1098,10 +1101,7 @@ function handleDeprecatedAlgorithm(message, behavior, errorCode) {
1098
1101
  message,
1099
1102
  code: errorCode
1100
1103
  });
1101
- case "warn":
1102
- console.warn(`[SAML Security Warning] ${message}`);
1103
- break;
1104
- case "allow": break;
1104
+ case "warn": console.warn(`[SAML Security Warning] ${message}`);
1105
1105
  }
1106
1106
  }
1107
1107
  function validateSignatureAlgorithm(algorithm, options = {}) {
@@ -2276,9 +2276,10 @@ async function checkProviderAccess(ctx, providerId) {
2276
2276
  });
2277
2277
  if (!provider) throw new APIError("NOT_FOUND", { message: "Provider not found" });
2278
2278
  let hasAccess = false;
2279
- if (provider.organizationId) if (ctx.context.hasPlugin("organization")) hasAccess = await isOrgAdmin(ctx, userId, provider.organizationId);
2280
- else hasAccess = provider.userId === userId;
2281
- else hasAccess = provider.userId === userId;
2279
+ if (provider.organizationId) {
2280
+ if (ctx.context.hasPlugin("organization")) hasAccess = await isOrgAdmin(ctx, userId, provider.organizationId);
2281
+ else hasAccess = provider.userId === userId;
2282
+ } else hasAccess = provider.userId === userId;
2282
2283
  if (!hasAccess) throw new APIError("FORBIDDEN", { message: "You don't have access to this provider" });
2283
2284
  return provider;
2284
2285
  }
@@ -2573,7 +2574,7 @@ const requestDomainVerification = (options) => {
2573
2574
  await ctx.context.internalAdapter.createVerificationValue({
2574
2575
  identifier,
2575
2576
  value: domainVerificationToken,
2576
- expiresAt: new Date(Date.now() + 3600 * 24 * 7 * 1e3)
2577
+ expiresAt: new Date(Date.now() + 6048e5)
2577
2578
  });
2578
2579
  ctx.setStatus(201);
2579
2580
  return ctx.json({ domainVerificationToken });
@@ -2661,7 +2662,7 @@ async function generateRelayState(c, link, providerReference) {
2661
2662
  /**
2662
2663
  * This is the actual expiry time of the state
2663
2664
  */
2664
- expiresAt: Date.now() + 600 * 1e3,
2665
+ expiresAt: Date.now() + 6e5,
2665
2666
  requestSignUp: c.body.requestSignUp,
2666
2667
  serverContext: providerReference ? { [SSO_PROVIDER_STATE_KEY]: providerReference } : void 0
2667
2668
  };
@@ -3191,9 +3192,10 @@ const spMetadata = (options) => {
3191
3192
  });
3192
3193
  };
3193
3194
  const registerSSOProvider = (options) => {
3195
+ const registerBodySchema = getRegisterSSOProviderBodySchema(options);
3194
3196
  return createAuthEndpoint("/sso/register", {
3195
3197
  method: "POST",
3196
- body: getRegisterSSOProviderBodySchema(options),
3198
+ body: registerBodySchema,
3197
3199
  use: [sessionMiddleware],
3198
3200
  metadata: {
3199
3201
  $Infer: { body: {} },
@@ -3388,13 +3390,13 @@ const registerSSOProvider = (options) => {
3388
3390
  if (!member) throw new APIError("BAD_REQUEST", { message: "You are not a member of the organization" });
3389
3391
  if (ctx.context.hasPlugin("organization") && !hasOrgAdminRole(member)) throw new APIError("FORBIDDEN", { message: "You must be an organization owner or admin to register SSO providers" });
3390
3392
  }
3391
- if (new Set([
3393
+ if ((/* @__PURE__ */ new Set([
3392
3394
  ...BUILT_IN_ACCOUNT_PROVIDER_IDS,
3393
3395
  ...Object.keys(ctx.context.options.socialProviders ?? {}),
3394
3396
  ...ctx.context.socialProviders.map((p) => p.id),
3395
3397
  ...ctx.context.trustedProviders,
3396
3398
  ...options?.defaultSSO?.map((p) => p.providerId) ?? []
3397
- ]).has(body.providerId)) {
3399
+ ])).has(body.providerId)) {
3398
3400
  ctx.context.logger.warn(`SSO provider registration rejected for reserved providerId: ${body.providerId}`);
3399
3401
  throw new APIError("UNPROCESSABLE_ENTITY", { message: "This providerId is reserved and cannot be used for an SSO provider" });
3400
3402
  }
@@ -3536,7 +3538,7 @@ const registerSSOProvider = (options) => {
3536
3538
  await ctx.context.internalAdapter.createVerificationValue({
3537
3539
  identifier: getVerificationIdentifier(options, provider.providerId),
3538
3540
  value: domainVerificationToken,
3539
- expiresAt: new Date(Date.now() + 3600 * 24 * 7 * 1e3)
3541
+ expiresAt: new Date(Date.now() + 6048e5)
3540
3542
  });
3541
3543
  }
3542
3544
  const result = {
@@ -3816,7 +3818,9 @@ async function handleOIDCCallback(ctx, options, providerId, stateData, parsedPro
3816
3818
  const { code, error, error_description } = ctx.query;
3817
3819
  if (!stateData) stateData = await parseState(ctx);
3818
3820
  if (!stateData) {
3819
- const redirectURL = appendQueryParams(ctx.context.options.onAPIError?.errorURL || `${ctx.context.baseURL}/error`, new URLSearchParams({ error: "invalid_state" }));
3821
+ const errorURL = ctx.context.options.onAPIError?.errorURL || `${ctx.context.baseURL}/error`;
3822
+ const params = new URLSearchParams({ error: "invalid_state" });
3823
+ const redirectURL = appendQueryParams(errorURL, params);
3820
3824
  throw ctx.redirect(redirectURL);
3821
3825
  }
3822
3826
  const providerReference = parsedProviderReference ?? parseSSOProviderReference(stateData.serverContext?.["ssoProviderReference"]);
@@ -4197,15 +4201,19 @@ const callbackSSOShared = (options) => {
4197
4201
  }, async (ctx) => {
4198
4202
  const stateData = await parseState(ctx);
4199
4203
  if (!stateData) {
4200
- const redirectURL = appendQueryParams(ctx.context.options.onAPIError?.errorURL || `${ctx.context.baseURL}/error`, new URLSearchParams({ error: "invalid_state" }));
4204
+ const errorURL = ctx.context.options.onAPIError?.errorURL || `${ctx.context.baseURL}/error`;
4205
+ const params = new URLSearchParams({ error: "invalid_state" });
4206
+ const redirectURL = appendQueryParams(errorURL, params);
4201
4207
  throw ctx.redirect(redirectURL);
4202
4208
  }
4203
4209
  const providerReference = parseSSOProviderReference(stateData.serverContext?.[SSO_PROVIDER_STATE_KEY]);
4204
4210
  if (!providerReference) {
4205
- const redirectURL = appendQueryParams(stateData.errorURL || stateData.callbackURL, new URLSearchParams({
4211
+ const errorURL = stateData.errorURL || stateData.callbackURL;
4212
+ const params = new URLSearchParams({
4206
4213
  error: "invalid_state",
4207
4214
  error_description: "missing_sso_provider_reference"
4208
- }));
4215
+ });
4216
+ const redirectURL = appendQueryParams(errorURL, params);
4209
4217
  throw ctx.redirect(redirectURL);
4210
4218
  }
4211
4219
  return handleOIDCCallback(ctx, options, providerReference.providerId, stateData, providerReference);
@@ -4241,7 +4249,9 @@ const acsEndpoint = (options) => {
4241
4249
  let resolvedErrorRedirectUrl;
4242
4250
  if (ctx.method === "GET" && !ctx.body?.SAMLResponse) {
4243
4251
  if (!(await getSessionFromCtx(ctx))?.session) {
4244
- const redirectURL = appendQueryParams(ctx.context.options.onAPIError?.errorURL || `${appOrigin}/error`, new URLSearchParams({ error: "invalid_request" }));
4252
+ const errorURL = ctx.context.options.onAPIError?.errorURL || `${appOrigin}/error`;
4253
+ const params = new URLSearchParams({ error: "invalid_request" });
4254
+ const redirectURL = appendQueryParams(errorURL, params);
4245
4255
  throw ctx.redirect(redirectURL);
4246
4256
  }
4247
4257
  const relayState = ctx.query?.RelayState;
@@ -4310,10 +4320,11 @@ const sloEndpoint = (options) => {
4310
4320
  const appOrigin = new URL(ctx.context.baseURL).origin;
4311
4321
  const safeErrorURL = getSafeRedirectUrl([relayState], `${appOrigin}/sso/saml2/sp/slo/${providerId}`, appOrigin, (url, settings) => ctx.context.isTrustedOrigin(url, settings));
4312
4322
  if (!samlRequest && !samlResponse) {
4313
- const redirectURL = appendQueryParams(safeErrorURL, new URLSearchParams({
4323
+ const params = new URLSearchParams({
4314
4324
  error: "invalid_request",
4315
4325
  error_description: "missing_logout_data"
4316
- }));
4326
+ });
4327
+ const redirectURL = appendQueryParams(safeErrorURL, params);
4317
4328
  throw ctx.redirect(redirectURL);
4318
4329
  }
4319
4330
  const provider = await findSAMLProvider(providerId, options, ctx.context.adapter);
@@ -4376,14 +4387,16 @@ async function handleLogoutRequest(ctx, sp, idp, relayState, providerId) {
4376
4387
  const stored = await ctx.context.internalAdapter.findVerificationValue(key);
4377
4388
  if (stored) {
4378
4389
  const data = safeJsonParse(stored.value);
4379
- if (data) if (!sessionIndex || !data.sessionIndex || sessionIndex === data.sessionIndex) {
4380
- await ctx.context.internalAdapter.deleteSession(data.sessionToken).catch((e) => ctx.context.logger.warn("Failed to delete session during SLO", { error: e }));
4381
- await ctx.context.internalAdapter.deleteVerificationByIdentifier(`${SAML_SESSION_BY_ID_PREFIX}${data.sessionId}`).catch((e) => ctx.context.logger.warn("Failed to delete SAML session lookup during SLO", e));
4382
- } else ctx.context.logger.warn("SessionIndex mismatch in LogoutRequest - skipping session deletion", {
4383
- providerId,
4384
- requestedSessionIndex: sessionIndex,
4385
- storedSessionIndex: data.sessionIndex
4386
- });
4390
+ if (data) {
4391
+ if (!sessionIndex || !data.sessionIndex || sessionIndex === data.sessionIndex) {
4392
+ await ctx.context.internalAdapter.deleteSession(data.sessionToken).catch((e) => ctx.context.logger.warn("Failed to delete session during SLO", { error: e }));
4393
+ await ctx.context.internalAdapter.deleteVerificationByIdentifier(`${SAML_SESSION_BY_ID_PREFIX}${data.sessionId}`).catch((e) => ctx.context.logger.warn("Failed to delete SAML session lookup during SLO", e));
4394
+ } else ctx.context.logger.warn("SessionIndex mismatch in LogoutRequest - skipping session deletion", {
4395
+ providerId,
4396
+ requestedSessionIndex: sessionIndex,
4397
+ storedSessionIndex: data.sessionIndex
4398
+ });
4399
+ }
4387
4400
  await ctx.context.internalAdapter.deleteVerificationByIdentifier(key).catch((e) => ctx.context.logger.warn("Failed to delete SAML session key during SLO", e));
4388
4401
  }
4389
4402
  const currentSession = await getSessionFromCtx(ctx);
@@ -1,5 +1,5 @@
1
1
  //#endregion
2
2
  //#region src/version.ts
3
- const PACKAGE_VERSION = "1.8.0-beta.1";
3
+ const PACKAGE_VERSION = "1.8.0-beta.3";
4
4
  //#endregion
5
5
  export { PACKAGE_VERSION as t };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@better-auth/sso",
3
- "version": "1.8.0-beta.1",
3
+ "version": "1.8.0-beta.3",
4
4
  "description": "SSO plugin for Better Auth",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -66,22 +66,22 @@
66
66
  "devDependencies": {
67
67
  "@types/body-parser": "^1.19.6",
68
68
  "@types/express": "^5.0.6",
69
- "better-call": "1.4.2",
69
+ "better-call": "1.4.4",
70
70
  "body-parser": "^2.3.0",
71
71
  "express": "^5.2.1",
72
72
  "kysely": "^0.28.17 || ^0.29.0",
73
73
  "oauth2-mock-server": "^9.0.0",
74
- "tsdown": "0.21.10",
75
- "@better-auth/core": "1.8.0-beta.1",
76
- "@better-auth/kysely-adapter": "1.8.0-beta.1",
77
- "better-auth": "1.8.0-beta.1"
74
+ "tsdown": "0.23.1",
75
+ "@better-auth/core": "1.8.0-beta.3",
76
+ "@better-auth/kysely-adapter": "1.8.0-beta.3",
77
+ "better-auth": "1.8.0-beta.3"
78
78
  },
79
79
  "peerDependencies": {
80
80
  "@better-auth/utils": "^0.4.2 || ^0.5.0",
81
- "@better-fetch/fetch": "1.3.2",
82
- "better-call": "1.4.2",
83
- "better-auth": "^1.8.0-beta.1",
84
- "@better-auth/core": "^1.8.0-beta.1"
81
+ "@better-fetch/fetch": "1.3.3",
82
+ "better-call": "1.4.4",
83
+ "@better-auth/core": "^1.8.0-beta.3",
84
+ "better-auth": "^1.8.0-beta.3"
85
85
  },
86
86
  "scripts": {
87
87
  "build": "tsdown",