@better-auth/sso 1.7.21 → 1.7.23
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-
|
|
1
|
+
import { t as SSOPlugin } from "./index-CndkJEsk.mjs";
|
|
2
2
|
import { DBFieldAttribute } from "better-auth/db";
|
|
3
|
-
//#region src/client.d.ts
|
|
4
3
|
interface SSOClientOptions {
|
|
5
4
|
domainVerification?: {
|
|
6
5
|
enabled: boolean;
|
|
@@ -29,5 +28,4 @@ export declare const ssoClient: <CO extends SSOClientOptions>(options?: CO | und
|
|
|
29
28
|
"/sso/get-provider": "GET";
|
|
30
29
|
};
|
|
31
30
|
};
|
|
32
|
-
//#endregion
|
|
33
31
|
export {};
|
package/dist/client.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { t as PACKAGE_VERSION } from "./version-
|
|
2
|
-
|
|
1
|
+
import { t as PACKAGE_VERSION } from "./version-C4dOSLv6.mjs";
|
|
2
|
+
// src/client.ts
|
|
3
3
|
const ssoClient = (options) => {
|
|
4
4
|
return {
|
|
5
5
|
id: "sso-client",
|
|
@@ -11,5 +11,4 @@ const ssoClient = (options) => {
|
|
|
11
11
|
}
|
|
12
12
|
};
|
|
13
13
|
};
|
|
14
|
-
//#endregion
|
|
15
14
|
export { ssoClient };
|
|
@@ -6,7 +6,6 @@ import { DBFieldAttribute, FieldAttributeToObject, InferAdditionalFieldsFromPlug
|
|
|
6
6
|
import { Awaitable, DBTransactionAdapter, OAuth2Tokens, User } from "better-auth";
|
|
7
7
|
import "@better-auth/core/db/adapter";
|
|
8
8
|
import "@better-auth/core";
|
|
9
|
-
//#region src/saml/algorithms.d.ts
|
|
10
9
|
declare const SignatureAlgorithm: {
|
|
11
10
|
readonly RSA_SHA1: "http://www.w3.org/2000/09/xmldsig#rsa-sha1";
|
|
12
11
|
readonly RSA_SHA256: "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";
|
|
@@ -44,8 +43,6 @@ interface AlgorithmValidationOptions {
|
|
|
44
43
|
allowedKeyEncryptionAlgorithms?: string[];
|
|
45
44
|
allowedDataEncryptionAlgorithms?: string[];
|
|
46
45
|
}
|
|
47
|
-
//#endregion
|
|
48
|
-
//#region src/types.d.ts
|
|
49
46
|
interface OIDCMapping {
|
|
50
47
|
email?: string | undefined;
|
|
51
48
|
emailVerified?: string | undefined;
|
|
@@ -683,8 +680,6 @@ interface SSOOptions {
|
|
|
683
680
|
idpInitiatedCallbackUrl?: string | undefined;
|
|
684
681
|
};
|
|
685
682
|
}
|
|
686
|
-
//#endregion
|
|
687
|
-
//#region src/routes/domain-verification.d.ts
|
|
688
683
|
declare const requestDomainVerification: (options: SSOOptions) => import("better-call").StrictEndpoint<"/sso/request-domain-verification", {
|
|
689
684
|
method: "POST";
|
|
690
685
|
body: z.ZodObject<{
|
|
@@ -782,16 +777,12 @@ declare const verifyDomain: (options: SSOOptions) => import("better-call").Stric
|
|
|
782
777
|
};
|
|
783
778
|
}>>[];
|
|
784
779
|
}, void>;
|
|
785
|
-
//#endregion
|
|
786
|
-
//#region src/utils.d.ts
|
|
787
780
|
declare function parseCertificate(certPem: string): {
|
|
788
781
|
fingerprintSha256: string;
|
|
789
782
|
notBefore: string;
|
|
790
783
|
notAfter: string;
|
|
791
784
|
publicKeyAlgorithm: string;
|
|
792
785
|
};
|
|
793
|
-
//#endregion
|
|
794
|
-
//#region src/routes/providers.d.ts
|
|
795
786
|
type ParsedCert = ReturnType<typeof parseCertificate>;
|
|
796
787
|
type SanitizedCert = ParsedCert | {
|
|
797
788
|
error: string;
|
|
@@ -1150,8 +1141,6 @@ declare const deleteSSOProvider: (options?: SSOOptions) => import("better-call")
|
|
|
1150
1141
|
}, {
|
|
1151
1142
|
success: boolean;
|
|
1152
1143
|
}>;
|
|
1153
|
-
//#endregion
|
|
1154
|
-
//#region src/routes/sso.d.ts
|
|
1155
1144
|
declare const spMetadata: (options?: SSOOptions) => import("better-call").StrictEndpoint<"/sso/saml2/sp/metadata", {
|
|
1156
1145
|
method: "GET";
|
|
1157
1146
|
query: z.ZodObject<{
|
|
@@ -1200,7 +1189,9 @@ declare const registerSSOProvider: <O extends SSOOptions>(options: O) => import(
|
|
|
1200
1189
|
}>>[];
|
|
1201
1190
|
metadata: {
|
|
1202
1191
|
$Infer: {
|
|
1203
|
-
body:
|
|
1192
|
+
body: {
|
|
1193
|
+
[x: string]: any;
|
|
1194
|
+
} & SSOProviderAdditionalFieldsInput<O>;
|
|
1204
1195
|
};
|
|
1205
1196
|
openapi: {
|
|
1206
1197
|
operationId: string;
|
|
@@ -1627,8 +1618,6 @@ declare const initiateSLO: (options?: SSOOptions) => import("better-call").Stric
|
|
|
1627
1618
|
readonly scope: "server";
|
|
1628
1619
|
};
|
|
1629
1620
|
}, never>;
|
|
1630
|
-
//#endregion
|
|
1631
|
-
//#region src/constants.d.ts
|
|
1632
1621
|
/**
|
|
1633
1622
|
* Default clock skew tolerance (5 minutes).
|
|
1634
1623
|
* Allows for minor time differences between IdP and SP servers.
|
|
@@ -1649,8 +1638,6 @@ declare const DEFAULT_MAX_SAML_RESPONSE_SIZE: number;
|
|
|
1649
1638
|
* Protects against oversized metadata documents.
|
|
1650
1639
|
*/
|
|
1651
1640
|
declare const DEFAULT_MAX_SAML_METADATA_SIZE: number;
|
|
1652
|
-
//#endregion
|
|
1653
|
-
//#region src/routes/helpers.d.ts
|
|
1654
1641
|
interface SAMLServiceProviderPolicy {
|
|
1655
1642
|
/** Effective assertion-signing requirement advertised by SP metadata. */
|
|
1656
1643
|
wantAssertionsSigned: boolean;
|
|
@@ -1668,8 +1655,6 @@ declare function deriveSAMLServiceProviderPolicy(config: Pick<SAMLConfig, "spMet
|
|
|
1668
1655
|
* parsing and manual-configuration validation as SAML authentication.
|
|
1669
1656
|
*/
|
|
1670
1657
|
declare function deriveSAMLIdentityProviderEntityID(config: SAMLConfig): string;
|
|
1671
|
-
//#endregion
|
|
1672
|
-
//#region src/saml/timestamp.d.ts
|
|
1673
1658
|
interface TimestampValidationOptions {
|
|
1674
1659
|
clockSkew?: number;
|
|
1675
1660
|
requireTimestamps?: boolean;
|
|
@@ -1688,8 +1673,6 @@ interface SAMLConditions {
|
|
|
1688
1673
|
* @throws {APIError} If timestamps are invalid, expired, or not yet valid
|
|
1689
1674
|
*/
|
|
1690
1675
|
declare function validateSAMLTimestamp(conditions: SAMLConditions | undefined, options?: TimestampValidationOptions): void;
|
|
1691
|
-
//#endregion
|
|
1692
|
-
//#region src/oidc/types.d.ts
|
|
1693
1676
|
/**
|
|
1694
1677
|
* OIDC Discovery Types
|
|
1695
1678
|
*
|
|
@@ -1856,8 +1839,6 @@ interface DiscoverOIDCConfigParams {
|
|
|
1856
1839
|
*/
|
|
1857
1840
|
declare const REQUIRED_DISCOVERY_FIELDS: readonly ["issuer", "authorization_endpoint", "token_endpoint", "jwks_uri"];
|
|
1858
1841
|
type RequiredDiscoveryField = (typeof REQUIRED_DISCOVERY_FIELDS)[number];
|
|
1859
|
-
//#endregion
|
|
1860
|
-
//#region src/oidc/discovery.d.ts
|
|
1861
1842
|
/**
|
|
1862
1843
|
* Main entry point: Discover and hydrate OIDC configuration from an issuer.
|
|
1863
1844
|
*
|
|
@@ -1957,8 +1938,6 @@ declare function selectTokenEndpointAuthMethod(doc: OIDCDiscoveryDocument, exist
|
|
|
1957
1938
|
* @returns true if runtime discovery should be performed
|
|
1958
1939
|
*/
|
|
1959
1940
|
declare function needsRuntimeDiscovery(config: Partial<HydratedOIDCConfig> | undefined): boolean;
|
|
1960
|
-
//#endregion
|
|
1961
|
-
//#region src/index.d.ts
|
|
1962
1941
|
declare module "@better-auth/core" {
|
|
1963
1942
|
interface BetterAuthPluginRegistry<AuthOptions, Options> {
|
|
1964
1943
|
sso: {
|
|
@@ -2022,5 +2001,4 @@ declare function sso<O extends SSOOptions>(options?: O | undefined): {
|
|
|
2022
2001
|
};
|
|
2023
2002
|
options: NoInfer<O>;
|
|
2024
2003
|
};
|
|
2025
|
-
//#endregion
|
|
2026
2004
|
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 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-
|
|
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-CndkJEsk.mjs";
|
|
2
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-
|
|
1
|
+
import { t as PACKAGE_VERSION } from "./version-C4dOSLv6.mjs";
|
|
2
2
|
import { APIError, addOAuthServerContext, createAuthEndpoint, createAuthMiddleware, generateGenericState, getSessionFromCtx, parseGenericState, sessionMiddleware } from "better-auth/api";
|
|
3
3
|
import { XMLParser, XMLValidator } from "fast-xml-parser";
|
|
4
4
|
import { X509Certificate } from "node:crypto";
|
|
@@ -18,12 +18,12 @@ 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 { HIDE_METADATA } from "@better-auth/core/api";
|
|
21
|
-
import { PRIVATE_KEY_JWT_SIGNING_ALGORITHMS, authorizationCodeRequest, createAuthorizationURL, createPrivateKeyJwtClientAssertionGetter, getOAuth2Tokens } from "@better-auth/core/oauth2";
|
|
21
|
+
import { PRIVATE_KEY_JWT_SIGNING_ALGORITHMS, authorizationCodeRequest, createAuthorizationURL, createPrivateKeyJwtClientAssertionGetter, getOAuth2Tokens, parseStringBoolean } from "@better-auth/core/oauth2";
|
|
22
22
|
import { isAPIError } from "@better-auth/core/utils/is-api-error";
|
|
23
23
|
import { appendQueryParams } from "@better-auth/core/utils/url";
|
|
24
24
|
import { deleteSessionCookie, setAccountCookie, setSessionCookie } from "better-auth/cookies";
|
|
25
25
|
import { additionalAuthorizationParamsSchema, generateState, handleOAuthUserInfo, parseState } from "better-auth/oauth2";
|
|
26
|
-
|
|
26
|
+
// src/constants.ts
|
|
27
27
|
/**
|
|
28
28
|
* SAML Constants
|
|
29
29
|
*
|
|
@@ -62,8 +62,7 @@ const DEFAULT_MAX_SAML_RESPONSE_SIZE = 262144;
|
|
|
62
62
|
* Protects against oversized metadata documents.
|
|
63
63
|
*/
|
|
64
64
|
const DEFAULT_MAX_SAML_METADATA_SIZE = 102400;
|
|
65
|
-
|
|
66
|
-
//#region src/utils.ts
|
|
65
|
+
// src/utils.ts
|
|
67
66
|
const unsafeSAMLRedirectPathPrefix = /^\/(?:\/|\\|%2f|%5c)/i;
|
|
68
67
|
const isSafeSAMLRedirectPath = (url) => url.startsWith("/") && !unsafeSAMLRedirectPathPrefix.test(url);
|
|
69
68
|
/**
|
|
@@ -95,16 +94,6 @@ const domainMatches = (searchDomain, domainList) => {
|
|
|
95
94
|
return domains.some((domain) => search === domain || search.endsWith(`.${domain}`));
|
|
96
95
|
};
|
|
97
96
|
/**
|
|
98
|
-
* Strictly parse a provider-supplied email-verification claim.
|
|
99
|
-
*
|
|
100
|
-
* OIDC userInfo, OIDC id-token, and SAML attribute values are frequently
|
|
101
|
-
* strings, so a loose `Boolean(value)` or truthy fallback treats the string
|
|
102
|
-
* `"false"` as verified. Only a boolean `true` or the exact string `"true"`
|
|
103
|
-
* count as verified; every other value, including `"false"`, `"0"`, `""`,
|
|
104
|
-
* numbers, arrays, and objects, is unverified.
|
|
105
|
-
*/
|
|
106
|
-
const parseProviderEmailVerified = (value) => value === true || value === "true";
|
|
107
|
-
/**
|
|
108
97
|
* Validates email domain against allowed domain(s).
|
|
109
98
|
* Supports comma-separated domains for multi-domain SSO.
|
|
110
99
|
*/
|
|
@@ -152,8 +141,7 @@ function maskClientId(clientId) {
|
|
|
152
141
|
if (clientId.length <= 4) return "****";
|
|
153
142
|
return `****${clientId.slice(-4)}`;
|
|
154
143
|
}
|
|
155
|
-
|
|
156
|
-
//#region src/linking/org-assignment.ts
|
|
144
|
+
// src/linking/org-assignment.ts
|
|
157
145
|
const VERIFIED_PROVIDER_PAGE_SIZE = 100;
|
|
158
146
|
function getEmailDomain(email) {
|
|
159
147
|
const parts = email.trim().toLowerCase().split("@");
|
|
@@ -296,8 +284,7 @@ async function assignOrganizationByDomain(ctx, options) {
|
|
|
296
284
|
...options
|
|
297
285
|
});
|
|
298
286
|
}
|
|
299
|
-
|
|
300
|
-
//#region src/oidc/types.ts
|
|
287
|
+
// src/oidc/types.ts
|
|
301
288
|
/**
|
|
302
289
|
* Custom error class for OIDC discovery failures.
|
|
303
290
|
* Can be caught and mapped to APIError at the edge.
|
|
@@ -322,8 +309,7 @@ const REQUIRED_DISCOVERY_FIELDS = [
|
|
|
322
309
|
"token_endpoint",
|
|
323
310
|
"jwks_uri"
|
|
324
311
|
];
|
|
325
|
-
|
|
326
|
-
//#region src/oidc/discovery.ts
|
|
312
|
+
// src/oidc/discovery.ts
|
|
327
313
|
/**
|
|
328
314
|
* OIDC Discovery Pipeline
|
|
329
315
|
*
|
|
@@ -789,8 +775,7 @@ async function ensureRuntimeDiscovery(config, issuer, isTrustedOrigin) {
|
|
|
789
775
|
await assertServerFetchedOIDCEndpointsAllowed(resolved, isTrustedOrigin);
|
|
790
776
|
return resolved;
|
|
791
777
|
}
|
|
792
|
-
|
|
793
|
-
//#region src/oidc/errors.ts
|
|
778
|
+
// src/oidc/errors.ts
|
|
794
779
|
/**
|
|
795
780
|
* OIDC Discovery Error Mapping
|
|
796
781
|
*
|
|
@@ -870,8 +855,7 @@ function mapDiscoveryErrorToAPIError(error) {
|
|
|
870
855
|
});
|
|
871
856
|
}
|
|
872
857
|
}
|
|
873
|
-
|
|
874
|
-
//#region src/provider-reference.ts
|
|
858
|
+
// src/provider-reference.ts
|
|
875
859
|
const SSO_PROVIDER_STATE_KEY = "ssoProviderReference";
|
|
876
860
|
function serializeCanonical(value) {
|
|
877
861
|
if (value === null) return "null";
|
|
@@ -966,8 +950,7 @@ async function isCurrentSSOProviderReference(provider, reference) {
|
|
|
966
950
|
if (source.type === "persisted" && (reference.source.type !== "persisted" || source.recordId !== reference.source.recordId)) return false;
|
|
967
951
|
return reference.authenticationConfigurationFingerprint === await computeProviderAuthenticationFingerprint(provider);
|
|
968
952
|
}
|
|
969
|
-
|
|
970
|
-
//#region src/saml/parser.ts
|
|
953
|
+
// src/saml/parser.ts
|
|
971
954
|
const xmlParser = new XMLParser({
|
|
972
955
|
ignoreAttributes: false,
|
|
973
956
|
attributeNamePrefix: "@_",
|
|
@@ -1000,8 +983,7 @@ function countAllNodes(obj, nodeName) {
|
|
|
1000
983
|
else if (typeof value === "object" && value !== null) count += countAllNodes(value, nodeName);
|
|
1001
984
|
return count;
|
|
1002
985
|
}
|
|
1003
|
-
|
|
1004
|
-
//#region src/saml/algorithms.ts
|
|
986
|
+
// src/saml/algorithms.ts
|
|
1005
987
|
const SignatureAlgorithm = {
|
|
1006
988
|
RSA_SHA1: "http://www.w3.org/2000/09/xmldsig#rsa-sha1",
|
|
1007
989
|
RSA_SHA256: "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256",
|
|
@@ -1178,8 +1160,7 @@ function validateConfigAlgorithms(config, options = {}) {
|
|
|
1178
1160
|
}
|
|
1179
1161
|
}
|
|
1180
1162
|
const saml = typeof samlifyNamespace.SPMetadata === "function" && typeof samlifyNamespace.setSchemaValidator === "function" ? samlifyNamespace : samlifyDefault ?? samlifyNamespace;
|
|
1181
|
-
|
|
1182
|
-
//#region src/saml/assertions.ts
|
|
1163
|
+
// src/saml/assertions.ts
|
|
1183
1164
|
const SAML_ASSERTION_NAMESPACE = "urn:oasis:names:tc:SAML:2.0:assertion";
|
|
1184
1165
|
const SAML_PROTOCOL_NAMESPACE = "urn:oasis:names:tc:SAML:2.0:protocol";
|
|
1185
1166
|
const XML_SIGNATURE_NAMESPACE = "http://www.w3.org/2000/09/xmldsig#";
|
|
@@ -1255,8 +1236,7 @@ function verifySAMLAssertionSignature(samlContent, verificationOptions) {
|
|
|
1255
1236
|
throw assertionSignatureFailure();
|
|
1256
1237
|
}
|
|
1257
1238
|
}
|
|
1258
|
-
|
|
1259
|
-
//#region src/saml/error-codes.ts
|
|
1239
|
+
// src/saml/error-codes.ts
|
|
1260
1240
|
const SAML_ERROR_CODES = defineErrorCodes({
|
|
1261
1241
|
SINGLE_LOGOUT_NOT_ENABLED: "Single Logout is not enabled",
|
|
1262
1242
|
INVALID_LOGOUT_RESPONSE: "Invalid LogoutResponse",
|
|
@@ -1266,8 +1246,7 @@ const SAML_ERROR_CODES = defineErrorCodes({
|
|
|
1266
1246
|
SAML_PROVIDER_NOT_FOUND: "SAML provider not found",
|
|
1267
1247
|
CERT_SOURCE_MISSING: "samlConfig requires either a signing certificate (cert or idpMetadata.cert) or an idpMetadata.metadata XML document."
|
|
1268
1248
|
});
|
|
1269
|
-
|
|
1270
|
-
//#region src/saml/cert.ts
|
|
1249
|
+
// src/saml/cert.ts
|
|
1271
1250
|
/**
|
|
1272
1251
|
* IdP signing-certificate rules for SAML configs. Centralized so the runtime
|
|
1273
1252
|
* verification path (`createIdP`), the sanitizer (`getSSOProvider` and
|
|
@@ -1296,8 +1275,7 @@ function validateCertSources(config) {
|
|
|
1296
1275
|
const hasExplicitCert = config.idpMetadata?.cert !== void 0 || config.cert !== void 0;
|
|
1297
1276
|
if (!hasMetadataXml && !hasExplicitCert) throw APIError.from("BAD_REQUEST", SAML_ERROR_CODES.CERT_SOURCE_MISSING);
|
|
1298
1277
|
}
|
|
1299
|
-
|
|
1300
|
-
//#region src/saml/response-binding.ts
|
|
1278
|
+
// src/saml/response-binding.ts
|
|
1301
1279
|
const SAML_HTTP_POST_BINDING = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST";
|
|
1302
1280
|
const SAML_BEARER_CONFIRMATION_METHOD = "urn:oasis:names:tc:SAML:2.0:cm:bearer";
|
|
1303
1281
|
const SAML_METADATA_NAMESPACE = "urn:oasis:names:tc:SAML:2.0:metadata";
|
|
@@ -1474,8 +1452,7 @@ function validateSAMLResponseBinding(samlContent, options) {
|
|
|
1474
1452
|
validateBearerRecipient(assertion, expectedRecipients);
|
|
1475
1453
|
validateResponseDestination(response, expectedRecipients);
|
|
1476
1454
|
}
|
|
1477
|
-
|
|
1478
|
-
//#region src/saml/response-validation.ts
|
|
1455
|
+
// src/saml/response-validation.ts
|
|
1479
1456
|
function errorRedirectUrl(base, error, description) {
|
|
1480
1457
|
try {
|
|
1481
1458
|
const url = new URL(base);
|
|
@@ -1572,8 +1549,7 @@ function validateAudience(c, ctx) {
|
|
|
1572
1549
|
throw c.redirect(errorRedirectUrl(ctx.redirectUrl, "invalid_saml_response", "Audience mismatch"));
|
|
1573
1550
|
}
|
|
1574
1551
|
}
|
|
1575
|
-
|
|
1576
|
-
//#region src/user-resolution.ts
|
|
1552
|
+
// src/user-resolution.ts
|
|
1577
1553
|
const SSO_AUTHENTICATION_FAILURE = Symbol("SSO_AUTHENTICATION_FAILURE");
|
|
1578
1554
|
function isRecord$1(value) {
|
|
1579
1555
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -1659,8 +1635,7 @@ function getFailedSSOAuthenticationResult(error) {
|
|
|
1659
1635
|
if (!(error instanceof Error) || !(SSO_AUTHENTICATION_FAILURE in error) || error[SSO_AUTHENTICATION_FAILURE] !== true || !("result" in error)) return;
|
|
1660
1636
|
return error.result;
|
|
1661
1637
|
}
|
|
1662
|
-
|
|
1663
|
-
//#region src/routes/helpers.ts
|
|
1638
|
+
// src/routes/helpers.ts
|
|
1664
1639
|
/**
|
|
1665
1640
|
* Same as `normalizePem`, but applied across the resolved list of IdP signing
|
|
1666
1641
|
* certificates so multi-cert rotation configs survive the line-trim step.
|
|
@@ -1824,8 +1799,7 @@ function createSAMLPostForm(action, samlParam, samlValue, relayState) {
|
|
|
1824
1799
|
const html = `<!DOCTYPE html><html><body onload="document.forms[0].submit();"><form method="POST" action="${safeAction}"><input type="hidden" name="${safeSamlParam}" value="${safeSamlValue}" />${safeRelayState ? `<input type="hidden" name="RelayState" value="${safeRelayState}" />` : ""}<noscript><input type="submit" value="Continue" /></noscript></form></body></html>`;
|
|
1825
1800
|
return new Response(html, { headers: { "Content-Type": "text/html" } });
|
|
1826
1801
|
}
|
|
1827
|
-
|
|
1828
|
-
//#region src/routes/schemas.ts
|
|
1802
|
+
// src/routes/schemas.ts
|
|
1829
1803
|
const absoluteUrlSchema = z.url();
|
|
1830
1804
|
const samlRedirectUrlSchema = z.string().refine((url) => isSafeSAMLRedirectPath(url) || absoluteUrlSchema.safeParse(url).success, { message: "Expected an absolute URL or a relative path starting with /" });
|
|
1831
1805
|
function getSSOProviderAdditionalFields$1(options) {
|
|
@@ -1968,8 +1942,7 @@ function getUpdateSSOProviderBodySchema(options) {
|
|
|
1968
1942
|
...getSSOProviderAdditionalFieldsSchema(options).partial().shape
|
|
1969
1943
|
});
|
|
1970
1944
|
}
|
|
1971
|
-
|
|
1972
|
-
//#region src/routes/providers.ts
|
|
1945
|
+
// src/routes/providers.ts
|
|
1973
1946
|
const ADMIN_ROLES = ["owner", "admin"];
|
|
1974
1947
|
const OIDC_IDENTITY_BOUNDARY_FIELDS = [
|
|
1975
1948
|
"authorizationEndpoint",
|
|
@@ -2520,8 +2493,7 @@ const deleteSSOProvider = (options) => {
|
|
|
2520
2493
|
return ctx.json({ success: true });
|
|
2521
2494
|
});
|
|
2522
2495
|
};
|
|
2523
|
-
|
|
2524
|
-
//#region src/routes/domain-verification.ts
|
|
2496
|
+
// src/routes/domain-verification.ts
|
|
2525
2497
|
const DNS_LABEL_MAX_LENGTH = 63;
|
|
2526
2498
|
const DEFAULT_TOKEN_PREFIX = "better-auth-token";
|
|
2527
2499
|
const domainVerificationBodySchema = z.object({ providerId: z.string() });
|
|
@@ -2650,8 +2622,7 @@ const verifyDomain = (options) => {
|
|
|
2650
2622
|
ctx.setStatus(204);
|
|
2651
2623
|
});
|
|
2652
2624
|
};
|
|
2653
|
-
|
|
2654
|
-
//#region src/saml-state.ts
|
|
2625
|
+
// src/saml-state.ts
|
|
2655
2626
|
async function generateRelayState(c, link, providerReference) {
|
|
2656
2627
|
const callbackURL = c.body.callbackURL;
|
|
2657
2628
|
if (!callbackURL) throw new APIError("BAD_REQUEST", { message: "callbackURL is required" });
|
|
@@ -2701,8 +2672,7 @@ async function parseRelayState(c) {
|
|
|
2701
2672
|
if (!parsedData.errorURL) parsedData.errorURL = errorURL;
|
|
2702
2673
|
return parsedData;
|
|
2703
2674
|
}
|
|
2704
|
-
|
|
2705
|
-
//#region src/saml/timestamp.ts
|
|
2675
|
+
// src/saml/timestamp.ts
|
|
2706
2676
|
/**
|
|
2707
2677
|
* Validates SAML assertion timestamp conditions (NotBefore/NotOnOrAfter).
|
|
2708
2678
|
* Prevents acceptance of expired or future-dated assertions.
|
|
@@ -2742,8 +2712,7 @@ function validateSAMLTimestamp(conditions, options = {}) {
|
|
|
2742
2712
|
});
|
|
2743
2713
|
}
|
|
2744
2714
|
}
|
|
2745
|
-
|
|
2746
|
-
//#region src/routes/saml-pipeline.ts
|
|
2715
|
+
// src/routes/saml-pipeline.ts
|
|
2747
2716
|
function isSameSSOProviderReference(left, right) {
|
|
2748
2717
|
if (left.providerId !== right.providerId || left.authenticationConfigurationFingerprint !== right.authenticationConfigurationFingerprint || left.source.type !== right.source.type) return false;
|
|
2749
2718
|
return left.source.type === "configured" ? true : right.source.type === "persisted" && left.source.recordId === right.source.recordId;
|
|
@@ -2996,7 +2965,7 @@ async function processSAMLResponse(ctx, params, options) {
|
|
|
2996
2965
|
id: extract.nameID,
|
|
2997
2966
|
email: (attr(mapping.email || "email") || extract.nameID || "").toLowerCase(),
|
|
2998
2967
|
name: [attr(mapping.firstName || "givenName"), attr(mapping.lastName || "surname")].filter(Boolean).join(" ") || attr(mapping.name || "displayName") || extract.nameID,
|
|
2999
|
-
emailVerified: options?.trustEmailVerified && mapping.emailVerified ?
|
|
2968
|
+
emailVerified: options?.trustEmailVerified && mapping.emailVerified ? parseStringBoolean(attr(mapping.emailVerified)) ?? false : false
|
|
3000
2969
|
};
|
|
3001
2970
|
if (!userInfo.id || !userInfo.email) {
|
|
3002
2971
|
ctx.context.logger.error("Missing essential user info from SAML response", {
|
|
@@ -3137,8 +3106,7 @@ async function processSAMLResponse(ctx, params, options) {
|
|
|
3137
3106
|
}
|
|
3138
3107
|
return samlRedirectUrl;
|
|
3139
3108
|
}
|
|
3140
|
-
|
|
3141
|
-
//#region src/routes/sso.ts
|
|
3109
|
+
// src/routes/sso.ts
|
|
3142
3110
|
const BUILT_IN_ACCOUNT_PROVIDER_IDS = [
|
|
3143
3111
|
"credential",
|
|
3144
3112
|
"email-otp",
|
|
@@ -3936,7 +3904,7 @@ async function handleOIDCCallback(ctx, options, providerId, stateData, parsedPro
|
|
|
3936
3904
|
...Object.fromEntries(Object.entries(mapping.extraFields || {}).map(([key, value]) => [key, rawUserInfo[value]])),
|
|
3937
3905
|
id: readStringClaim(rawUserInfo, "sub"),
|
|
3938
3906
|
email: readEmailClaim(rawUserInfo),
|
|
3939
|
-
emailVerified: options?.trustEmailVerified ?
|
|
3907
|
+
emailVerified: options?.trustEmailVerified ? parseStringBoolean(rawUserInfo[mapping.emailVerified || "email_verified"]) ?? false : false,
|
|
3940
3908
|
name: readStringClaim(rawUserInfo, mapping.name || "name"),
|
|
3941
3909
|
image: readStringClaim(rawUserInfo, mapping.image || "picture")
|
|
3942
3910
|
};
|
|
@@ -3947,7 +3915,7 @@ async function handleOIDCCallback(ctx, options, providerId, stateData, parsedPro
|
|
|
3947
3915
|
...Object.fromEntries(Object.entries(mapping.extraFields || {}).map(([key, value]) => [key, idToken[value]])),
|
|
3948
3916
|
id: idToken.sub,
|
|
3949
3917
|
email: readEmailClaim(idToken),
|
|
3950
|
-
emailVerified: options?.trustEmailVerified ?
|
|
3918
|
+
emailVerified: options?.trustEmailVerified ? parseStringBoolean(idToken[mapping.emailVerified || "email_verified"]) ?? false : false,
|
|
3951
3919
|
name: readStringClaim(idToken, mapping.name || "name"),
|
|
3952
3920
|
image: readStringClaim(idToken, mapping.image || "picture")
|
|
3953
3921
|
};
|
|
@@ -4456,8 +4424,7 @@ const initiateSLO = (options) => {
|
|
|
4456
4424
|
throw ctx.redirect(logoutRequest.context);
|
|
4457
4425
|
});
|
|
4458
4426
|
};
|
|
4459
|
-
|
|
4460
|
-
//#region src/index.ts
|
|
4427
|
+
// src/index.ts
|
|
4461
4428
|
saml.setSchemaValidator({ async validate(xml) {
|
|
4462
4429
|
if (XMLValidator.validate(xml, { allowBooleanAttributes: true }) === true) return "SUCCESS_VALIDATE_XML";
|
|
4463
4430
|
throw "ERR_INVALID_XML";
|
|
@@ -4677,5 +4644,4 @@ function sso(options) {
|
|
|
4677
4644
|
options
|
|
4678
4645
|
};
|
|
4679
4646
|
}
|
|
4680
|
-
//#endregion
|
|
4681
4647
|
export { DEFAULT_CLOCK_SKEW_MS, DEFAULT_MAX_SAML_METADATA_SIZE, DEFAULT_MAX_SAML_RESPONSE_SIZE, DataEncryptionAlgorithm, DigestAlgorithm, DiscoveryError, KeyEncryptionAlgorithm, REQUIRED_DISCOVERY_FIELDS, SignatureAlgorithm, computeDiscoveryUrl, deriveSAMLIdentityProviderEntityID, deriveSAMLServiceProviderPolicy, discoverOIDCConfig, fetchDiscoveryDocument, needsRuntimeDiscovery, normalizeDiscoveryUrls, normalizeUrl, selectTokenEndpointAuthMethod, sso, validateDiscoveryDocument, validateDiscoveryUrl, validateSAMLTimestamp };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@better-auth/sso",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.23",
|
|
4
4
|
"description": "SSO plugin for Better Auth",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -64,24 +64,24 @@
|
|
|
64
64
|
"zod": "^4.5.4"
|
|
65
65
|
},
|
|
66
66
|
"devDependencies": {
|
|
67
|
+
"@better-auth/core": "1.7.23",
|
|
68
|
+
"@better-auth/kysely-adapter": "1.7.23",
|
|
67
69
|
"@types/body-parser": "^1.19.6",
|
|
68
70
|
"@types/express": "^5.0.6",
|
|
71
|
+
"better-auth": "1.7.23",
|
|
69
72
|
"better-call": "1.4.5",
|
|
70
73
|
"body-parser": "^2.3.0",
|
|
71
74
|
"express": "^5.2.1",
|
|
72
75
|
"kysely": "^0.28.17 || ^0.29.0",
|
|
73
76
|
"oauth2-mock-server": "^9.0.0",
|
|
74
|
-
"tsdown": "0.23.1"
|
|
75
|
-
"@better-auth/core": "1.7.21",
|
|
76
|
-
"@better-auth/kysely-adapter": "1.7.21",
|
|
77
|
-
"better-auth": "1.7.21"
|
|
77
|
+
"tsdown": "0.23.1"
|
|
78
78
|
},
|
|
79
79
|
"peerDependencies": {
|
|
80
|
+
"@better-auth/core": "^1.7.23",
|
|
80
81
|
"@better-auth/utils": "^0.4.2 || ^0.5.0",
|
|
81
82
|
"@better-fetch/fetch": "1.3.3",
|
|
82
|
-
"better-
|
|
83
|
-
"
|
|
84
|
-
"better-auth": "^1.7.21"
|
|
83
|
+
"better-auth": "^1.7.23",
|
|
84
|
+
"better-call": "1.4.5"
|
|
85
85
|
},
|
|
86
86
|
"scripts": {
|
|
87
87
|
"build": "tsdown",
|