@better-auth/sso 1.4.0-beta.2 → 1.4.0-beta.20
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/.turbo/turbo-build.log +15 -15
- package/dist/client.d.mts +6 -8
- package/dist/client.mjs +9 -5
- package/dist/index-Ba2niv2R.d.mts +669 -0
- package/dist/index.d.mts +2 -959
- package/dist/index.mjs +2 -1582
- package/dist/src-BUIX9n33.mjs +1215 -0
- package/package.json +28 -21
- package/src/index.ts +34 -2112
- package/src/oidc.test.ts +133 -212
- package/src/routes/sso.ts +2019 -0
- package/src/saml.test.ts +140 -28
- package/src/types.ts +208 -0
- package/tsconfig.json +7 -16
- package/tsdown.config.ts +8 -0
- package/build.config.ts +0 -12
- package/dist/client.cjs +0 -10
- package/dist/client.d.cts +0 -11
- package/dist/client.d.ts +0 -11
- package/dist/index.cjs +0 -1600
- package/dist/index.d.cts +0 -959
- package/dist/index.d.ts +0 -959
package/src/saml.test.ts
CHANGED
|
@@ -1,31 +1,31 @@
|
|
|
1
|
-
import {
|
|
2
|
-
afterAll,
|
|
3
|
-
beforeAll,
|
|
4
|
-
beforeEach,
|
|
5
|
-
describe,
|
|
6
|
-
expect,
|
|
7
|
-
it,
|
|
8
|
-
vi,
|
|
9
|
-
} from "vitest";
|
|
1
|
+
import { betterFetch } from "@better-fetch/fetch";
|
|
10
2
|
import { betterAuth } from "better-auth";
|
|
11
3
|
import { memoryAdapter } from "better-auth/adapters/memory";
|
|
12
4
|
import { createAuthClient } from "better-auth/client";
|
|
13
|
-
import { betterFetch } from "@better-fetch/fetch";
|
|
14
5
|
import { setCookieToHeader } from "better-auth/cookies";
|
|
15
6
|
import { bearer } from "better-auth/plugins";
|
|
16
|
-
import {
|
|
17
|
-
import
|
|
18
|
-
import {
|
|
19
|
-
import * as saml from "samlify";
|
|
7
|
+
import { getTestInstance } from "better-auth/test";
|
|
8
|
+
import bodyParser from "body-parser";
|
|
9
|
+
import { randomUUID } from "crypto";
|
|
20
10
|
import type {
|
|
21
11
|
Application as ExpressApp,
|
|
22
12
|
Request as ExpressRequest,
|
|
23
13
|
Response as ExpressResponse,
|
|
24
14
|
} from "express";
|
|
25
15
|
import express from "express";
|
|
26
|
-
import
|
|
27
|
-
import
|
|
28
|
-
import {
|
|
16
|
+
import { createServer } from "http";
|
|
17
|
+
import * as saml from "samlify";
|
|
18
|
+
import {
|
|
19
|
+
afterAll,
|
|
20
|
+
beforeAll,
|
|
21
|
+
beforeEach,
|
|
22
|
+
describe,
|
|
23
|
+
expect,
|
|
24
|
+
it,
|
|
25
|
+
vi,
|
|
26
|
+
} from "vitest";
|
|
27
|
+
import { sso } from ".";
|
|
28
|
+
import { ssoClient } from "./client";
|
|
29
29
|
|
|
30
30
|
const spMetadata = `
|
|
31
31
|
<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" entityID="http://localhost:3001/api/sso/saml2/sp/metadata">
|
|
@@ -242,7 +242,7 @@ const certificate = `
|
|
|
242
242
|
yyoWAJDUHiAmvFA=
|
|
243
243
|
-----END CERTIFICATE-----
|
|
244
244
|
`;
|
|
245
|
-
const
|
|
245
|
+
const idpEncryptionKey = `
|
|
246
246
|
-----BEGIN RSA PRIVATE KEY-----
|
|
247
247
|
Proc-Type: 4,ENCRYPTED
|
|
248
248
|
DEK-Info: DES-EDE3-CBC,860FDB9F3BE14699
|
|
@@ -274,7 +274,7 @@ const idpEncyptionKey = `
|
|
|
274
274
|
ISbutnQPUN5fsaIsgKDIV3T7n6519t6brobcW5bdigmf5ebFeZJ16/lYy6V77UM5
|
|
275
275
|
-----END RSA PRIVATE KEY-----
|
|
276
276
|
`;
|
|
277
|
-
const
|
|
277
|
+
const spEncryptionKey = `
|
|
278
278
|
-----BEGIN RSA PRIVATE KEY-----
|
|
279
279
|
Proc-Type: 4,ENCRYPTED
|
|
280
280
|
DEK-Info: DES-EDE3-CBC,860FDB9F3BE14699
|
|
@@ -698,7 +698,7 @@ describe("SAML SSO", async () => {
|
|
|
698
698
|
privateKey: idpPrivateKey,
|
|
699
699
|
privateKeyPass: "q9ALNhGT5EhfcRmp8Pg7e9zTQeP2x1bW",
|
|
700
700
|
isAssertionEncrypted: true,
|
|
701
|
-
encPrivateKey:
|
|
701
|
+
encPrivateKey: idpEncryptionKey,
|
|
702
702
|
encPrivateKeyPass: "g7hGcRmp8PxT5QeP2q9Ehf1bWe9zTALN",
|
|
703
703
|
},
|
|
704
704
|
spMetadata: {
|
|
@@ -707,7 +707,7 @@ describe("SAML SSO", async () => {
|
|
|
707
707
|
privateKey: spPrivateKey,
|
|
708
708
|
privateKeyPass: "VHOSp5RUiBcrsjrcAuXFwU1NKCkGA8px",
|
|
709
709
|
isAssertionEncrypted: true,
|
|
710
|
-
encPrivateKey:
|
|
710
|
+
encPrivateKey: spEncryptionKey,
|
|
711
711
|
encPrivateKeyPass: "BXFNKpxrsjrCkGA8cAu5wUVHOSpci1RU",
|
|
712
712
|
},
|
|
713
713
|
identifierFormat:
|
|
@@ -754,7 +754,7 @@ describe("SAML SSO", async () => {
|
|
|
754
754
|
privateKey: idpPrivateKey,
|
|
755
755
|
privateKeyPass: "q9ALNhGT5EhfcRmp8Pg7e9zTQeP2x1bW",
|
|
756
756
|
isAssertionEncrypted: true,
|
|
757
|
-
encPrivateKey:
|
|
757
|
+
encPrivateKey: idpEncryptionKey,
|
|
758
758
|
encPrivateKeyPass: "g7hGcRmp8PxT5QeP2q9Ehf1bWe9zTALN",
|
|
759
759
|
},
|
|
760
760
|
spMetadata: {
|
|
@@ -763,7 +763,7 @@ describe("SAML SSO", async () => {
|
|
|
763
763
|
privateKey: spPrivateKey,
|
|
764
764
|
privateKeyPass: "VHOSp5RUiBcrsjrcAuXFwU1NKCkGA8px",
|
|
765
765
|
isAssertionEncrypted: true,
|
|
766
|
-
encPrivateKey:
|
|
766
|
+
encPrivateKey: spEncryptionKey,
|
|
767
767
|
encPrivateKeyPass: "BXFNKpxrsjrCkGA8cAu5wUVHOSpci1RU",
|
|
768
768
|
},
|
|
769
769
|
identifierFormat:
|
|
@@ -782,6 +782,69 @@ describe("SAML SSO", async () => {
|
|
|
782
782
|
expect(spMetadataRes.status).toBe(200);
|
|
783
783
|
expect(spMetadataResResValue).toBe(spMetadata);
|
|
784
784
|
});
|
|
785
|
+
it("Should fetch sp metadata", async () => {
|
|
786
|
+
const headers = await getAuthHeaders();
|
|
787
|
+
await authClient.signIn.email(testUser, {
|
|
788
|
+
throw: true,
|
|
789
|
+
onSuccess: setCookieToHeader(headers),
|
|
790
|
+
});
|
|
791
|
+
const issuer = "http://localhost:8081";
|
|
792
|
+
const provider = await auth.api.registerSSOProvider({
|
|
793
|
+
body: {
|
|
794
|
+
providerId: "saml-provider-1",
|
|
795
|
+
issuer: issuer,
|
|
796
|
+
domain: issuer,
|
|
797
|
+
samlConfig: {
|
|
798
|
+
entryPoint: mockIdP.metadataUrl,
|
|
799
|
+
cert: certificate,
|
|
800
|
+
callbackUrl: `${issuer}/api/sso/saml2/sp/acs`,
|
|
801
|
+
wantAssertionsSigned: false,
|
|
802
|
+
signatureAlgorithm: "sha256",
|
|
803
|
+
digestAlgorithm: "sha256",
|
|
804
|
+
idpMetadata: {
|
|
805
|
+
metadata: idpMetadata,
|
|
806
|
+
privateKey: idpPrivateKey,
|
|
807
|
+
privateKeyPass: "q9ALNhGT5EhfcRmp8Pg7e9zTQeP2x1bW",
|
|
808
|
+
isAssertionEncrypted: true,
|
|
809
|
+
encPrivateKey: idpEncryptionKey,
|
|
810
|
+
encPrivateKeyPass: "g7hGcRmp8PxT5QeP2q9Ehf1bWe9zTALN",
|
|
811
|
+
},
|
|
812
|
+
spMetadata: {
|
|
813
|
+
binding: "post",
|
|
814
|
+
privateKey: spPrivateKey,
|
|
815
|
+
privateKeyPass: "VHOSp5RUiBcrsjrcAuXFwU1NKCkGA8px",
|
|
816
|
+
isAssertionEncrypted: true,
|
|
817
|
+
encPrivateKey: spEncryptionKey,
|
|
818
|
+
encPrivateKeyPass: "BXFNKpxrsjrCkGA8cAu5wUVHOSpci1RU",
|
|
819
|
+
},
|
|
820
|
+
identifierFormat:
|
|
821
|
+
"urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress",
|
|
822
|
+
},
|
|
823
|
+
},
|
|
824
|
+
headers,
|
|
825
|
+
});
|
|
826
|
+
|
|
827
|
+
const spMetadataRes = await auth.api.spMetadata({
|
|
828
|
+
query: {
|
|
829
|
+
providerId: provider.providerId,
|
|
830
|
+
},
|
|
831
|
+
});
|
|
832
|
+
const spMetadataResResValue = await spMetadataRes.text();
|
|
833
|
+
expect(spMetadataRes.status).toBe(200);
|
|
834
|
+
expect(spMetadataResResValue).toBeDefined();
|
|
835
|
+
expect(spMetadataResResValue).toContain(
|
|
836
|
+
"urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress",
|
|
837
|
+
);
|
|
838
|
+
expect(spMetadataResResValue).toContain(
|
|
839
|
+
"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST",
|
|
840
|
+
);
|
|
841
|
+
expect(spMetadataResResValue).toContain(
|
|
842
|
+
`<EntityDescriptor entityID="${issuer}"`,
|
|
843
|
+
);
|
|
844
|
+
expect(spMetadataResResValue).toContain(
|
|
845
|
+
`Location="${issuer}/api/sso/saml2/sp/acs"`,
|
|
846
|
+
);
|
|
847
|
+
});
|
|
785
848
|
it("should initiate SAML login and handle response", async () => {
|
|
786
849
|
const headers = await getAuthHeaders();
|
|
787
850
|
const res = await authClient.signIn.email(testUser, {
|
|
@@ -805,7 +868,7 @@ describe("SAML SSO", async () => {
|
|
|
805
868
|
privateKey: idpPrivateKey,
|
|
806
869
|
privateKeyPass: "q9ALNhGT5EhfcRmp8Pg7e9zTQeP2x1bW",
|
|
807
870
|
isAssertionEncrypted: true,
|
|
808
|
-
encPrivateKey:
|
|
871
|
+
encPrivateKey: idpEncryptionKey,
|
|
809
872
|
encPrivateKeyPass: "g7hGcRmp8PxT5QeP2q9Ehf1bWe9zTALN",
|
|
810
873
|
},
|
|
811
874
|
spMetadata: {
|
|
@@ -814,7 +877,7 @@ describe("SAML SSO", async () => {
|
|
|
814
877
|
privateKey: spPrivateKey,
|
|
815
878
|
privateKeyPass: "VHOSp5RUiBcrsjrcAuXFwU1NKCkGA8px",
|
|
816
879
|
isAssertionEncrypted: true,
|
|
817
|
-
encPrivateKey:
|
|
880
|
+
encPrivateKey: spEncryptionKey,
|
|
818
881
|
encPrivateKeyPass: "BXFNKpxrsjrCkGA8cAu5wUVHOSpci1RU",
|
|
819
882
|
},
|
|
820
883
|
identifierFormat:
|
|
@@ -863,7 +926,7 @@ describe("SAML SSO", async () => {
|
|
|
863
926
|
});
|
|
864
927
|
|
|
865
928
|
it("should not allow creating a provider if limit is set to 0", async () => {
|
|
866
|
-
const { auth, signInWithTestUser } = await
|
|
929
|
+
const { auth, signInWithTestUser } = await getTestInstance({
|
|
867
930
|
plugins: [sso({ providersLimit: 0 })],
|
|
868
931
|
});
|
|
869
932
|
const { headers } = await signInWithTestUser();
|
|
@@ -894,7 +957,7 @@ describe("SAML SSO", async () => {
|
|
|
894
957
|
});
|
|
895
958
|
|
|
896
959
|
it("should not allow creating a provider if limit is reached", async () => {
|
|
897
|
-
const { auth, signInWithTestUser } = await
|
|
960
|
+
const { auth, signInWithTestUser } = await getTestInstance({
|
|
898
961
|
plugins: [sso({ providersLimit: 1 })],
|
|
899
962
|
});
|
|
900
963
|
const { headers } = await signInWithTestUser();
|
|
@@ -948,7 +1011,7 @@ describe("SAML SSO", async () => {
|
|
|
948
1011
|
});
|
|
949
1012
|
|
|
950
1013
|
it("should not allow creating a provider if limit from function is reached", async () => {
|
|
951
|
-
const { auth, signInWithTestUser } = await
|
|
1014
|
+
const { auth, signInWithTestUser } = await getTestInstance({
|
|
952
1015
|
plugins: [
|
|
953
1016
|
sso({
|
|
954
1017
|
providersLimit: async (user) => {
|
|
@@ -1006,4 +1069,53 @@ describe("SAML SSO", async () => {
|
|
|
1006
1069
|
},
|
|
1007
1070
|
});
|
|
1008
1071
|
});
|
|
1072
|
+
|
|
1073
|
+
it("should not allow creating a provider with duplicate providerId", async () => {
|
|
1074
|
+
const headers = await getAuthHeaders();
|
|
1075
|
+
await authClient.signIn.email(testUser, {
|
|
1076
|
+
throw: true,
|
|
1077
|
+
onSuccess: setCookieToHeader(headers),
|
|
1078
|
+
});
|
|
1079
|
+
|
|
1080
|
+
await auth.api.registerSSOProvider({
|
|
1081
|
+
body: {
|
|
1082
|
+
providerId: "duplicate-provider",
|
|
1083
|
+
issuer: "http://localhost:8081",
|
|
1084
|
+
domain: "http://localhost:8081",
|
|
1085
|
+
samlConfig: {
|
|
1086
|
+
entryPoint: mockIdP.metadataUrl,
|
|
1087
|
+
cert: certificate,
|
|
1088
|
+
callbackUrl: "http://localhost:8081/api/sso/saml2/callback",
|
|
1089
|
+
spMetadata: {
|
|
1090
|
+
metadata: spMetadata,
|
|
1091
|
+
},
|
|
1092
|
+
},
|
|
1093
|
+
},
|
|
1094
|
+
headers,
|
|
1095
|
+
});
|
|
1096
|
+
|
|
1097
|
+
await expect(
|
|
1098
|
+
auth.api.registerSSOProvider({
|
|
1099
|
+
body: {
|
|
1100
|
+
providerId: "duplicate-provider",
|
|
1101
|
+
issuer: "http://localhost:8082",
|
|
1102
|
+
domain: "http://localhost:8082",
|
|
1103
|
+
samlConfig: {
|
|
1104
|
+
entryPoint: mockIdP.metadataUrl,
|
|
1105
|
+
cert: certificate,
|
|
1106
|
+
callbackUrl: "http://localhost:8082/api/sso/saml2/callback",
|
|
1107
|
+
spMetadata: {
|
|
1108
|
+
metadata: spMetadata,
|
|
1109
|
+
},
|
|
1110
|
+
},
|
|
1111
|
+
},
|
|
1112
|
+
headers,
|
|
1113
|
+
}),
|
|
1114
|
+
).rejects.toMatchObject({
|
|
1115
|
+
status: "UNPROCESSABLE_ENTITY",
|
|
1116
|
+
body: {
|
|
1117
|
+
message: "SSO provider with this providerId already exists",
|
|
1118
|
+
},
|
|
1119
|
+
});
|
|
1120
|
+
});
|
|
1009
1121
|
});
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import type { OAuth2Tokens, User } from "better-auth";
|
|
2
|
+
|
|
3
|
+
export interface OIDCMapping {
|
|
4
|
+
id?: string | undefined;
|
|
5
|
+
email?: string | undefined;
|
|
6
|
+
emailVerified?: string | undefined;
|
|
7
|
+
name?: string | undefined;
|
|
8
|
+
image?: string | undefined;
|
|
9
|
+
extraFields?: Record<string, string> | undefined;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface SAMLMapping {
|
|
13
|
+
id?: string | undefined;
|
|
14
|
+
email?: string | undefined;
|
|
15
|
+
emailVerified?: string | undefined;
|
|
16
|
+
name?: string | undefined;
|
|
17
|
+
firstName?: string | undefined;
|
|
18
|
+
lastName?: string | undefined;
|
|
19
|
+
extraFields?: Record<string, string> | undefined;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface OIDCConfig {
|
|
23
|
+
issuer: string;
|
|
24
|
+
pkce: boolean;
|
|
25
|
+
clientId: string;
|
|
26
|
+
clientSecret: string;
|
|
27
|
+
authorizationEndpoint?: string | undefined;
|
|
28
|
+
discoveryEndpoint: string;
|
|
29
|
+
userInfoEndpoint?: string | undefined;
|
|
30
|
+
scopes?: string[] | undefined;
|
|
31
|
+
overrideUserInfo?: boolean | undefined;
|
|
32
|
+
tokenEndpoint?: string | undefined;
|
|
33
|
+
tokenEndpointAuthentication?:
|
|
34
|
+
| ("client_secret_post" | "client_secret_basic")
|
|
35
|
+
| undefined;
|
|
36
|
+
jwksEndpoint?: string | undefined;
|
|
37
|
+
mapping?: OIDCMapping | undefined;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface SAMLConfig {
|
|
41
|
+
issuer: string;
|
|
42
|
+
entryPoint: string;
|
|
43
|
+
cert: string;
|
|
44
|
+
callbackUrl: string;
|
|
45
|
+
audience?: string | undefined;
|
|
46
|
+
idpMetadata?:
|
|
47
|
+
| {
|
|
48
|
+
metadata?: string;
|
|
49
|
+
entityID?: string;
|
|
50
|
+
entityURL?: string;
|
|
51
|
+
redirectURL?: string;
|
|
52
|
+
cert?: string;
|
|
53
|
+
privateKey?: string;
|
|
54
|
+
privateKeyPass?: string;
|
|
55
|
+
isAssertionEncrypted?: boolean;
|
|
56
|
+
encPrivateKey?: string;
|
|
57
|
+
encPrivateKeyPass?: string;
|
|
58
|
+
singleSignOnService?: Array<{
|
|
59
|
+
Binding: string;
|
|
60
|
+
Location: string;
|
|
61
|
+
}>;
|
|
62
|
+
}
|
|
63
|
+
| undefined;
|
|
64
|
+
spMetadata: {
|
|
65
|
+
metadata?: string | undefined;
|
|
66
|
+
entityID?: string | undefined;
|
|
67
|
+
binding?: string | undefined;
|
|
68
|
+
privateKey?: string | undefined;
|
|
69
|
+
privateKeyPass?: string | undefined;
|
|
70
|
+
isAssertionEncrypted?: boolean | undefined;
|
|
71
|
+
encPrivateKey?: string | undefined;
|
|
72
|
+
encPrivateKeyPass?: string | undefined;
|
|
73
|
+
};
|
|
74
|
+
wantAssertionsSigned?: boolean | undefined;
|
|
75
|
+
signatureAlgorithm?: string | undefined;
|
|
76
|
+
digestAlgorithm?: string | undefined;
|
|
77
|
+
identifierFormat?: string | undefined;
|
|
78
|
+
privateKey?: string | undefined;
|
|
79
|
+
decryptionPvk?: string | undefined;
|
|
80
|
+
additionalParams?: Record<string, any> | undefined;
|
|
81
|
+
mapping?: SAMLMapping | undefined;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export type SSOProvider = {
|
|
85
|
+
issuer: string;
|
|
86
|
+
oidcConfig?: OIDCConfig | undefined;
|
|
87
|
+
samlConfig?: SAMLConfig | undefined;
|
|
88
|
+
userId: string;
|
|
89
|
+
providerId: string;
|
|
90
|
+
organizationId?: string | undefined;
|
|
91
|
+
domain: string;
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
export interface SSOOptions {
|
|
95
|
+
/**
|
|
96
|
+
* custom function to provision a user when they sign in with an SSO provider.
|
|
97
|
+
*/
|
|
98
|
+
provisionUser?:
|
|
99
|
+
| ((data: {
|
|
100
|
+
/**
|
|
101
|
+
* The user object from the database
|
|
102
|
+
*/
|
|
103
|
+
user: User & Record<string, any>;
|
|
104
|
+
/**
|
|
105
|
+
* The user info object from the provider
|
|
106
|
+
*/
|
|
107
|
+
userInfo: Record<string, any>;
|
|
108
|
+
/**
|
|
109
|
+
* The OAuth2 tokens from the provider
|
|
110
|
+
*/
|
|
111
|
+
token?: OAuth2Tokens;
|
|
112
|
+
/**
|
|
113
|
+
* The SSO provider
|
|
114
|
+
*/
|
|
115
|
+
provider: SSOProvider;
|
|
116
|
+
}) => Promise<void>)
|
|
117
|
+
| undefined;
|
|
118
|
+
/**
|
|
119
|
+
* Organization provisioning options
|
|
120
|
+
*/
|
|
121
|
+
organizationProvisioning?:
|
|
122
|
+
| {
|
|
123
|
+
disabled?: boolean;
|
|
124
|
+
defaultRole?: "member" | "admin";
|
|
125
|
+
getRole?: (data: {
|
|
126
|
+
/**
|
|
127
|
+
* The user object from the database
|
|
128
|
+
*/
|
|
129
|
+
user: User & Record<string, any>;
|
|
130
|
+
/**
|
|
131
|
+
* The user info object from the provider
|
|
132
|
+
*/
|
|
133
|
+
userInfo: Record<string, any>;
|
|
134
|
+
/**
|
|
135
|
+
* The OAuth2 tokens from the provider
|
|
136
|
+
*/
|
|
137
|
+
token?: OAuth2Tokens;
|
|
138
|
+
/**
|
|
139
|
+
* The SSO provider
|
|
140
|
+
*/
|
|
141
|
+
provider: SSOProvider;
|
|
142
|
+
}) => Promise<"member" | "admin">;
|
|
143
|
+
}
|
|
144
|
+
| undefined;
|
|
145
|
+
/**
|
|
146
|
+
* Default SSO provider configurations for testing.
|
|
147
|
+
* These will take the precedence over the database providers.
|
|
148
|
+
*/
|
|
149
|
+
defaultSSO?:
|
|
150
|
+
| Array<{
|
|
151
|
+
/**
|
|
152
|
+
* The domain to match for this default provider.
|
|
153
|
+
* This is only used to match incoming requests to this default provider.
|
|
154
|
+
*/
|
|
155
|
+
domain: string;
|
|
156
|
+
/**
|
|
157
|
+
* The provider ID to use
|
|
158
|
+
*/
|
|
159
|
+
providerId: string;
|
|
160
|
+
/**
|
|
161
|
+
* SAML configuration
|
|
162
|
+
*/
|
|
163
|
+
samlConfig?: SAMLConfig;
|
|
164
|
+
/**
|
|
165
|
+
* OIDC configuration
|
|
166
|
+
*/
|
|
167
|
+
oidcConfig?: OIDCConfig;
|
|
168
|
+
}>
|
|
169
|
+
| undefined;
|
|
170
|
+
/**
|
|
171
|
+
* Override user info with the provider info.
|
|
172
|
+
* @default false
|
|
173
|
+
*/
|
|
174
|
+
defaultOverrideUserInfo?: boolean | undefined;
|
|
175
|
+
/**
|
|
176
|
+
* Disable implicit sign up for new users. When set to true for the provider,
|
|
177
|
+
* sign-in need to be called with with requestSignUp as true to create new users.
|
|
178
|
+
*/
|
|
179
|
+
disableImplicitSignUp?: boolean | undefined;
|
|
180
|
+
/**
|
|
181
|
+
* Configure the maximum number of SSO providers a user can register.
|
|
182
|
+
* You can also pass a function that returns a number.
|
|
183
|
+
* Set to 0 to disable SSO provider registration.
|
|
184
|
+
*
|
|
185
|
+
* @example
|
|
186
|
+
* ```ts
|
|
187
|
+
* providersLimit: async (user) => {
|
|
188
|
+
* const plan = await getUserPlan(user);
|
|
189
|
+
* return plan.name === "pro" ? 10 : 1;
|
|
190
|
+
* }
|
|
191
|
+
* ```
|
|
192
|
+
* @default 10
|
|
193
|
+
*/
|
|
194
|
+
providersLimit?:
|
|
195
|
+
| (number | ((user: User) => Promise<number> | number))
|
|
196
|
+
| undefined;
|
|
197
|
+
/**
|
|
198
|
+
* Trust the email verified flag from the provider.
|
|
199
|
+
*
|
|
200
|
+
* ⚠️ Use this with caution — it can lead to account takeover if misused. Only enable it if users **cannot freely register new providers**. You can
|
|
201
|
+
* prevent that by using `disabledPaths` or other safeguards to block provider registration from the client.
|
|
202
|
+
*
|
|
203
|
+
* If you want to allow account linking for specific trusted providers, enable the `accountLinking` option in your auth config and specify those
|
|
204
|
+
* providers in the `trustedProviders` list.
|
|
205
|
+
* @default false
|
|
206
|
+
*/
|
|
207
|
+
trustEmailVerified?: boolean | undefined;
|
|
208
|
+
}
|
package/tsconfig.json
CHANGED
|
@@ -1,20 +1,11 @@
|
|
|
1
1
|
{
|
|
2
|
+
"extends": "../../tsconfig.base.json",
|
|
2
3
|
"compilerOptions": {
|
|
3
|
-
"
|
|
4
|
-
"skipLibCheck": true,
|
|
5
|
-
"target": "es2022",
|
|
6
|
-
"allowJs": true,
|
|
7
|
-
"resolveJsonModule": true,
|
|
8
|
-
"module": "ESNext",
|
|
9
|
-
"noEmit": true,
|
|
10
|
-
"moduleResolution": "Bundler",
|
|
11
|
-
"moduleDetection": "force",
|
|
12
|
-
"isolatedModules": true,
|
|
13
|
-
"verbatimModuleSyntax": true,
|
|
14
|
-
"strict": true,
|
|
15
|
-
"noImplicitOverride": true,
|
|
16
|
-
"noFallthroughCasesInSwitch": true
|
|
4
|
+
"lib": ["esnext", "dom", "dom.iterable"]
|
|
17
5
|
},
|
|
18
|
-
"
|
|
19
|
-
|
|
6
|
+
"references": [
|
|
7
|
+
{
|
|
8
|
+
"path": "../better-auth/tsconfig.json"
|
|
9
|
+
}
|
|
10
|
+
]
|
|
20
11
|
}
|
package/tsdown.config.ts
ADDED
package/build.config.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { defineBuildConfig } from "unbuild";
|
|
2
|
-
|
|
3
|
-
export default defineBuildConfig({
|
|
4
|
-
declaration: true,
|
|
5
|
-
rollup: {
|
|
6
|
-
emitCJS: true,
|
|
7
|
-
},
|
|
8
|
-
outDir: "dist",
|
|
9
|
-
clean: false,
|
|
10
|
-
failOnWarn: false,
|
|
11
|
-
externals: ["better-auth", "better-call", "@better-fetch/fetch", "stripe"],
|
|
12
|
-
});
|
package/dist/client.cjs
DELETED
package/dist/client.d.cts
DELETED
package/dist/client.d.ts
DELETED