@better-auth/sso 1.7.0-rc.2 → 1.7.0-rc.4

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,4 +1,4 @@
1
- import { t as SSOPlugin } from "./index-D1yk91me.mjs";
1
+ import { t as SSOPlugin } from "./index-nfENSAuB.mjs";
2
2
  import { DBFieldAttribute } from "better-auth/db";
3
3
  //#region src/client.d.ts
4
4
  interface SSOClientOptions {
package/dist/client.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { t as PACKAGE_VERSION } from "./version-m-Zfjx6T.mjs";
1
+ import { t as PACKAGE_VERSION } from "./version-Do0kTnv7.mjs";
2
2
  //#region src/client.ts
3
3
  const ssoClient = (options) => {
4
4
  return {
@@ -1,8 +1,10 @@
1
1
  import { APIError } from "better-auth/api";
2
2
  import * as z from "zod";
3
3
  import "@better-fetch/fetch";
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";
7
+ import "@better-auth/core/db/adapter";
6
8
  import "@better-auth/core";
7
9
  //#region src/saml/algorithms.d.ts
8
10
  declare const SignatureAlgorithm: {
@@ -173,9 +175,10 @@ interface SAMLConfig {
173
175
  encPrivateKeyPass?: string | undefined;
174
176
  };
175
177
  /**
176
- * Request signed assertions from the IdP. When true, the SP metadata
177
- * advertises `WantAssertionsSigned="true"` and samlify will reject
178
- * unsigned assertions.
178
+ * Request and require signed assertions from the IdP. When true, generated
179
+ * SP metadata advertises `WantAssertionsSigned="true"` and the ACS rejects
180
+ * unsigned assertions. Custom SP metadata supplies the effective policy and
181
+ * accepts the XML Schema boolean forms `true`, `false`, `1`, and `0`.
179
182
  */
180
183
  wantAssertionsSigned?: boolean | undefined;
181
184
  authnRequestsSigned?: boolean | undefined;
@@ -239,37 +242,106 @@ type SSOProviderUserProfile = {
239
242
  name: string;
240
243
  image?: string | null | undefined;
241
244
  } & Record<string, unknown>;
242
- /** OIDC identity and profile data available to an application's SSO resolver. */
243
- interface SSOUserResolutionInput {
244
- protocol: "oidc";
245
+ /**
246
+ * Opaque reference to the SSO provider configuration accepted for the current
247
+ * authentication flow.
248
+ *
249
+ * This reference is a transient authentication fence. Applications must not
250
+ * persist it as a tenant or user binding.
251
+ */
252
+ interface SSOProviderReference {
253
+ providerId: string;
254
+ source: {
255
+ type: "configured";
256
+ } | {
257
+ type: "persisted";
258
+ recordId: string;
259
+ };
260
+ authenticationConfigurationFingerprint: string;
261
+ }
262
+ interface BaseSSOUserResolutionInput {
245
263
  providerId: string;
246
264
  accountKey: {
247
265
  issuer: string;
248
- providerAccountId: string;
266
+ accountId: string;
249
267
  };
250
268
  providerUser: SSOProviderUserProfile;
269
+ providerReference: SSOProviderReference;
270
+ }
271
+ /** OIDC identity and profile data available to an application's SSO resolver. */
272
+ interface SSOOIDCUserResolutionInput extends BaseSSOUserResolutionInput {
273
+ protocol: "oidc";
274
+ /** Raw claims from UserInfo, or the verified ID Token when UserInfo is absent. */
251
275
  providerClaims: Record<string, unknown>;
276
+ /** Claims from the cryptographically verified ID Token. */
277
+ verifiedIdTokenClaims: Record<string, unknown>;
278
+ }
279
+ /** SAML identity and assertion data available to an application's SSO resolver. */
280
+ interface SSOSAMLUserResolutionInput extends BaseSSOUserResolutionInput {
281
+ protocol: "saml";
282
+ /**
283
+ * Attributes from the verified assertion. Multi-valued attributes remain
284
+ * arrays and all scalar values remain strings.
285
+ */
286
+ providerAttributes: Record<string, string | readonly string[]>;
252
287
  }
288
+ /** Verified SSO identity and provider data available to an application resolver. */
289
+ type SSOUserResolutionInput = SSOOIDCUserResolutionInput | SSOSAMLUserResolutionInput;
253
290
  /** Transaction-bound capabilities available while resolving an SSO user. */
254
291
  interface SSOUserResolutionContext {
255
292
  database: DBTransactionAdapter;
256
293
  }
294
+ interface BaseSSOProviderMutationGuardInput {
295
+ provider: {
296
+ id: string;
297
+ providerId: string;
298
+ organizationId: string | null;
299
+ };
300
+ /**
301
+ * Opaque reference to the exact locked provider configuration.
302
+ *
303
+ * This value is transient and must not be persisted as a tenant binding.
304
+ */
305
+ providerReference: SSOProviderReference;
306
+ }
307
+ /** Mutation attempted against one exact persisted SSO provider row. */
308
+ type SSOProviderMutationGuardInput = (BaseSSOProviderMutationGuardInput & {
309
+ action: "update";
310
+ /**
311
+ * True when the validated proposal changes provider identity,
312
+ * routing, or verification policy used to authenticate accounts.
313
+ */
314
+ isAuthenticationBoundaryChange: boolean;
315
+ }) | (BaseSSOProviderMutationGuardInput & {
316
+ action: "delete";
317
+ });
318
+ /** Transaction-bound context for guarding a persisted provider mutation. */
319
+ interface SSOProviderMutationGuardContext {
320
+ database: DBTransactionAdapter;
321
+ }
257
322
  interface SSOOptions {
258
323
  /**
259
324
  * Resolve a verified provider identity to a Better Auth user.
260
325
  *
261
- * Currently invoked for OIDC callbacks only.
326
+ * For OIDC, `accountKey` is derived from the validated ID Token. For SAML,
327
+ * it contains the verified IdP entity ID and signed NameID. Profile fields,
328
+ * raw OIDC claims, and SAML assertion attributes are protocol-accepted
329
+ * provider data and may require application-level validation.
262
330
  *
263
- * TODO: Invoke this resolver for SAML callbacks after normalizing the verified
264
- * IdP entity ID as `accountKey.issuer` and the signed NameID as
265
- * `accountKey.providerAccountId`.
266
- *
267
- * `accountKey` is derived from the validated ID Token. Profile fields and raw
268
- * claims are protocol-accepted provider data and may require application-level
269
- * validation. The callback runs on every OIDC sign-in inside the same native
270
- * database transaction as account finalization and session creation.
331
+ * The callback runs on every SSO sign-in inside the same native database
332
+ * transaction as account finalization and session creation.
271
333
  */
272
334
  resolveUser?: ((input: SSOUserResolutionInput, context: SSOUserResolutionContext) => Awaitable<SSOUserResolution>) | undefined;
335
+ /**
336
+ * Guards updates and deletion of an exact persisted SSO provider.
337
+ *
338
+ * The callback runs after the provider row is locked and before any provider
339
+ * or linked Account mutation. Update inputs disclose only whether the
340
+ * validated proposal changes the authentication boundary; proposed secrets
341
+ * and configuration values are never exposed. Throw to reject the mutation.
342
+ * Better Auth converts callback failures into a stable conflict response.
343
+ */
344
+ guardProviderMutation?: ((input: SSOProviderMutationGuardInput, context: SSOProviderMutationGuardContext) => Awaitable<void>) | undefined;
273
345
  /**
274
346
  * custom function to provision a user when they sign in with an SSO provider.
275
347
  */
@@ -576,7 +648,7 @@ interface SSOOptions {
576
648
  */
577
649
  maxResponseSize?: number;
578
650
  /**
579
- * Maximum allowed size for IdP metadata XML in bytes.
651
+ * Maximum allowed size for IdP or SP metadata XML in bytes.
580
652
  *
581
653
  * @default 102400 (100KB)
582
654
  */
@@ -927,9 +999,15 @@ declare const updateSSOProvider: (options: SSOOptions) => import("better-call").
927
999
  }, z.core.$strip>>;
928
1000
  samlConfig: z.ZodOptional<z.ZodObject<{
929
1001
  audience: z.ZodOptional<z.ZodOptional<z.ZodString>>;
930
- cert: z.ZodOptional<z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>>;
931
- entryPoint: z.ZodOptional<z.ZodString>;
932
- callbackUrl: z.ZodOptional<z.ZodOptional<z.ZodString>>;
1002
+ mapping: z.ZodOptional<z.ZodOptional<z.ZodObject<{
1003
+ email: z.ZodString;
1004
+ emailVerified: z.ZodOptional<z.ZodString>;
1005
+ name: z.ZodString;
1006
+ firstName: z.ZodOptional<z.ZodString>;
1007
+ lastName: z.ZodOptional<z.ZodString>;
1008
+ extraFields: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
1009
+ }, z.core.$strict>>>;
1010
+ privateKey: z.ZodOptional<z.ZodOptional<z.ZodString>>;
933
1011
  spMetadata: z.ZodOptional<z.ZodOptional<z.ZodObject<{
934
1012
  metadata: z.ZodOptional<z.ZodString>;
935
1013
  entityID: z.ZodOptional<z.ZodString>;
@@ -940,20 +1018,14 @@ declare const updateSSOProvider: (options: SSOOptions) => import("better-call").
940
1018
  encPrivateKey: z.ZodOptional<z.ZodString>;
941
1019
  encPrivateKeyPass: z.ZodOptional<z.ZodString>;
942
1020
  }, z.core.$strip>>>;
1021
+ cert: z.ZodOptional<z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>>;
1022
+ entryPoint: z.ZodOptional<z.ZodString>;
1023
+ callbackUrl: z.ZodOptional<z.ZodOptional<z.ZodString>>;
943
1024
  wantAssertionsSigned: z.ZodOptional<z.ZodOptional<z.ZodBoolean>>;
944
1025
  authnRequestsSigned: z.ZodOptional<z.ZodOptional<z.ZodBoolean>>;
945
1026
  signatureAlgorithm: z.ZodOptional<z.ZodOptional<z.ZodString>>;
946
1027
  digestAlgorithm: z.ZodOptional<z.ZodOptional<z.ZodString>>;
947
1028
  identifierFormat: z.ZodOptional<z.ZodOptional<z.ZodString>>;
948
- privateKey: z.ZodOptional<z.ZodOptional<z.ZodString>>;
949
- mapping: z.ZodOptional<z.ZodOptional<z.ZodObject<{
950
- email: z.ZodString;
951
- emailVerified: z.ZodOptional<z.ZodString>;
952
- name: z.ZodString;
953
- firstName: z.ZodOptional<z.ZodString>;
954
- lastName: z.ZodOptional<z.ZodString>;
955
- extraFields: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
956
- }, z.core.$strict>>>;
957
1029
  idpInitiatedCallbackUrl: z.ZodOptional<z.ZodNullable<z.ZodString>>;
958
1030
  idpMetadata: z.ZodOptional<z.ZodObject<{
959
1031
  cert: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
@@ -1026,7 +1098,7 @@ declare const updateSSOProvider: (options: SSOOptions) => import("better-call").
1026
1098
  } | undefined;
1027
1099
  spMetadataUrl: string;
1028
1100
  }>;
1029
- declare const deleteSSOProvider: () => import("better-call").StrictEndpoint<"/sso/delete-provider", {
1101
+ declare const deleteSSOProvider: (options?: SSOOptions) => import("better-call").StrictEndpoint<"/sso/delete-provider", {
1030
1102
  method: "POST";
1031
1103
  use: ((inputContext: import("better-call").MiddlewareInputContext<import("better-call").MiddlewareOptions>) => Promise<{
1032
1104
  session: {
@@ -1576,6 +1648,25 @@ declare const DEFAULT_MAX_SAML_RESPONSE_SIZE: number;
1576
1648
  */
1577
1649
  declare const DEFAULT_MAX_SAML_METADATA_SIZE: number;
1578
1650
  //#endregion
1651
+ //#region src/routes/helpers.d.ts
1652
+ interface SAMLServiceProviderPolicy {
1653
+ /** Effective assertion-signing requirement advertised by SP metadata. */
1654
+ wantAssertionsSigned: boolean;
1655
+ }
1656
+ /**
1657
+ * Parses custom SP metadata and returns its effective verification policy.
1658
+ *
1659
+ * Configurations without custom metadata use the code-defined policy directly.
1660
+ * Invalid or unusable custom metadata throws an API error with the
1661
+ * `SAML_INVALID_SP_METADATA` code.
1662
+ */
1663
+ declare function deriveSAMLServiceProviderPolicy(config: Pick<SAMLConfig, "spMetadata" | "wantAssertionsSigned">): SAMLServiceProviderPolicy;
1664
+ /**
1665
+ * Derive the verified SAML identity-provider entity ID using the same metadata
1666
+ * parsing and manual-configuration validation as SAML authentication.
1667
+ */
1668
+ declare function deriveSAMLIdentityProviderEntityID(config: SAMLConfig): string;
1669
+ //#endregion
1579
1670
  //#region src/saml/timestamp.d.ts
1580
1671
  interface TimestampValidationOptions {
1581
1672
  clockSkew?: number;
@@ -1930,4 +2021,4 @@ declare function sso<O extends SSOOptions>(options?: O | undefined): {
1930
2021
  options: NoInfer<O>;
1931
2022
  };
1932
2023
  //#endregion
1933
- export { SSOProviderUserProfile as A, DEFAULT_MAX_SAML_METADATA_SIZE as C, SAMLIdentityProviderMetadata as D, SAMLConfig as E, DataEncryptionAlgorithm as F, DeprecatedAlgorithmBehavior as I, DigestAlgorithm as L, SSOUserResolutionContext as M, SSOUserResolutionInput as N, SSOOptions as O, AlgorithmValidationOptions as P, KeyEncryptionAlgorithm as R, DEFAULT_CLOCK_SKEW_MS as S, OIDCConfig as T, REQUIRED_DISCOVERY_FIELDS as _, fetchDiscoveryDocument as a, TimestampValidationOptions as b, normalizeUrl as c, validateDiscoveryUrl as d, DiscoverOIDCConfigParams as f, OIDCDiscoveryDocument as g, HydratedOIDCConfig as h, discoverOIDCConfig as i, SSOUserResolution as j, SSOProvider as k, selectTokenEndpointAuthMethod as l, DiscoveryErrorCode as m, sso as n, needsRuntimeDiscovery as o, DiscoveryError as p, computeDiscoveryUrl as r, normalizeDiscoveryUrls as s, SSOPlugin as t, validateDiscoveryDocument as u, RequiredDiscoveryField as v, DEFAULT_MAX_SAML_RESPONSE_SIZE as w, validateSAMLTimestamp as x, SAMLConditions as y, SignatureAlgorithm as z };
2024
+ export { SAMLIdentityProviderMetadata as A, SSOUserResolutionContext as B, deriveSAMLIdentityProviderEntityID as C, DEFAULT_MAX_SAML_RESPONSE_SIZE as D, DEFAULT_MAX_SAML_METADATA_SIZE as E, SSOProviderMutationGuardInput as F, DigestAlgorithm as G, AlgorithmValidationOptions as H, SSOProviderReference as I, KeyEncryptionAlgorithm as K, SSOProviderUserProfile as L, SSOOptions as M, SSOProvider as N, OIDCConfig as O, SSOProviderMutationGuardContext as P, SSOSAMLUserResolutionInput as R, SAMLServiceProviderPolicy as S, DEFAULT_CLOCK_SKEW_MS as T, DataEncryptionAlgorithm as U, SSOUserResolutionInput as V, DeprecatedAlgorithmBehavior as W, REQUIRED_DISCOVERY_FIELDS as _, fetchDiscoveryDocument as a, TimestampValidationOptions as b, normalizeUrl as c, validateDiscoveryUrl as d, DiscoverOIDCConfigParams as f, OIDCDiscoveryDocument as g, HydratedOIDCConfig as h, discoverOIDCConfig as i, SSOOIDCUserResolutionInput as j, SAMLConfig as k, selectTokenEndpointAuthMethod as l, DiscoveryErrorCode as m, sso as n, needsRuntimeDiscovery as o, DiscoveryError as p, SignatureAlgorithm as q, computeDiscoveryUrl as r, normalizeDiscoveryUrls as s, SSOPlugin as t, validateDiscoveryDocument as u, RequiredDiscoveryField as v, deriveSAMLServiceProviderPolicy as w, validateSAMLTimestamp as x, SAMLConditions as y, SSOUserResolution as z };
package/dist/index.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- import { A as SSOProviderUserProfile, C as DEFAULT_MAX_SAML_METADATA_SIZE, D as SAMLIdentityProviderMetadata, E as SAMLConfig, F as DataEncryptionAlgorithm, I as DeprecatedAlgorithmBehavior, L as DigestAlgorithm, M as SSOUserResolutionContext, N as SSOUserResolutionInput, O as SSOOptions, P as AlgorithmValidationOptions, R as KeyEncryptionAlgorithm, S as DEFAULT_CLOCK_SKEW_MS, T as OIDCConfig, _ 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 SSOUserResolution, k as SSOProvider, l as selectTokenEndpointAuthMethod, m as DiscoveryErrorCode, n as sso, o as needsRuntimeDiscovery, p as DiscoveryError, r as computeDiscoveryUrl, s as normalizeDiscoveryUrls, t as SSOPlugin, u as validateDiscoveryDocument, v as RequiredDiscoveryField, w as DEFAULT_MAX_SAML_RESPONSE_SIZE, x as validateSAMLTimestamp, y as SAMLConditions, z as SignatureAlgorithm } from "./index-D1yk91me.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 SSOOptions, SSOPlugin, type SSOProvider, type SSOProviderUserProfile, type SSOUserResolution, type SSOUserResolutionContext, type SSOUserResolutionInput, SignatureAlgorithm, type TimestampValidationOptions, computeDiscoveryUrl, 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-nfENSAuB.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 };