@better-auth/core 1.4.0-beta.13 → 1.4.0-beta.15
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 +34 -58
- package/dist/api/index.cjs +1 -1
- package/dist/api/index.d.cts +2 -6
- package/dist/api/index.d.ts +2 -6
- package/dist/api/index.js +1 -1
- package/dist/async_hooks/index.d.cts +1 -1
- package/dist/async_hooks/index.d.ts +1 -1
- package/dist/context/index.cjs +1 -1
- package/dist/context/index.d.cts +14 -18
- package/dist/context/index.d.ts +14 -18
- package/dist/context/index.js +1 -1
- package/dist/{context-Bm0rm76r.js → context-BAOGRjRS.js} +30 -30
- package/dist/{context-7VgEbfs3.cjs → context-BRDf96na.cjs} +29 -29
- package/dist/db/adapter/index.d.cts +2 -6
- package/dist/db/adapter/index.d.ts +2 -6
- package/dist/db/index.cjs +17 -17
- package/dist/db/index.d.cts +2 -2
- package/dist/db/index.d.ts +2 -2
- package/dist/db/index.js +17 -17
- package/dist/env/index.d.cts +1 -1
- package/dist/env/index.d.ts +1 -1
- package/dist/error/index.d.cts +1 -1
- package/dist/error/index.d.ts +1 -1
- package/dist/{index-D5uj-vER.d.ts → index-B_YiOlcX.d.cts} +9 -9
- package/dist/index-Bab6W0hG.d.ts +7155 -0
- package/dist/index-CGS5U4X6.d.cts +7155 -0
- package/dist/{index-Dy_s5RNc.d.cts → index-CSISZQGm.d.ts} +9 -9
- package/dist/index.d.cts +3 -65
- package/dist/index.d.ts +3 -65
- package/dist/oauth2/index.cjs +1 -1
- package/dist/oauth2/index.d.cts +2 -2
- package/dist/oauth2/index.d.ts +2 -2
- package/dist/oauth2/index.js +1 -1
- package/dist/{oauth2-C8-hfKTF.cjs → oauth2-C4Pt8KMZ.cjs} +87 -87
- package/dist/{oauth2-CjVUvPq7.js → oauth2-CP3eVHS_.js} +88 -88
- package/dist/social-providers/index.cjs +963 -888
- package/dist/social-providers/index.d.cts +3 -4
- package/dist/social-providers/index.d.ts +3 -4
- package/dist/social-providers/index.js +1023 -948
- package/package.json +4 -3
- package/src/api/index.ts +3 -3
- package/src/context/endpoint-context.ts +1 -1
- package/src/context/index.ts +7 -7
- package/src/context/transaction.ts +2 -2
- package/src/db/adapter/index.ts +146 -128
- package/src/db/index.ts +11 -11
- package/src/db/plugin.ts +3 -3
- package/src/db/type.ts +47 -41
- package/src/env/index.ts +9 -9
- package/src/env/logger.test.ts +2 -2
- package/src/env/logger.ts +11 -9
- package/src/error/index.ts +1 -1
- package/src/oauth2/client-credentials-token.ts +9 -9
- package/src/oauth2/create-authorization-url.ts +12 -12
- package/src/oauth2/index.ts +10 -11
- package/src/oauth2/oauth-provider.ts +91 -74
- package/src/oauth2/refresh-access-token.ts +12 -12
- package/src/oauth2/validate-authorization-code.ts +13 -13
- package/src/social-providers/apple.ts +6 -6
- package/src/social-providers/atlassian.ts +23 -18
- package/src/social-providers/cognito.ts +17 -14
- package/src/social-providers/discord.ts +6 -6
- package/src/social-providers/dropbox.ts +3 -3
- package/src/social-providers/facebook.ts +10 -7
- package/src/social-providers/figma.ts +8 -5
- package/src/social-providers/github.ts +2 -2
- package/src/social-providers/gitlab.ts +7 -7
- package/src/social-providers/google.ts +15 -12
- package/src/social-providers/huggingface.ts +25 -23
- package/src/social-providers/index.ts +29 -26
- package/src/social-providers/kakao.ts +39 -39
- package/src/social-providers/kick.ts +3 -3
- package/src/social-providers/line.ts +10 -10
- package/src/social-providers/linear.ts +4 -4
- package/src/social-providers/linkedin.ts +3 -3
- package/src/social-providers/microsoft-entra-id.ts +15 -13
- package/src/social-providers/naver.ts +3 -3
- package/src/social-providers/notion.ts +9 -7
- package/src/social-providers/paybin.ts +122 -0
- package/src/social-providers/paypal.ts +29 -27
- package/src/social-providers/polar.ts +20 -18
- package/src/social-providers/reddit.ts +4 -4
- package/src/social-providers/roblox.ts +11 -8
- package/src/social-providers/salesforce.ts +22 -17
- package/src/social-providers/slack.ts +3 -3
- package/src/social-providers/spotify.ts +3 -3
- package/src/social-providers/tiktok.ts +30 -28
- package/src/social-providers/twitch.ts +6 -6
- package/src/social-providers/twitter.ts +47 -43
- package/src/social-providers/vk.ts +11 -10
- package/src/social-providers/zoom.ts +15 -13
- package/src/types/context.ts +23 -17
- package/src/types/index.ts +11 -10
- package/src/types/init-options.ts +1037 -932
- package/src/types/plugin-client.ts +44 -13
- package/src/types/plugin.ts +66 -52
- package/dist/helper-BH5srn6K.d.ts +0 -6
- package/dist/helper-ChPUVnMr.d.cts +0 -6
- package/dist/index-BCxkjvux.d.cts +0 -344
- package/dist/index-CZCOI9An.d.ts +0 -344
- package/dist/index-Cg7SVnu9.d.cts +0 -4645
- package/dist/index-DQNPxXof.d.ts +0 -262
- package/dist/index-DXj1sY8B.d.cts +0 -1772
- package/dist/index-DgTKobWC.d.ts +0 -1772
- package/dist/index-RfHoxHB4.d.ts +0 -4531
- package/dist/index-daoIWR6L.d.cts +0 -262
- /package/dist/{index-CR-gJyzm.d.ts → index-BzepAavo.d.cts} +0 -0
- /package/dist/{index-CilaMiAm.d.cts → index-DT7CRnvv.d.ts} +0 -0
|
@@ -2,7 +2,7 @@ const require_chunk = require('../chunk-CUT6urMc.cjs');
|
|
|
2
2
|
const require_env = require('../env-CuEMo0ZI.cjs');
|
|
3
3
|
require('../utils-Bs-jKit4.cjs');
|
|
4
4
|
const require_error = require('../error-k9KM7GAb.cjs');
|
|
5
|
-
const require_oauth2 = require('../oauth2-
|
|
5
|
+
const require_oauth2 = require('../oauth2-C4Pt8KMZ.cjs');
|
|
6
6
|
let better_call = require("better-call");
|
|
7
7
|
better_call = require_chunk.__toESM(better_call);
|
|
8
8
|
let zod = require("zod");
|
|
@@ -13,8 +13,6 @@ let __better_fetch_fetch = require("@better-fetch/fetch");
|
|
|
13
13
|
__better_fetch_fetch = require_chunk.__toESM(__better_fetch_fetch);
|
|
14
14
|
let jose = require("jose");
|
|
15
15
|
jose = require_chunk.__toESM(jose);
|
|
16
|
-
let __better_auth_core_oauth2 = require("@better-auth/core/oauth2");
|
|
17
|
-
__better_auth_core_oauth2 = require_chunk.__toESM(__better_auth_core_oauth2);
|
|
18
16
|
|
|
19
17
|
//#region src/social-providers/apple.ts
|
|
20
18
|
const apple = (options) => {
|
|
@@ -24,8 +22,8 @@ const apple = (options) => {
|
|
|
24
22
|
name: "Apple",
|
|
25
23
|
async createAuthorizationURL({ state, scopes, redirectURI }) {
|
|
26
24
|
const _scope = options.disableDefaultScope ? [] : ["email", "name"];
|
|
27
|
-
options.scope
|
|
28
|
-
scopes
|
|
25
|
+
if (options.scope) _scope.push(...options.scope);
|
|
26
|
+
if (scopes) _scope.push(...scopes);
|
|
29
27
|
return await require_oauth2.createAuthorizationURL({
|
|
30
28
|
id: "apple",
|
|
31
29
|
options,
|
|
@@ -121,8 +119,8 @@ const atlassian = (options) => {
|
|
|
121
119
|
}
|
|
122
120
|
if (!codeVerifier) throw new require_error.BetterAuthError("codeVerifier is required for Atlassian");
|
|
123
121
|
const _scopes = options.disableDefaultScope ? [] : ["read:jira-user", "offline_access"];
|
|
124
|
-
options.scope
|
|
125
|
-
scopes
|
|
122
|
+
if (options.scope) _scopes.push(...options.scope);
|
|
123
|
+
if (scopes) _scopes.push(...scopes);
|
|
126
124
|
return require_oauth2.createAuthorizationURL({
|
|
127
125
|
id: "atlassian",
|
|
128
126
|
options,
|
|
@@ -209,8 +207,8 @@ const cognito = (options) => {
|
|
|
209
207
|
"profile",
|
|
210
208
|
"email"
|
|
211
209
|
];
|
|
212
|
-
options.scope
|
|
213
|
-
scopes
|
|
210
|
+
if (options.scope) _scopes.push(...options.scope);
|
|
211
|
+
if (scopes) _scopes.push(...scopes);
|
|
214
212
|
return await require_oauth2.createAuthorizationURL({
|
|
215
213
|
id: "cognito",
|
|
216
214
|
options: { ...options },
|
|
@@ -334,8 +332,8 @@ const discord = (options) => {
|
|
|
334
332
|
name: "Discord",
|
|
335
333
|
createAuthorizationURL({ state, scopes, redirectURI }) {
|
|
336
334
|
const _scopes = options.disableDefaultScope ? [] : ["identify", "email"];
|
|
337
|
-
scopes
|
|
338
|
-
options.scope
|
|
335
|
+
if (scopes) _scopes.push(...scopes);
|
|
336
|
+
if (options.scope) _scopes.push(...options.scope);
|
|
339
337
|
const permissionsParam = _scopes.includes("bot") && options.permissions !== void 0 ? `&permissions=${options.permissions}` : "";
|
|
340
338
|
return new URL(`https://discord.com/api/oauth2/authorize?scope=${_scopes.join("+")}&response_type=code&client_id=${options.clientId}&redirect_uri=${encodeURIComponent(options.redirectURI || redirectURI)}&state=${state}&prompt=${options.prompt || "none"}${permissionsParam}`);
|
|
341
339
|
},
|
|
@@ -384,6 +382,74 @@ const discord = (options) => {
|
|
|
384
382
|
};
|
|
385
383
|
};
|
|
386
384
|
|
|
385
|
+
//#endregion
|
|
386
|
+
//#region src/social-providers/dropbox.ts
|
|
387
|
+
const dropbox = (options) => {
|
|
388
|
+
const tokenEndpoint = "https://api.dropboxapi.com/oauth2/token";
|
|
389
|
+
return {
|
|
390
|
+
id: "dropbox",
|
|
391
|
+
name: "Dropbox",
|
|
392
|
+
createAuthorizationURL: async ({ state, scopes, codeVerifier, redirectURI }) => {
|
|
393
|
+
const _scopes = options.disableDefaultScope ? [] : ["account_info.read"];
|
|
394
|
+
if (options.scope) _scopes.push(...options.scope);
|
|
395
|
+
if (scopes) _scopes.push(...scopes);
|
|
396
|
+
const additionalParams = {};
|
|
397
|
+
if (options.accessType) additionalParams.token_access_type = options.accessType;
|
|
398
|
+
return await require_oauth2.createAuthorizationURL({
|
|
399
|
+
id: "dropbox",
|
|
400
|
+
options,
|
|
401
|
+
authorizationEndpoint: "https://www.dropbox.com/oauth2/authorize",
|
|
402
|
+
scopes: _scopes,
|
|
403
|
+
state,
|
|
404
|
+
redirectURI,
|
|
405
|
+
codeVerifier,
|
|
406
|
+
additionalParams
|
|
407
|
+
});
|
|
408
|
+
},
|
|
409
|
+
validateAuthorizationCode: async ({ code, codeVerifier, redirectURI }) => {
|
|
410
|
+
return await require_oauth2.validateAuthorizationCode({
|
|
411
|
+
code,
|
|
412
|
+
codeVerifier,
|
|
413
|
+
redirectURI,
|
|
414
|
+
options,
|
|
415
|
+
tokenEndpoint
|
|
416
|
+
});
|
|
417
|
+
},
|
|
418
|
+
refreshAccessToken: options.refreshAccessToken ? options.refreshAccessToken : async (refreshToken) => {
|
|
419
|
+
return require_oauth2.refreshAccessToken({
|
|
420
|
+
refreshToken,
|
|
421
|
+
options: {
|
|
422
|
+
clientId: options.clientId,
|
|
423
|
+
clientKey: options.clientKey,
|
|
424
|
+
clientSecret: options.clientSecret
|
|
425
|
+
},
|
|
426
|
+
tokenEndpoint: "https://api.dropbox.com/oauth2/token"
|
|
427
|
+
});
|
|
428
|
+
},
|
|
429
|
+
async getUserInfo(token) {
|
|
430
|
+
if (options.getUserInfo) return options.getUserInfo(token);
|
|
431
|
+
const { data: profile, error } = await (0, __better_fetch_fetch.betterFetch)("https://api.dropboxapi.com/2/users/get_current_account", {
|
|
432
|
+
method: "POST",
|
|
433
|
+
headers: { Authorization: `Bearer ${token.accessToken}` }
|
|
434
|
+
});
|
|
435
|
+
if (error) return null;
|
|
436
|
+
const userMap = await options.mapProfileToUser?.(profile);
|
|
437
|
+
return {
|
|
438
|
+
user: {
|
|
439
|
+
id: profile.account_id,
|
|
440
|
+
name: profile.name?.display_name,
|
|
441
|
+
email: profile.email,
|
|
442
|
+
emailVerified: profile.email_verified || false,
|
|
443
|
+
image: profile.profile_photo_url,
|
|
444
|
+
...userMap
|
|
445
|
+
},
|
|
446
|
+
data: profile
|
|
447
|
+
};
|
|
448
|
+
},
|
|
449
|
+
options
|
|
450
|
+
};
|
|
451
|
+
};
|
|
452
|
+
|
|
387
453
|
//#endregion
|
|
388
454
|
//#region src/social-providers/facebook.ts
|
|
389
455
|
const facebook = (options) => {
|
|
@@ -392,8 +458,8 @@ const facebook = (options) => {
|
|
|
392
458
|
name: "Facebook",
|
|
393
459
|
async createAuthorizationURL({ state, scopes, redirectURI, loginHint }) {
|
|
394
460
|
const _scopes = options.disableDefaultScope ? [] : ["email", "public_profile"];
|
|
395
|
-
options.scope
|
|
396
|
-
scopes
|
|
461
|
+
if (options.scope) _scopes.push(...options.scope);
|
|
462
|
+
if (scopes) _scopes.push(...scopes);
|
|
397
463
|
return await require_oauth2.createAuthorizationURL({
|
|
398
464
|
id: "facebook",
|
|
399
465
|
options,
|
|
@@ -509,8 +575,8 @@ const figma = (options) => {
|
|
|
509
575
|
}
|
|
510
576
|
if (!codeVerifier) throw new require_error.BetterAuthError("codeVerifier is required for Figma");
|
|
511
577
|
const _scopes = options.disableDefaultScope ? [] : ["file_read"];
|
|
512
|
-
options.scope
|
|
513
|
-
scopes
|
|
578
|
+
if (options.scope) _scopes.push(...options.scope);
|
|
579
|
+
if (scopes) _scopes.push(...scopes);
|
|
514
580
|
return await require_oauth2.createAuthorizationURL({
|
|
515
581
|
id: "figma",
|
|
516
582
|
options,
|
|
@@ -579,8 +645,8 @@ const github = (options) => {
|
|
|
579
645
|
name: "GitHub",
|
|
580
646
|
createAuthorizationURL({ state, scopes, loginHint, redirectURI }) {
|
|
581
647
|
const _scopes = options.disableDefaultScope ? [] : ["read:user", "user:email"];
|
|
582
|
-
options.scope
|
|
583
|
-
scopes
|
|
648
|
+
if (options.scope) _scopes.push(...options.scope);
|
|
649
|
+
if (scopes) _scopes.push(...scopes);
|
|
584
650
|
return require_oauth2.createAuthorizationURL({
|
|
585
651
|
id: "github",
|
|
586
652
|
options,
|
|
@@ -641,6 +707,81 @@ const github = (options) => {
|
|
|
641
707
|
};
|
|
642
708
|
};
|
|
643
709
|
|
|
710
|
+
//#endregion
|
|
711
|
+
//#region src/social-providers/gitlab.ts
|
|
712
|
+
const cleanDoubleSlashes = (input = "") => {
|
|
713
|
+
return input.split("://").map((str) => str.replace(/\/{2,}/g, "/")).join("://");
|
|
714
|
+
};
|
|
715
|
+
const issuerToEndpoints = (issuer) => {
|
|
716
|
+
let baseUrl = issuer || "https://gitlab.com";
|
|
717
|
+
return {
|
|
718
|
+
authorizationEndpoint: cleanDoubleSlashes(`${baseUrl}/oauth/authorize`),
|
|
719
|
+
tokenEndpoint: cleanDoubleSlashes(`${baseUrl}/oauth/token`),
|
|
720
|
+
userinfoEndpoint: cleanDoubleSlashes(`${baseUrl}/api/v4/user`)
|
|
721
|
+
};
|
|
722
|
+
};
|
|
723
|
+
const gitlab = (options) => {
|
|
724
|
+
const { authorizationEndpoint, tokenEndpoint, userinfoEndpoint } = issuerToEndpoints(options.issuer);
|
|
725
|
+
const issuerId = "gitlab";
|
|
726
|
+
return {
|
|
727
|
+
id: issuerId,
|
|
728
|
+
name: "Gitlab",
|
|
729
|
+
createAuthorizationURL: async ({ state, scopes, codeVerifier, loginHint, redirectURI }) => {
|
|
730
|
+
const _scopes = options.disableDefaultScope ? [] : ["read_user"];
|
|
731
|
+
if (options.scope) _scopes.push(...options.scope);
|
|
732
|
+
if (scopes) _scopes.push(...scopes);
|
|
733
|
+
return await require_oauth2.createAuthorizationURL({
|
|
734
|
+
id: issuerId,
|
|
735
|
+
options,
|
|
736
|
+
authorizationEndpoint,
|
|
737
|
+
scopes: _scopes,
|
|
738
|
+
state,
|
|
739
|
+
redirectURI,
|
|
740
|
+
codeVerifier,
|
|
741
|
+
loginHint
|
|
742
|
+
});
|
|
743
|
+
},
|
|
744
|
+
validateAuthorizationCode: async ({ code, redirectURI, codeVerifier }) => {
|
|
745
|
+
return require_oauth2.validateAuthorizationCode({
|
|
746
|
+
code,
|
|
747
|
+
redirectURI,
|
|
748
|
+
options,
|
|
749
|
+
codeVerifier,
|
|
750
|
+
tokenEndpoint
|
|
751
|
+
});
|
|
752
|
+
},
|
|
753
|
+
refreshAccessToken: options.refreshAccessToken ? options.refreshAccessToken : async (refreshToken) => {
|
|
754
|
+
return require_oauth2.refreshAccessToken({
|
|
755
|
+
refreshToken,
|
|
756
|
+
options: {
|
|
757
|
+
clientId: options.clientId,
|
|
758
|
+
clientKey: options.clientKey,
|
|
759
|
+
clientSecret: options.clientSecret
|
|
760
|
+
},
|
|
761
|
+
tokenEndpoint
|
|
762
|
+
});
|
|
763
|
+
},
|
|
764
|
+
async getUserInfo(token) {
|
|
765
|
+
if (options.getUserInfo) return options.getUserInfo(token);
|
|
766
|
+
const { data: profile, error } = await (0, __better_fetch_fetch.betterFetch)(userinfoEndpoint, { headers: { authorization: `Bearer ${token.accessToken}` } });
|
|
767
|
+
if (error || profile.state !== "active" || profile.locked) return null;
|
|
768
|
+
const userMap = await options.mapProfileToUser?.(profile);
|
|
769
|
+
return {
|
|
770
|
+
user: {
|
|
771
|
+
id: profile.id,
|
|
772
|
+
name: profile.name ?? profile.username,
|
|
773
|
+
email: profile.email,
|
|
774
|
+
image: profile.avatar_url,
|
|
775
|
+
emailVerified: true,
|
|
776
|
+
...userMap
|
|
777
|
+
},
|
|
778
|
+
data: profile
|
|
779
|
+
};
|
|
780
|
+
},
|
|
781
|
+
options
|
|
782
|
+
};
|
|
783
|
+
};
|
|
784
|
+
|
|
644
785
|
//#endregion
|
|
645
786
|
//#region src/social-providers/google.ts
|
|
646
787
|
const google = (options) => {
|
|
@@ -658,8 +799,8 @@ const google = (options) => {
|
|
|
658
799
|
"profile",
|
|
659
800
|
"openid"
|
|
660
801
|
];
|
|
661
|
-
options.scope
|
|
662
|
-
scopes
|
|
802
|
+
if (options.scope) _scopes.push(...options.scope);
|
|
803
|
+
if (scopes) _scopes.push(...scopes);
|
|
663
804
|
return await require_oauth2.createAuthorizationURL({
|
|
664
805
|
id: "google",
|
|
665
806
|
options,
|
|
@@ -724,60 +865,6 @@ const google = (options) => {
|
|
|
724
865
|
};
|
|
725
866
|
};
|
|
726
867
|
|
|
727
|
-
//#endregion
|
|
728
|
-
//#region src/social-providers/kick.ts
|
|
729
|
-
const kick = (options) => {
|
|
730
|
-
return {
|
|
731
|
-
id: "kick",
|
|
732
|
-
name: "Kick",
|
|
733
|
-
createAuthorizationURL({ state, scopes, redirectURI, codeVerifier }) {
|
|
734
|
-
const _scopes = options.disableDefaultScope ? [] : ["user:read"];
|
|
735
|
-
options.scope && _scopes.push(...options.scope);
|
|
736
|
-
scopes && _scopes.push(...scopes);
|
|
737
|
-
return require_oauth2.createAuthorizationURL({
|
|
738
|
-
id: "kick",
|
|
739
|
-
redirectURI,
|
|
740
|
-
options,
|
|
741
|
-
authorizationEndpoint: "https://id.kick.com/oauth/authorize",
|
|
742
|
-
scopes: _scopes,
|
|
743
|
-
codeVerifier,
|
|
744
|
-
state
|
|
745
|
-
});
|
|
746
|
-
},
|
|
747
|
-
async validateAuthorizationCode({ code, redirectURI, codeVerifier }) {
|
|
748
|
-
return require_oauth2.validateAuthorizationCode({
|
|
749
|
-
code,
|
|
750
|
-
redirectURI,
|
|
751
|
-
options,
|
|
752
|
-
tokenEndpoint: "https://id.kick.com/oauth/token",
|
|
753
|
-
codeVerifier
|
|
754
|
-
});
|
|
755
|
-
},
|
|
756
|
-
async getUserInfo(token) {
|
|
757
|
-
if (options.getUserInfo) return options.getUserInfo(token);
|
|
758
|
-
const { data, error } = await (0, __better_fetch_fetch.betterFetch)("https://api.kick.com/public/v1/users", {
|
|
759
|
-
method: "GET",
|
|
760
|
-
headers: { Authorization: `Bearer ${token.accessToken}` }
|
|
761
|
-
});
|
|
762
|
-
if (error) return null;
|
|
763
|
-
const profile = data.data[0];
|
|
764
|
-
const userMap = await options.mapProfileToUser?.(profile);
|
|
765
|
-
return {
|
|
766
|
-
user: {
|
|
767
|
-
id: profile.user_id,
|
|
768
|
-
name: profile.name,
|
|
769
|
-
email: profile.email,
|
|
770
|
-
image: profile.profile_picture,
|
|
771
|
-
emailVerified: true,
|
|
772
|
-
...userMap
|
|
773
|
-
},
|
|
774
|
-
data: profile
|
|
775
|
-
};
|
|
776
|
-
},
|
|
777
|
-
options
|
|
778
|
-
};
|
|
779
|
-
};
|
|
780
|
-
|
|
781
868
|
//#endregion
|
|
782
869
|
//#region src/social-providers/huggingface.ts
|
|
783
870
|
const huggingface = (options) => {
|
|
@@ -790,8 +877,8 @@ const huggingface = (options) => {
|
|
|
790
877
|
"profile",
|
|
791
878
|
"email"
|
|
792
879
|
];
|
|
793
|
-
options.scope
|
|
794
|
-
scopes
|
|
880
|
+
if (options.scope) _scopes.push(...options.scope);
|
|
881
|
+
if (scopes) _scopes.push(...scopes);
|
|
795
882
|
return require_oauth2.createAuthorizationURL({
|
|
796
883
|
id: "huggingface",
|
|
797
884
|
options,
|
|
@@ -847,152 +934,115 @@ const huggingface = (options) => {
|
|
|
847
934
|
};
|
|
848
935
|
|
|
849
936
|
//#endregion
|
|
850
|
-
//#region src/social-providers/
|
|
851
|
-
const
|
|
852
|
-
const tenant = options.tenantId || "common";
|
|
853
|
-
const authority = options.authority || "https://login.microsoftonline.com";
|
|
854
|
-
const authorizationEndpoint = `${authority}/${tenant}/oauth2/v2.0/authorize`;
|
|
855
|
-
const tokenEndpoint = `${authority}/${tenant}/oauth2/v2.0/token`;
|
|
937
|
+
//#region src/social-providers/kakao.ts
|
|
938
|
+
const kakao = (options) => {
|
|
856
939
|
return {
|
|
857
|
-
id: "
|
|
858
|
-
name: "
|
|
859
|
-
createAuthorizationURL(
|
|
860
|
-
const
|
|
861
|
-
"
|
|
862
|
-
"
|
|
863
|
-
"
|
|
864
|
-
"User.Read",
|
|
865
|
-
"offline_access"
|
|
940
|
+
id: "kakao",
|
|
941
|
+
name: "Kakao",
|
|
942
|
+
createAuthorizationURL({ state, scopes, redirectURI }) {
|
|
943
|
+
const _scopes = options.disableDefaultScope ? [] : [
|
|
944
|
+
"account_email",
|
|
945
|
+
"profile_image",
|
|
946
|
+
"profile_nickname"
|
|
866
947
|
];
|
|
867
|
-
options.scope
|
|
868
|
-
|
|
948
|
+
if (options.scope) _scopes.push(...options.scope);
|
|
949
|
+
if (scopes) _scopes.push(...scopes);
|
|
869
950
|
return require_oauth2.createAuthorizationURL({
|
|
870
|
-
id: "
|
|
951
|
+
id: "kakao",
|
|
871
952
|
options,
|
|
872
|
-
authorizationEndpoint,
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
redirectURI: data.redirectURI,
|
|
877
|
-
prompt: options.prompt,
|
|
878
|
-
loginHint: data.loginHint
|
|
953
|
+
authorizationEndpoint: "https://kauth.kakao.com/oauth/authorize",
|
|
954
|
+
scopes: _scopes,
|
|
955
|
+
state,
|
|
956
|
+
redirectURI
|
|
879
957
|
});
|
|
880
958
|
},
|
|
881
|
-
validateAuthorizationCode({ code,
|
|
959
|
+
validateAuthorizationCode: async ({ code, redirectURI }) => {
|
|
882
960
|
return require_oauth2.validateAuthorizationCode({
|
|
883
961
|
code,
|
|
884
|
-
codeVerifier,
|
|
885
962
|
redirectURI,
|
|
886
963
|
options,
|
|
887
|
-
tokenEndpoint
|
|
964
|
+
tokenEndpoint: "https://kauth.kakao.com/oauth/token"
|
|
965
|
+
});
|
|
966
|
+
},
|
|
967
|
+
refreshAccessToken: options.refreshAccessToken ? options.refreshAccessToken : async (refreshToken) => {
|
|
968
|
+
return require_oauth2.refreshAccessToken({
|
|
969
|
+
refreshToken,
|
|
970
|
+
options: {
|
|
971
|
+
clientId: options.clientId,
|
|
972
|
+
clientKey: options.clientKey,
|
|
973
|
+
clientSecret: options.clientSecret
|
|
974
|
+
},
|
|
975
|
+
tokenEndpoint: "https://kauth.kakao.com/oauth/token"
|
|
888
976
|
});
|
|
889
977
|
},
|
|
890
978
|
async getUserInfo(token) {
|
|
891
979
|
if (options.getUserInfo) return options.getUserInfo(token);
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
const
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
async onResponse(context) {
|
|
898
|
-
if (options.disableProfilePhoto || !context.response.ok) return;
|
|
899
|
-
try {
|
|
900
|
-
const pictureBuffer = await context.response.clone().arrayBuffer();
|
|
901
|
-
user.picture = `data:image/jpeg;base64, ${__better_auth_utils_base64.base64.encode(pictureBuffer)}`;
|
|
902
|
-
} catch (e) {
|
|
903
|
-
require_env.logger.error(e && typeof e === "object" && "name" in e ? e.name : "", e);
|
|
904
|
-
}
|
|
905
|
-
}
|
|
906
|
-
});
|
|
907
|
-
const userMap = await options.mapProfileToUser?.(user);
|
|
980
|
+
const { data: profile, error } = await (0, __better_fetch_fetch.betterFetch)("https://kapi.kakao.com/v2/user/me", { headers: { Authorization: `Bearer ${token.accessToken}` } });
|
|
981
|
+
if (error || !profile) return null;
|
|
982
|
+
const userMap = await options.mapProfileToUser?.(profile);
|
|
983
|
+
const account = profile.kakao_account || {};
|
|
984
|
+
const kakaoProfile = account.profile || {};
|
|
908
985
|
return {
|
|
909
986
|
user: {
|
|
910
|
-
id:
|
|
911
|
-
name:
|
|
912
|
-
email:
|
|
913
|
-
image:
|
|
914
|
-
emailVerified:
|
|
987
|
+
id: String(profile.id),
|
|
988
|
+
name: kakaoProfile.nickname || account.name || void 0,
|
|
989
|
+
email: account.email,
|
|
990
|
+
image: kakaoProfile.profile_image_url || kakaoProfile.thumbnail_image_url,
|
|
991
|
+
emailVerified: !!account.is_email_valid && !!account.is_email_verified,
|
|
915
992
|
...userMap
|
|
916
993
|
},
|
|
917
|
-
data:
|
|
994
|
+
data: profile
|
|
918
995
|
};
|
|
919
996
|
},
|
|
920
|
-
refreshAccessToken: options.refreshAccessToken ? options.refreshAccessToken : async (refreshToken) => {
|
|
921
|
-
const scopes = options.disableDefaultScope ? [] : [
|
|
922
|
-
"openid",
|
|
923
|
-
"profile",
|
|
924
|
-
"email",
|
|
925
|
-
"User.Read",
|
|
926
|
-
"offline_access"
|
|
927
|
-
];
|
|
928
|
-
options.scope && scopes.push(...options.scope);
|
|
929
|
-
return require_oauth2.refreshAccessToken({
|
|
930
|
-
refreshToken,
|
|
931
|
-
options: {
|
|
932
|
-
clientId: options.clientId,
|
|
933
|
-
clientSecret: options.clientSecret
|
|
934
|
-
},
|
|
935
|
-
extraParams: { scope: scopes.join(" ") },
|
|
936
|
-
tokenEndpoint
|
|
937
|
-
});
|
|
938
|
-
},
|
|
939
997
|
options
|
|
940
998
|
};
|
|
941
999
|
};
|
|
942
1000
|
|
|
943
1001
|
//#endregion
|
|
944
|
-
//#region src/social-providers/
|
|
945
|
-
const
|
|
1002
|
+
//#region src/social-providers/kick.ts
|
|
1003
|
+
const kick = (options) => {
|
|
946
1004
|
return {
|
|
947
|
-
id: "
|
|
948
|
-
name: "
|
|
949
|
-
createAuthorizationURL({ state, scopes, redirectURI }) {
|
|
950
|
-
const _scopes = options.disableDefaultScope ? [] : [
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
url.searchParams.set("state", state);
|
|
963
|
-
return url;
|
|
1005
|
+
id: "kick",
|
|
1006
|
+
name: "Kick",
|
|
1007
|
+
createAuthorizationURL({ state, scopes, redirectURI, codeVerifier }) {
|
|
1008
|
+
const _scopes = options.disableDefaultScope ? [] : ["user:read"];
|
|
1009
|
+
if (options.scope) _scopes.push(...options.scope);
|
|
1010
|
+
if (scopes) _scopes.push(...scopes);
|
|
1011
|
+
return require_oauth2.createAuthorizationURL({
|
|
1012
|
+
id: "kick",
|
|
1013
|
+
redirectURI,
|
|
1014
|
+
options,
|
|
1015
|
+
authorizationEndpoint: "https://id.kick.com/oauth/authorize",
|
|
1016
|
+
scopes: _scopes,
|
|
1017
|
+
codeVerifier,
|
|
1018
|
+
state
|
|
1019
|
+
});
|
|
964
1020
|
},
|
|
965
|
-
|
|
1021
|
+
async validateAuthorizationCode({ code, redirectURI, codeVerifier }) {
|
|
966
1022
|
return require_oauth2.validateAuthorizationCode({
|
|
967
1023
|
code,
|
|
968
1024
|
redirectURI,
|
|
969
1025
|
options,
|
|
970
|
-
tokenEndpoint: "https://
|
|
971
|
-
|
|
972
|
-
},
|
|
973
|
-
refreshAccessToken: options.refreshAccessToken ? options.refreshAccessToken : async (refreshToken) => {
|
|
974
|
-
return require_oauth2.refreshAccessToken({
|
|
975
|
-
refreshToken,
|
|
976
|
-
options: {
|
|
977
|
-
clientId: options.clientId,
|
|
978
|
-
clientKey: options.clientKey,
|
|
979
|
-
clientSecret: options.clientSecret
|
|
980
|
-
},
|
|
981
|
-
tokenEndpoint: "https://slack.com/api/openid.connect.token"
|
|
1026
|
+
tokenEndpoint: "https://id.kick.com/oauth/token",
|
|
1027
|
+
codeVerifier
|
|
982
1028
|
});
|
|
983
1029
|
},
|
|
984
1030
|
async getUserInfo(token) {
|
|
985
1031
|
if (options.getUserInfo) return options.getUserInfo(token);
|
|
986
|
-
const { data
|
|
1032
|
+
const { data, error } = await (0, __better_fetch_fetch.betterFetch)("https://api.kick.com/public/v1/users", {
|
|
1033
|
+
method: "GET",
|
|
1034
|
+
headers: { Authorization: `Bearer ${token.accessToken}` }
|
|
1035
|
+
});
|
|
987
1036
|
if (error) return null;
|
|
1037
|
+
const profile = data.data[0];
|
|
988
1038
|
const userMap = await options.mapProfileToUser?.(profile);
|
|
989
1039
|
return {
|
|
990
1040
|
user: {
|
|
991
|
-
id: profile
|
|
992
|
-
name: profile.name
|
|
1041
|
+
id: profile.user_id,
|
|
1042
|
+
name: profile.name,
|
|
993
1043
|
email: profile.email,
|
|
994
|
-
|
|
995
|
-
|
|
1044
|
+
image: profile.profile_picture,
|
|
1045
|
+
emailVerified: true,
|
|
996
1046
|
...userMap
|
|
997
1047
|
},
|
|
998
1048
|
data: profile
|
|
@@ -1003,34 +1053,50 @@ const slack = (options) => {
|
|
|
1003
1053
|
};
|
|
1004
1054
|
|
|
1005
1055
|
//#endregion
|
|
1006
|
-
//#region src/social-providers/
|
|
1007
|
-
|
|
1008
|
-
|
|
1056
|
+
//#region src/social-providers/line.ts
|
|
1057
|
+
/**
|
|
1058
|
+
* LINE Login v2.1
|
|
1059
|
+
* - Authorization endpoint: https://access.line.me/oauth2/v2.1/authorize
|
|
1060
|
+
* - Token endpoint: https://api.line.me/oauth2/v2.1/token
|
|
1061
|
+
* - UserInfo endpoint: https://api.line.me/oauth2/v2.1/userinfo
|
|
1062
|
+
* - Verify ID token: https://api.line.me/oauth2/v2.1/verify
|
|
1063
|
+
*
|
|
1064
|
+
* Docs: https://developers.line.biz/en/reference/line-login/#issue-access-token
|
|
1065
|
+
*/
|
|
1066
|
+
const line = (options) => {
|
|
1067
|
+
const authorizationEndpoint = "https://access.line.me/oauth2/v2.1/authorize";
|
|
1068
|
+
const tokenEndpoint = "https://api.line.me/oauth2/v2.1/token";
|
|
1069
|
+
const userInfoEndpoint = "https://api.line.me/oauth2/v2.1/userinfo";
|
|
1070
|
+
const verifyIdTokenEndpoint = "https://api.line.me/oauth2/v2.1/verify";
|
|
1009
1071
|
return {
|
|
1010
|
-
id: "
|
|
1011
|
-
name: "
|
|
1012
|
-
createAuthorizationURL({ state, scopes,
|
|
1013
|
-
const _scopes = options.disableDefaultScope ? [] : [
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1072
|
+
id: "line",
|
|
1073
|
+
name: "LINE",
|
|
1074
|
+
async createAuthorizationURL({ state, scopes, codeVerifier, redirectURI, loginHint }) {
|
|
1075
|
+
const _scopes = options.disableDefaultScope ? [] : [
|
|
1076
|
+
"openid",
|
|
1077
|
+
"profile",
|
|
1078
|
+
"email"
|
|
1079
|
+
];
|
|
1080
|
+
if (options.scope) _scopes.push(...options.scope);
|
|
1081
|
+
if (scopes) _scopes.push(...scopes);
|
|
1082
|
+
return await require_oauth2.createAuthorizationURL({
|
|
1083
|
+
id: "line",
|
|
1018
1084
|
options,
|
|
1019
|
-
authorizationEndpoint
|
|
1085
|
+
authorizationEndpoint,
|
|
1020
1086
|
scopes: _scopes,
|
|
1021
1087
|
state,
|
|
1088
|
+
codeVerifier,
|
|
1022
1089
|
redirectURI,
|
|
1023
|
-
loginHint
|
|
1024
|
-
additionalParams: { owner: "user" }
|
|
1090
|
+
loginHint
|
|
1025
1091
|
});
|
|
1026
1092
|
},
|
|
1027
|
-
validateAuthorizationCode: async ({ code, redirectURI }) => {
|
|
1093
|
+
validateAuthorizationCode: async ({ code, codeVerifier, redirectURI }) => {
|
|
1028
1094
|
return require_oauth2.validateAuthorizationCode({
|
|
1029
1095
|
code,
|
|
1096
|
+
codeVerifier,
|
|
1030
1097
|
redirectURI,
|
|
1031
1098
|
options,
|
|
1032
|
-
tokenEndpoint
|
|
1033
|
-
authentication: "basic"
|
|
1099
|
+
tokenEndpoint
|
|
1034
1100
|
});
|
|
1035
1101
|
},
|
|
1036
1102
|
refreshAccessToken: options.refreshAccessToken ? options.refreshAccessToken : async (refreshToken) => {
|
|
@@ -1038,32 +1104,53 @@ const notion = (options) => {
|
|
|
1038
1104
|
refreshToken,
|
|
1039
1105
|
options: {
|
|
1040
1106
|
clientId: options.clientId,
|
|
1041
|
-
clientKey: options.clientKey,
|
|
1042
1107
|
clientSecret: options.clientSecret
|
|
1043
1108
|
},
|
|
1044
1109
|
tokenEndpoint
|
|
1045
1110
|
});
|
|
1046
1111
|
},
|
|
1112
|
+
async verifyIdToken(token, nonce) {
|
|
1113
|
+
if (options.disableIdTokenSignIn) return false;
|
|
1114
|
+
if (options.verifyIdToken) return options.verifyIdToken(token, nonce);
|
|
1115
|
+
const body = new URLSearchParams();
|
|
1116
|
+
body.set("id_token", token);
|
|
1117
|
+
body.set("client_id", options.clientId);
|
|
1118
|
+
if (nonce) body.set("nonce", nonce);
|
|
1119
|
+
const { data, error } = await (0, __better_fetch_fetch.betterFetch)(verifyIdTokenEndpoint, {
|
|
1120
|
+
method: "POST",
|
|
1121
|
+
headers: { "content-type": "application/x-www-form-urlencoded" },
|
|
1122
|
+
body
|
|
1123
|
+
});
|
|
1124
|
+
if (error || !data) return false;
|
|
1125
|
+
if (data.aud !== options.clientId) return false;
|
|
1126
|
+
if (nonce && data.nonce && data.nonce !== nonce) return false;
|
|
1127
|
+
return true;
|
|
1128
|
+
},
|
|
1047
1129
|
async getUserInfo(token) {
|
|
1048
1130
|
if (options.getUserInfo) return options.getUserInfo(token);
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
} }
|
|
1053
|
-
if (
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1131
|
+
let profile = null;
|
|
1132
|
+
if (token.idToken) try {
|
|
1133
|
+
profile = (0, jose.decodeJwt)(token.idToken);
|
|
1134
|
+
} catch {}
|
|
1135
|
+
if (!profile) {
|
|
1136
|
+
const { data } = await (0, __better_fetch_fetch.betterFetch)(userInfoEndpoint, { headers: { authorization: `Bearer ${token.accessToken}` } });
|
|
1137
|
+
profile = data || null;
|
|
1138
|
+
}
|
|
1139
|
+
if (!profile) return null;
|
|
1140
|
+
const userMap = await options.mapProfileToUser?.(profile);
|
|
1141
|
+
const id = profile.sub || profile.userId;
|
|
1142
|
+
const name = profile.name || profile.displayName;
|
|
1143
|
+
const image = profile.picture || profile.pictureUrl || void 0;
|
|
1057
1144
|
return {
|
|
1058
1145
|
user: {
|
|
1059
|
-
id
|
|
1060
|
-
name
|
|
1061
|
-
email:
|
|
1062
|
-
image
|
|
1063
|
-
emailVerified:
|
|
1146
|
+
id,
|
|
1147
|
+
name,
|
|
1148
|
+
email: profile.email,
|
|
1149
|
+
image,
|
|
1150
|
+
emailVerified: false,
|
|
1064
1151
|
...userMap
|
|
1065
1152
|
},
|
|
1066
|
-
data:
|
|
1153
|
+
data: profile
|
|
1067
1154
|
};
|
|
1068
1155
|
},
|
|
1069
1156
|
options
|
|
@@ -1071,32 +1158,32 @@ const notion = (options) => {
|
|
|
1071
1158
|
};
|
|
1072
1159
|
|
|
1073
1160
|
//#endregion
|
|
1074
|
-
//#region src/social-providers/
|
|
1075
|
-
const
|
|
1161
|
+
//#region src/social-providers/linear.ts
|
|
1162
|
+
const linear = (options) => {
|
|
1163
|
+
const tokenEndpoint = "https://api.linear.app/oauth/token";
|
|
1076
1164
|
return {
|
|
1077
|
-
id: "
|
|
1078
|
-
name: "
|
|
1079
|
-
createAuthorizationURL({ state, scopes,
|
|
1080
|
-
const _scopes = options.disableDefaultScope ? [] : ["
|
|
1081
|
-
options.scope
|
|
1082
|
-
scopes
|
|
1165
|
+
id: "linear",
|
|
1166
|
+
name: "Linear",
|
|
1167
|
+
createAuthorizationURL({ state, scopes, loginHint, redirectURI }) {
|
|
1168
|
+
const _scopes = options.disableDefaultScope ? [] : ["read"];
|
|
1169
|
+
if (options.scope) _scopes.push(...options.scope);
|
|
1170
|
+
if (scopes) _scopes.push(...scopes);
|
|
1083
1171
|
return require_oauth2.createAuthorizationURL({
|
|
1084
|
-
id: "
|
|
1172
|
+
id: "linear",
|
|
1085
1173
|
options,
|
|
1086
|
-
authorizationEndpoint: "https://
|
|
1174
|
+
authorizationEndpoint: "https://linear.app/oauth/authorize",
|
|
1087
1175
|
scopes: _scopes,
|
|
1088
1176
|
state,
|
|
1089
|
-
|
|
1090
|
-
|
|
1177
|
+
redirectURI,
|
|
1178
|
+
loginHint
|
|
1091
1179
|
});
|
|
1092
1180
|
},
|
|
1093
|
-
validateAuthorizationCode: async ({ code,
|
|
1181
|
+
validateAuthorizationCode: async ({ code, redirectURI }) => {
|
|
1094
1182
|
return require_oauth2.validateAuthorizationCode({
|
|
1095
1183
|
code,
|
|
1096
|
-
codeVerifier,
|
|
1097
1184
|
redirectURI,
|
|
1098
1185
|
options,
|
|
1099
|
-
tokenEndpoint
|
|
1186
|
+
tokenEndpoint
|
|
1100
1187
|
});
|
|
1101
1188
|
},
|
|
1102
1189
|
refreshAccessToken: options.refreshAccessToken ? options.refreshAccessToken : async (refreshToken) => {
|
|
@@ -1107,27 +1194,44 @@ const spotify = (options) => {
|
|
|
1107
1194
|
clientKey: options.clientKey,
|
|
1108
1195
|
clientSecret: options.clientSecret
|
|
1109
1196
|
},
|
|
1110
|
-
tokenEndpoint
|
|
1197
|
+
tokenEndpoint
|
|
1111
1198
|
});
|
|
1112
1199
|
},
|
|
1113
1200
|
async getUserInfo(token) {
|
|
1114
1201
|
if (options.getUserInfo) return options.getUserInfo(token);
|
|
1115
|
-
const { data: profile, error } = await (0, __better_fetch_fetch.betterFetch)("https://api.
|
|
1116
|
-
method: "
|
|
1117
|
-
headers: {
|
|
1202
|
+
const { data: profile, error } = await (0, __better_fetch_fetch.betterFetch)("https://api.linear.app/graphql", {
|
|
1203
|
+
method: "POST",
|
|
1204
|
+
headers: {
|
|
1205
|
+
"Content-Type": "application/json",
|
|
1206
|
+
Authorization: `Bearer ${token.accessToken}`
|
|
1207
|
+
},
|
|
1208
|
+
body: JSON.stringify({ query: `
|
|
1209
|
+
query {
|
|
1210
|
+
viewer {
|
|
1211
|
+
id
|
|
1212
|
+
name
|
|
1213
|
+
email
|
|
1214
|
+
avatarUrl
|
|
1215
|
+
active
|
|
1216
|
+
createdAt
|
|
1217
|
+
updatedAt
|
|
1218
|
+
}
|
|
1219
|
+
}
|
|
1220
|
+
` })
|
|
1118
1221
|
});
|
|
1119
|
-
if (error) return null;
|
|
1120
|
-
const
|
|
1222
|
+
if (error || !profile?.data?.viewer) return null;
|
|
1223
|
+
const userData = profile.data.viewer;
|
|
1224
|
+
const userMap = await options.mapProfileToUser?.(userData);
|
|
1121
1225
|
return {
|
|
1122
1226
|
user: {
|
|
1123
|
-
id: profile.id,
|
|
1124
|
-
name: profile.
|
|
1125
|
-
email: profile.email,
|
|
1126
|
-
image: profile.
|
|
1127
|
-
emailVerified:
|
|
1227
|
+
id: profile.data.viewer.id,
|
|
1228
|
+
name: profile.data.viewer.name,
|
|
1229
|
+
email: profile.data.viewer.email,
|
|
1230
|
+
image: profile.data.viewer.avatarUrl,
|
|
1231
|
+
emailVerified: true,
|
|
1128
1232
|
...userMap
|
|
1129
1233
|
},
|
|
1130
|
-
data:
|
|
1234
|
+
data: userData
|
|
1131
1235
|
};
|
|
1132
1236
|
},
|
|
1133
1237
|
options
|
|
@@ -1135,36 +1239,37 @@ const spotify = (options) => {
|
|
|
1135
1239
|
};
|
|
1136
1240
|
|
|
1137
1241
|
//#endregion
|
|
1138
|
-
//#region src/social-providers/
|
|
1139
|
-
const
|
|
1242
|
+
//#region src/social-providers/linkedin.ts
|
|
1243
|
+
const linkedin = (options) => {
|
|
1244
|
+
const authorizationEndpoint = "https://www.linkedin.com/oauth/v2/authorization";
|
|
1245
|
+
const tokenEndpoint = "https://www.linkedin.com/oauth/v2/accessToken";
|
|
1140
1246
|
return {
|
|
1141
|
-
id: "
|
|
1142
|
-
name: "
|
|
1143
|
-
createAuthorizationURL({ state, scopes, redirectURI }) {
|
|
1144
|
-
const _scopes = options.disableDefaultScope ? [] : [
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1247
|
+
id: "linkedin",
|
|
1248
|
+
name: "Linkedin",
|
|
1249
|
+
createAuthorizationURL: async ({ state, scopes, redirectURI, loginHint }) => {
|
|
1250
|
+
const _scopes = options.disableDefaultScope ? [] : [
|
|
1251
|
+
"profile",
|
|
1252
|
+
"email",
|
|
1253
|
+
"openid"
|
|
1254
|
+
];
|
|
1255
|
+
if (options.scope) _scopes.push(...options.scope);
|
|
1256
|
+
if (scopes) _scopes.push(...scopes);
|
|
1257
|
+
return await require_oauth2.createAuthorizationURL({
|
|
1258
|
+
id: "linkedin",
|
|
1150
1259
|
options,
|
|
1151
|
-
authorizationEndpoint
|
|
1260
|
+
authorizationEndpoint,
|
|
1152
1261
|
scopes: _scopes,
|
|
1153
1262
|
state,
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
"email_verified",
|
|
1157
|
-
"preferred_username",
|
|
1158
|
-
"picture"
|
|
1159
|
-
]
|
|
1263
|
+
loginHint,
|
|
1264
|
+
redirectURI
|
|
1160
1265
|
});
|
|
1161
1266
|
},
|
|
1162
1267
|
validateAuthorizationCode: async ({ code, redirectURI }) => {
|
|
1163
|
-
return require_oauth2.validateAuthorizationCode({
|
|
1268
|
+
return await require_oauth2.validateAuthorizationCode({
|
|
1164
1269
|
code,
|
|
1165
1270
|
redirectURI,
|
|
1166
1271
|
options,
|
|
1167
|
-
tokenEndpoint
|
|
1272
|
+
tokenEndpoint
|
|
1168
1273
|
});
|
|
1169
1274
|
},
|
|
1170
1275
|
refreshAccessToken: options.refreshAccessToken ? options.refreshAccessToken : async (refreshToken) => {
|
|
@@ -1175,25 +1280,24 @@ const twitch = (options) => {
|
|
|
1175
1280
|
clientKey: options.clientKey,
|
|
1176
1281
|
clientSecret: options.clientSecret
|
|
1177
1282
|
},
|
|
1178
|
-
tokenEndpoint
|
|
1283
|
+
tokenEndpoint
|
|
1179
1284
|
});
|
|
1180
1285
|
},
|
|
1181
1286
|
async getUserInfo(token) {
|
|
1182
1287
|
if (options.getUserInfo) return options.getUserInfo(token);
|
|
1183
|
-
const
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
const profile = (0, jose.decodeJwt)(idToken);
|
|
1288
|
+
const { data: profile, error } = await (0, __better_fetch_fetch.betterFetch)("https://api.linkedin.com/v2/userinfo", {
|
|
1289
|
+
method: "GET",
|
|
1290
|
+
headers: { Authorization: `Bearer ${token.accessToken}` }
|
|
1291
|
+
});
|
|
1292
|
+
if (error) return null;
|
|
1189
1293
|
const userMap = await options.mapProfileToUser?.(profile);
|
|
1190
1294
|
return {
|
|
1191
1295
|
user: {
|
|
1192
1296
|
id: profile.sub,
|
|
1193
|
-
name: profile.
|
|
1297
|
+
name: profile.name,
|
|
1194
1298
|
email: profile.email,
|
|
1299
|
+
emailVerified: profile.email_verified || false,
|
|
1195
1300
|
image: profile.picture,
|
|
1196
|
-
emailVerified: profile.email_verified,
|
|
1197
1301
|
...userMap
|
|
1198
1302
|
},
|
|
1199
1303
|
data: profile
|
|
@@ -1204,116 +1308,124 @@ const twitch = (options) => {
|
|
|
1204
1308
|
};
|
|
1205
1309
|
|
|
1206
1310
|
//#endregion
|
|
1207
|
-
//#region src/social-providers/
|
|
1208
|
-
const
|
|
1311
|
+
//#region src/social-providers/microsoft-entra-id.ts
|
|
1312
|
+
const microsoft = (options) => {
|
|
1313
|
+
const tenant = options.tenantId || "common";
|
|
1314
|
+
const authority = options.authority || "https://login.microsoftonline.com";
|
|
1315
|
+
const authorizationEndpoint = `${authority}/${tenant}/oauth2/v2.0/authorize`;
|
|
1316
|
+
const tokenEndpoint = `${authority}/${tenant}/oauth2/v2.0/token`;
|
|
1209
1317
|
return {
|
|
1210
|
-
id: "
|
|
1211
|
-
name: "
|
|
1318
|
+
id: "microsoft",
|
|
1319
|
+
name: "Microsoft EntraID",
|
|
1212
1320
|
createAuthorizationURL(data) {
|
|
1213
|
-
const
|
|
1214
|
-
"
|
|
1215
|
-
"
|
|
1216
|
-
"
|
|
1217
|
-
"
|
|
1321
|
+
const scopes = options.disableDefaultScope ? [] : [
|
|
1322
|
+
"openid",
|
|
1323
|
+
"profile",
|
|
1324
|
+
"email",
|
|
1325
|
+
"User.Read",
|
|
1326
|
+
"offline_access"
|
|
1218
1327
|
];
|
|
1219
|
-
options.scope
|
|
1220
|
-
data.scopes
|
|
1328
|
+
if (options.scope) scopes.push(...options.scope);
|
|
1329
|
+
if (data.scopes) scopes.push(...data.scopes);
|
|
1221
1330
|
return require_oauth2.createAuthorizationURL({
|
|
1222
|
-
id: "
|
|
1331
|
+
id: "microsoft",
|
|
1223
1332
|
options,
|
|
1224
|
-
authorizationEndpoint
|
|
1225
|
-
scopes: _scopes,
|
|
1333
|
+
authorizationEndpoint,
|
|
1226
1334
|
state: data.state,
|
|
1227
1335
|
codeVerifier: data.codeVerifier,
|
|
1228
|
-
|
|
1336
|
+
scopes,
|
|
1337
|
+
redirectURI: data.redirectURI,
|
|
1338
|
+
prompt: options.prompt,
|
|
1339
|
+
loginHint: data.loginHint
|
|
1229
1340
|
});
|
|
1230
1341
|
},
|
|
1231
|
-
validateAuthorizationCode
|
|
1342
|
+
validateAuthorizationCode({ code, codeVerifier, redirectURI }) {
|
|
1232
1343
|
return require_oauth2.validateAuthorizationCode({
|
|
1233
1344
|
code,
|
|
1234
1345
|
codeVerifier,
|
|
1235
|
-
authentication: "basic",
|
|
1236
1346
|
redirectURI,
|
|
1237
1347
|
options,
|
|
1238
|
-
tokenEndpoint
|
|
1239
|
-
});
|
|
1240
|
-
},
|
|
1241
|
-
refreshAccessToken: options.refreshAccessToken ? options.refreshAccessToken : async (refreshToken) => {
|
|
1242
|
-
return require_oauth2.refreshAccessToken({
|
|
1243
|
-
refreshToken,
|
|
1244
|
-
options: {
|
|
1245
|
-
clientId: options.clientId,
|
|
1246
|
-
clientKey: options.clientKey,
|
|
1247
|
-
clientSecret: options.clientSecret
|
|
1248
|
-
},
|
|
1249
|
-
authentication: "basic",
|
|
1250
|
-
tokenEndpoint: "https://api.x.com/2/oauth2/token"
|
|
1348
|
+
tokenEndpoint
|
|
1251
1349
|
});
|
|
1252
1350
|
},
|
|
1253
1351
|
async getUserInfo(token) {
|
|
1254
1352
|
if (options.getUserInfo) return options.getUserInfo(token);
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
}
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1353
|
+
if (!token.idToken) return null;
|
|
1354
|
+
const user = (0, jose.decodeJwt)(token.idToken);
|
|
1355
|
+
const profilePhotoSize = options.profilePhotoSize || 48;
|
|
1356
|
+
await (0, __better_fetch_fetch.betterFetch)(`https://graph.microsoft.com/v1.0/me/photos/${profilePhotoSize}x${profilePhotoSize}/$value`, {
|
|
1357
|
+
headers: { Authorization: `Bearer ${token.accessToken}` },
|
|
1358
|
+
async onResponse(context) {
|
|
1359
|
+
if (options.disableProfilePhoto || !context.response.ok) return;
|
|
1360
|
+
try {
|
|
1361
|
+
const pictureBuffer = await context.response.clone().arrayBuffer();
|
|
1362
|
+
user.picture = `data:image/jpeg;base64, ${__better_auth_utils_base64.base64.encode(pictureBuffer)}`;
|
|
1363
|
+
} catch (e) {
|
|
1364
|
+
require_env.logger.error(e && typeof e === "object" && "name" in e ? e.name : "", e);
|
|
1365
|
+
}
|
|
1366
|
+
}
|
|
1263
1367
|
});
|
|
1264
|
-
|
|
1265
|
-
if (!emailError && emailData?.data?.confirmed_email) {
|
|
1266
|
-
profile.data.email = emailData.data.confirmed_email;
|
|
1267
|
-
emailVerified = true;
|
|
1268
|
-
}
|
|
1269
|
-
const userMap = await options.mapProfileToUser?.(profile);
|
|
1368
|
+
const userMap = await options.mapProfileToUser?.(user);
|
|
1270
1369
|
return {
|
|
1271
1370
|
user: {
|
|
1272
|
-
id:
|
|
1273
|
-
name:
|
|
1274
|
-
email:
|
|
1275
|
-
image:
|
|
1276
|
-
emailVerified,
|
|
1371
|
+
id: user.sub,
|
|
1372
|
+
name: user.name,
|
|
1373
|
+
email: user.email,
|
|
1374
|
+
image: user.picture,
|
|
1375
|
+
emailVerified: true,
|
|
1277
1376
|
...userMap
|
|
1278
1377
|
},
|
|
1279
|
-
data:
|
|
1378
|
+
data: user
|
|
1280
1379
|
};
|
|
1281
1380
|
},
|
|
1381
|
+
refreshAccessToken: options.refreshAccessToken ? options.refreshAccessToken : async (refreshToken) => {
|
|
1382
|
+
const scopes = options.disableDefaultScope ? [] : [
|
|
1383
|
+
"openid",
|
|
1384
|
+
"profile",
|
|
1385
|
+
"email",
|
|
1386
|
+
"User.Read",
|
|
1387
|
+
"offline_access"
|
|
1388
|
+
];
|
|
1389
|
+
if (options.scope) scopes.push(...options.scope);
|
|
1390
|
+
return require_oauth2.refreshAccessToken({
|
|
1391
|
+
refreshToken,
|
|
1392
|
+
options: {
|
|
1393
|
+
clientId: options.clientId,
|
|
1394
|
+
clientSecret: options.clientSecret
|
|
1395
|
+
},
|
|
1396
|
+
extraParams: { scope: scopes.join(" ") },
|
|
1397
|
+
tokenEndpoint
|
|
1398
|
+
});
|
|
1399
|
+
},
|
|
1282
1400
|
options
|
|
1283
1401
|
};
|
|
1284
1402
|
};
|
|
1285
1403
|
|
|
1286
1404
|
//#endregion
|
|
1287
|
-
//#region src/social-providers/
|
|
1288
|
-
const
|
|
1289
|
-
const tokenEndpoint = "https://api.dropboxapi.com/oauth2/token";
|
|
1405
|
+
//#region src/social-providers/naver.ts
|
|
1406
|
+
const naver = (options) => {
|
|
1290
1407
|
return {
|
|
1291
|
-
id: "
|
|
1292
|
-
name: "
|
|
1293
|
-
createAuthorizationURL
|
|
1294
|
-
const _scopes = options.disableDefaultScope ? [] : ["
|
|
1295
|
-
options.scope
|
|
1296
|
-
scopes
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
return await require_oauth2.createAuthorizationURL({
|
|
1300
|
-
id: "dropbox",
|
|
1408
|
+
id: "naver",
|
|
1409
|
+
name: "Naver",
|
|
1410
|
+
createAuthorizationURL({ state, scopes, redirectURI }) {
|
|
1411
|
+
const _scopes = options.disableDefaultScope ? [] : ["profile", "email"];
|
|
1412
|
+
if (options.scope) _scopes.push(...options.scope);
|
|
1413
|
+
if (scopes) _scopes.push(...scopes);
|
|
1414
|
+
return require_oauth2.createAuthorizationURL({
|
|
1415
|
+
id: "naver",
|
|
1301
1416
|
options,
|
|
1302
|
-
authorizationEndpoint: "https://
|
|
1417
|
+
authorizationEndpoint: "https://nid.naver.com/oauth2.0/authorize",
|
|
1303
1418
|
scopes: _scopes,
|
|
1304
1419
|
state,
|
|
1305
|
-
redirectURI
|
|
1306
|
-
codeVerifier,
|
|
1307
|
-
additionalParams
|
|
1420
|
+
redirectURI
|
|
1308
1421
|
});
|
|
1309
1422
|
},
|
|
1310
|
-
validateAuthorizationCode: async ({ code,
|
|
1311
|
-
return
|
|
1423
|
+
validateAuthorizationCode: async ({ code, redirectURI }) => {
|
|
1424
|
+
return require_oauth2.validateAuthorizationCode({
|
|
1312
1425
|
code,
|
|
1313
|
-
codeVerifier,
|
|
1314
1426
|
redirectURI,
|
|
1315
1427
|
options,
|
|
1316
|
-
tokenEndpoint
|
|
1428
|
+
tokenEndpoint: "https://nid.naver.com/oauth2.0/token"
|
|
1317
1429
|
});
|
|
1318
1430
|
},
|
|
1319
1431
|
refreshAccessToken: options.refreshAccessToken ? options.refreshAccessToken : async (refreshToken) => {
|
|
@@ -1324,24 +1436,22 @@ const dropbox = (options) => {
|
|
|
1324
1436
|
clientKey: options.clientKey,
|
|
1325
1437
|
clientSecret: options.clientSecret
|
|
1326
1438
|
},
|
|
1327
|
-
tokenEndpoint: "https://
|
|
1439
|
+
tokenEndpoint: "https://nid.naver.com/oauth2.0/token"
|
|
1328
1440
|
});
|
|
1329
1441
|
},
|
|
1330
1442
|
async getUserInfo(token) {
|
|
1331
1443
|
if (options.getUserInfo) return options.getUserInfo(token);
|
|
1332
|
-
const { data: profile, error } = await (0, __better_fetch_fetch.betterFetch)("https://
|
|
1333
|
-
|
|
1334
|
-
headers: { Authorization: `Bearer ${token.accessToken}` }
|
|
1335
|
-
});
|
|
1336
|
-
if (error) return null;
|
|
1444
|
+
const { data: profile, error } = await (0, __better_fetch_fetch.betterFetch)("https://openapi.naver.com/v1/nid/me", { headers: { Authorization: `Bearer ${token.accessToken}` } });
|
|
1445
|
+
if (error || !profile || profile.resultcode !== "00") return null;
|
|
1337
1446
|
const userMap = await options.mapProfileToUser?.(profile);
|
|
1447
|
+
const res = profile.response || {};
|
|
1338
1448
|
return {
|
|
1339
1449
|
user: {
|
|
1340
|
-
id:
|
|
1341
|
-
name:
|
|
1342
|
-
email:
|
|
1343
|
-
|
|
1344
|
-
|
|
1450
|
+
id: res.id,
|
|
1451
|
+
name: res.name || res.nickname,
|
|
1452
|
+
email: res.email,
|
|
1453
|
+
image: res.profile_image,
|
|
1454
|
+
emailVerified: false,
|
|
1345
1455
|
...userMap
|
|
1346
1456
|
},
|
|
1347
1457
|
data: profile
|
|
@@ -1352,24 +1462,25 @@ const dropbox = (options) => {
|
|
|
1352
1462
|
};
|
|
1353
1463
|
|
|
1354
1464
|
//#endregion
|
|
1355
|
-
//#region src/social-providers/
|
|
1356
|
-
const
|
|
1357
|
-
const tokenEndpoint = "https://api.
|
|
1465
|
+
//#region src/social-providers/notion.ts
|
|
1466
|
+
const notion = (options) => {
|
|
1467
|
+
const tokenEndpoint = "https://api.notion.com/v1/oauth/token";
|
|
1358
1468
|
return {
|
|
1359
|
-
id: "
|
|
1360
|
-
name: "
|
|
1469
|
+
id: "notion",
|
|
1470
|
+
name: "Notion",
|
|
1361
1471
|
createAuthorizationURL({ state, scopes, loginHint, redirectURI }) {
|
|
1362
|
-
const _scopes = options.disableDefaultScope ? [] : [
|
|
1363
|
-
options.scope
|
|
1364
|
-
scopes
|
|
1472
|
+
const _scopes = options.disableDefaultScope ? [] : [];
|
|
1473
|
+
if (options.scope) _scopes.push(...options.scope);
|
|
1474
|
+
if (scopes) _scopes.push(...scopes);
|
|
1365
1475
|
return require_oauth2.createAuthorizationURL({
|
|
1366
|
-
id: "
|
|
1476
|
+
id: "notion",
|
|
1367
1477
|
options,
|
|
1368
|
-
authorizationEndpoint: "https://
|
|
1478
|
+
authorizationEndpoint: "https://api.notion.com/v1/oauth/authorize",
|
|
1369
1479
|
scopes: _scopes,
|
|
1370
1480
|
state,
|
|
1371
1481
|
redirectURI,
|
|
1372
|
-
loginHint
|
|
1482
|
+
loginHint,
|
|
1483
|
+
additionalParams: { owner: "user" }
|
|
1373
1484
|
});
|
|
1374
1485
|
},
|
|
1375
1486
|
validateAuthorizationCode: async ({ code, redirectURI }) => {
|
|
@@ -1377,7 +1488,8 @@ const linear = (options) => {
|
|
|
1377
1488
|
code,
|
|
1378
1489
|
redirectURI,
|
|
1379
1490
|
options,
|
|
1380
|
-
tokenEndpoint
|
|
1491
|
+
tokenEndpoint,
|
|
1492
|
+
authentication: "basic"
|
|
1381
1493
|
});
|
|
1382
1494
|
},
|
|
1383
1495
|
refreshAccessToken: options.refreshAccessToken ? options.refreshAccessToken : async (refreshToken) => {
|
|
@@ -1393,39 +1505,24 @@ const linear = (options) => {
|
|
|
1393
1505
|
},
|
|
1394
1506
|
async getUserInfo(token) {
|
|
1395
1507
|
if (options.getUserInfo) return options.getUserInfo(token);
|
|
1396
|
-
const { data: profile, error } = await (0, __better_fetch_fetch.betterFetch)("https://api.
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
viewer {
|
|
1405
|
-
id
|
|
1406
|
-
name
|
|
1407
|
-
email
|
|
1408
|
-
avatarUrl
|
|
1409
|
-
active
|
|
1410
|
-
createdAt
|
|
1411
|
-
updatedAt
|
|
1412
|
-
}
|
|
1413
|
-
}
|
|
1414
|
-
` })
|
|
1415
|
-
});
|
|
1416
|
-
if (error || !profile?.data?.viewer) return null;
|
|
1417
|
-
const userData = profile.data.viewer;
|
|
1418
|
-
const userMap = await options.mapProfileToUser?.(userData);
|
|
1508
|
+
const { data: profile, error } = await (0, __better_fetch_fetch.betterFetch)("https://api.notion.com/v1/users/me", { headers: {
|
|
1509
|
+
Authorization: `Bearer ${token.accessToken}`,
|
|
1510
|
+
"Notion-Version": "2022-06-28"
|
|
1511
|
+
} });
|
|
1512
|
+
if (error || !profile) return null;
|
|
1513
|
+
const userProfile = profile.bot?.owner?.user;
|
|
1514
|
+
if (!userProfile) return null;
|
|
1515
|
+
const userMap = await options.mapProfileToUser?.(userProfile);
|
|
1419
1516
|
return {
|
|
1420
1517
|
user: {
|
|
1421
|
-
id:
|
|
1422
|
-
name:
|
|
1423
|
-
email:
|
|
1424
|
-
image:
|
|
1425
|
-
emailVerified:
|
|
1518
|
+
id: userProfile.id,
|
|
1519
|
+
name: userProfile.name || "Notion User",
|
|
1520
|
+
email: userProfile.person?.email || null,
|
|
1521
|
+
image: userProfile.avatar_url,
|
|
1522
|
+
emailVerified: !!userProfile.person?.email,
|
|
1426
1523
|
...userMap
|
|
1427
1524
|
},
|
|
1428
|
-
data:
|
|
1525
|
+
data: userProfile
|
|
1429
1526
|
};
|
|
1430
1527
|
},
|
|
1431
1528
|
options
|
|
@@ -1433,34 +1530,43 @@ const linear = (options) => {
|
|
|
1433
1530
|
};
|
|
1434
1531
|
|
|
1435
1532
|
//#endregion
|
|
1436
|
-
//#region src/social-providers/
|
|
1437
|
-
const
|
|
1438
|
-
const
|
|
1439
|
-
const
|
|
1533
|
+
//#region src/social-providers/paybin.ts
|
|
1534
|
+
const paybin = (options) => {
|
|
1535
|
+
const issuer = options.issuer || "https://idp.paybin.io";
|
|
1536
|
+
const authorizationEndpoint = `${issuer}/oauth2/authorize`;
|
|
1537
|
+
const tokenEndpoint = `${issuer}/oauth2/token`;
|
|
1440
1538
|
return {
|
|
1441
|
-
id: "
|
|
1442
|
-
name: "
|
|
1443
|
-
|
|
1539
|
+
id: "paybin",
|
|
1540
|
+
name: "Paybin",
|
|
1541
|
+
async createAuthorizationURL({ state, scopes, codeVerifier, redirectURI, loginHint }) {
|
|
1542
|
+
if (!options.clientId || !options.clientSecret) {
|
|
1543
|
+
require_env.logger.error("Client Id and Client Secret is required for Paybin. Make sure to provide them in the options.");
|
|
1544
|
+
throw new require_error.BetterAuthError("CLIENT_ID_AND_SECRET_REQUIRED");
|
|
1545
|
+
}
|
|
1546
|
+
if (!codeVerifier) throw new require_error.BetterAuthError("codeVerifier is required for Paybin");
|
|
1444
1547
|
const _scopes = options.disableDefaultScope ? [] : [
|
|
1445
|
-
"
|
|
1548
|
+
"openid",
|
|
1446
1549
|
"email",
|
|
1447
|
-
"
|
|
1550
|
+
"profile"
|
|
1448
1551
|
];
|
|
1449
|
-
options.scope
|
|
1450
|
-
scopes
|
|
1552
|
+
if (options.scope) _scopes.push(...options.scope);
|
|
1553
|
+
if (scopes) _scopes.push(...scopes);
|
|
1451
1554
|
return await require_oauth2.createAuthorizationURL({
|
|
1452
|
-
id: "
|
|
1555
|
+
id: "paybin",
|
|
1453
1556
|
options,
|
|
1454
1557
|
authorizationEndpoint,
|
|
1455
1558
|
scopes: _scopes,
|
|
1456
1559
|
state,
|
|
1457
|
-
|
|
1458
|
-
redirectURI
|
|
1560
|
+
codeVerifier,
|
|
1561
|
+
redirectURI,
|
|
1562
|
+
prompt: options.prompt,
|
|
1563
|
+
loginHint
|
|
1459
1564
|
});
|
|
1460
1565
|
},
|
|
1461
|
-
validateAuthorizationCode: async ({ code, redirectURI }) => {
|
|
1462
|
-
return
|
|
1566
|
+
validateAuthorizationCode: async ({ code, codeVerifier, redirectURI }) => {
|
|
1567
|
+
return require_oauth2.validateAuthorizationCode({
|
|
1463
1568
|
code,
|
|
1569
|
+
codeVerifier,
|
|
1464
1570
|
redirectURI,
|
|
1465
1571
|
options,
|
|
1466
1572
|
tokenEndpoint
|
|
@@ -1479,22 +1585,19 @@ const linkedin = (options) => {
|
|
|
1479
1585
|
},
|
|
1480
1586
|
async getUserInfo(token) {
|
|
1481
1587
|
if (options.getUserInfo) return options.getUserInfo(token);
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
});
|
|
1486
|
-
if (error) return null;
|
|
1487
|
-
const userMap = await options.mapProfileToUser?.(profile);
|
|
1588
|
+
if (!token.idToken) return null;
|
|
1589
|
+
const user = (0, jose.decodeJwt)(token.idToken);
|
|
1590
|
+
const userMap = await options.mapProfileToUser?.(user);
|
|
1488
1591
|
return {
|
|
1489
1592
|
user: {
|
|
1490
|
-
id:
|
|
1491
|
-
name:
|
|
1492
|
-
email:
|
|
1493
|
-
|
|
1494
|
-
|
|
1593
|
+
id: user.sub,
|
|
1594
|
+
name: user.name || user.preferred_username || (user.email ? user.email.split("@")[0] : "User") || "User",
|
|
1595
|
+
email: user.email,
|
|
1596
|
+
image: user.picture,
|
|
1597
|
+
emailVerified: user.email_verified || false,
|
|
1495
1598
|
...userMap
|
|
1496
1599
|
},
|
|
1497
|
-
data:
|
|
1600
|
+
data: user
|
|
1498
1601
|
};
|
|
1499
1602
|
},
|
|
1500
1603
|
options
|
|
@@ -1502,46 +1605,171 @@ const linkedin = (options) => {
|
|
|
1502
1605
|
};
|
|
1503
1606
|
|
|
1504
1607
|
//#endregion
|
|
1505
|
-
//#region src/social-providers/
|
|
1506
|
-
const
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
const
|
|
1510
|
-
|
|
1608
|
+
//#region src/social-providers/paypal.ts
|
|
1609
|
+
const paypal = (options) => {
|
|
1610
|
+
const isSandbox = (options.environment || "sandbox") === "sandbox";
|
|
1611
|
+
const authorizationEndpoint = isSandbox ? "https://www.sandbox.paypal.com/signin/authorize" : "https://www.paypal.com/signin/authorize";
|
|
1612
|
+
const tokenEndpoint = isSandbox ? "https://api-m.sandbox.paypal.com/v1/oauth2/token" : "https://api-m.paypal.com/v1/oauth2/token";
|
|
1613
|
+
const userInfoEndpoint = isSandbox ? "https://api-m.sandbox.paypal.com/v1/identity/oauth2/userinfo" : "https://api-m.paypal.com/v1/identity/oauth2/userinfo";
|
|
1511
1614
|
return {
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1615
|
+
id: "paypal",
|
|
1616
|
+
name: "PayPal",
|
|
1617
|
+
async createAuthorizationURL({ state, codeVerifier, redirectURI }) {
|
|
1618
|
+
if (!options.clientId || !options.clientSecret) {
|
|
1619
|
+
require_env.logger.error("Client Id and Client Secret is required for PayPal. Make sure to provide them in the options.");
|
|
1620
|
+
throw new require_error.BetterAuthError("CLIENT_ID_AND_SECRET_REQUIRED");
|
|
1621
|
+
}
|
|
1622
|
+
return await require_oauth2.createAuthorizationURL({
|
|
1623
|
+
id: "paypal",
|
|
1624
|
+
options,
|
|
1625
|
+
authorizationEndpoint,
|
|
1626
|
+
scopes: [],
|
|
1627
|
+
state,
|
|
1628
|
+
codeVerifier,
|
|
1629
|
+
redirectURI,
|
|
1630
|
+
prompt: options.prompt
|
|
1631
|
+
});
|
|
1632
|
+
},
|
|
1633
|
+
validateAuthorizationCode: async ({ code, redirectURI }) => {
|
|
1634
|
+
/**
|
|
1635
|
+
* PayPal requires Basic Auth for token exchange
|
|
1636
|
+
**/
|
|
1637
|
+
const credentials = __better_auth_utils_base64.base64.encode(`${options.clientId}:${options.clientSecret}`);
|
|
1638
|
+
try {
|
|
1639
|
+
const response = await (0, __better_fetch_fetch.betterFetch)(tokenEndpoint, {
|
|
1640
|
+
method: "POST",
|
|
1641
|
+
headers: {
|
|
1642
|
+
Authorization: `Basic ${credentials}`,
|
|
1643
|
+
Accept: "application/json",
|
|
1644
|
+
"Accept-Language": "en_US",
|
|
1645
|
+
"Content-Type": "application/x-www-form-urlencoded"
|
|
1646
|
+
},
|
|
1647
|
+
body: new URLSearchParams({
|
|
1648
|
+
grant_type: "authorization_code",
|
|
1649
|
+
code,
|
|
1650
|
+
redirect_uri: redirectURI
|
|
1651
|
+
}).toString()
|
|
1652
|
+
});
|
|
1653
|
+
if (!response.data) throw new require_error.BetterAuthError("FAILED_TO_GET_ACCESS_TOKEN");
|
|
1654
|
+
const data = response.data;
|
|
1655
|
+
return {
|
|
1656
|
+
accessToken: data.access_token,
|
|
1657
|
+
refreshToken: data.refresh_token,
|
|
1658
|
+
accessTokenExpiresAt: data.expires_in ? new Date(Date.now() + data.expires_in * 1e3) : void 0,
|
|
1659
|
+
idToken: data.id_token
|
|
1660
|
+
};
|
|
1661
|
+
} catch (error) {
|
|
1662
|
+
require_env.logger.error("PayPal token exchange failed:", error);
|
|
1663
|
+
throw new require_error.BetterAuthError("FAILED_TO_GET_ACCESS_TOKEN");
|
|
1664
|
+
}
|
|
1665
|
+
},
|
|
1666
|
+
refreshAccessToken: options.refreshAccessToken ? options.refreshAccessToken : async (refreshToken) => {
|
|
1667
|
+
const credentials = __better_auth_utils_base64.base64.encode(`${options.clientId}:${options.clientSecret}`);
|
|
1668
|
+
try {
|
|
1669
|
+
const response = await (0, __better_fetch_fetch.betterFetch)(tokenEndpoint, {
|
|
1670
|
+
method: "POST",
|
|
1671
|
+
headers: {
|
|
1672
|
+
Authorization: `Basic ${credentials}`,
|
|
1673
|
+
Accept: "application/json",
|
|
1674
|
+
"Accept-Language": "en_US",
|
|
1675
|
+
"Content-Type": "application/x-www-form-urlencoded"
|
|
1676
|
+
},
|
|
1677
|
+
body: new URLSearchParams({
|
|
1678
|
+
grant_type: "refresh_token",
|
|
1679
|
+
refresh_token: refreshToken
|
|
1680
|
+
}).toString()
|
|
1681
|
+
});
|
|
1682
|
+
if (!response.data) throw new require_error.BetterAuthError("FAILED_TO_REFRESH_ACCESS_TOKEN");
|
|
1683
|
+
const data = response.data;
|
|
1684
|
+
return {
|
|
1685
|
+
accessToken: data.access_token,
|
|
1686
|
+
refreshToken: data.refresh_token,
|
|
1687
|
+
accessTokenExpiresAt: data.expires_in ? new Date(Date.now() + data.expires_in * 1e3) : void 0
|
|
1688
|
+
};
|
|
1689
|
+
} catch (error) {
|
|
1690
|
+
require_env.logger.error("PayPal token refresh failed:", error);
|
|
1691
|
+
throw new require_error.BetterAuthError("FAILED_TO_REFRESH_ACCESS_TOKEN");
|
|
1692
|
+
}
|
|
1693
|
+
},
|
|
1694
|
+
async verifyIdToken(token, nonce) {
|
|
1695
|
+
if (options.disableIdTokenSignIn) return false;
|
|
1696
|
+
if (options.verifyIdToken) return options.verifyIdToken(token, nonce);
|
|
1697
|
+
try {
|
|
1698
|
+
return !!(0, jose.decodeJwt)(token).sub;
|
|
1699
|
+
} catch (error) {
|
|
1700
|
+
require_env.logger.error("Failed to verify PayPal ID token:", error);
|
|
1701
|
+
return false;
|
|
1702
|
+
}
|
|
1703
|
+
},
|
|
1704
|
+
async getUserInfo(token) {
|
|
1705
|
+
if (options.getUserInfo) return options.getUserInfo(token);
|
|
1706
|
+
if (!token.accessToken) {
|
|
1707
|
+
require_env.logger.error("Access token is required to fetch PayPal user info");
|
|
1708
|
+
return null;
|
|
1709
|
+
}
|
|
1710
|
+
try {
|
|
1711
|
+
const response = await (0, __better_fetch_fetch.betterFetch)(`${userInfoEndpoint}?schema=paypalv1.1`, { headers: {
|
|
1712
|
+
Authorization: `Bearer ${token.accessToken}`,
|
|
1713
|
+
Accept: "application/json"
|
|
1714
|
+
} });
|
|
1715
|
+
if (!response.data) {
|
|
1716
|
+
require_env.logger.error("Failed to fetch user info from PayPal");
|
|
1717
|
+
return null;
|
|
1718
|
+
}
|
|
1719
|
+
const userInfo = response.data;
|
|
1720
|
+
const userMap = await options.mapProfileToUser?.(userInfo);
|
|
1721
|
+
return {
|
|
1722
|
+
user: {
|
|
1723
|
+
id: userInfo.user_id,
|
|
1724
|
+
name: userInfo.name,
|
|
1725
|
+
email: userInfo.email,
|
|
1726
|
+
image: userInfo.picture,
|
|
1727
|
+
emailVerified: userInfo.email_verified,
|
|
1728
|
+
...userMap
|
|
1729
|
+
},
|
|
1730
|
+
data: userInfo
|
|
1731
|
+
};
|
|
1732
|
+
} catch (error) {
|
|
1733
|
+
require_env.logger.error("Failed to fetch user info from PayPal:", error);
|
|
1734
|
+
return null;
|
|
1735
|
+
}
|
|
1736
|
+
},
|
|
1737
|
+
options
|
|
1515
1738
|
};
|
|
1516
1739
|
};
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1740
|
+
|
|
1741
|
+
//#endregion
|
|
1742
|
+
//#region src/social-providers/polar.ts
|
|
1743
|
+
const polar = (options) => {
|
|
1520
1744
|
return {
|
|
1521
|
-
id:
|
|
1522
|
-
name: "
|
|
1523
|
-
createAuthorizationURL
|
|
1524
|
-
const _scopes = options.disableDefaultScope ? [] : [
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1745
|
+
id: "polar",
|
|
1746
|
+
name: "Polar",
|
|
1747
|
+
createAuthorizationURL({ state, scopes, codeVerifier, redirectURI }) {
|
|
1748
|
+
const _scopes = options.disableDefaultScope ? [] : [
|
|
1749
|
+
"openid",
|
|
1750
|
+
"profile",
|
|
1751
|
+
"email"
|
|
1752
|
+
];
|
|
1753
|
+
if (options.scope) _scopes.push(...options.scope);
|
|
1754
|
+
if (scopes) _scopes.push(...scopes);
|
|
1755
|
+
return require_oauth2.createAuthorizationURL({
|
|
1756
|
+
id: "polar",
|
|
1529
1757
|
options,
|
|
1530
|
-
authorizationEndpoint,
|
|
1758
|
+
authorizationEndpoint: "https://polar.sh/oauth2/authorize",
|
|
1531
1759
|
scopes: _scopes,
|
|
1532
1760
|
state,
|
|
1533
|
-
redirectURI,
|
|
1534
1761
|
codeVerifier,
|
|
1535
|
-
|
|
1762
|
+
redirectURI,
|
|
1763
|
+
prompt: options.prompt
|
|
1536
1764
|
});
|
|
1537
1765
|
},
|
|
1538
|
-
validateAuthorizationCode: async ({ code,
|
|
1766
|
+
validateAuthorizationCode: async ({ code, codeVerifier, redirectURI }) => {
|
|
1539
1767
|
return require_oauth2.validateAuthorizationCode({
|
|
1540
1768
|
code,
|
|
1769
|
+
codeVerifier,
|
|
1541
1770
|
redirectURI,
|
|
1542
1771
|
options,
|
|
1543
|
-
|
|
1544
|
-
tokenEndpoint
|
|
1772
|
+
tokenEndpoint: "https://api.polar.sh/v1/oauth2/token"
|
|
1545
1773
|
});
|
|
1546
1774
|
},
|
|
1547
1775
|
refreshAccessToken: options.refreshAccessToken ? options.refreshAccessToken : async (refreshToken) => {
|
|
@@ -1552,18 +1780,18 @@ const gitlab = (options) => {
|
|
|
1552
1780
|
clientKey: options.clientKey,
|
|
1553
1781
|
clientSecret: options.clientSecret
|
|
1554
1782
|
},
|
|
1555
|
-
tokenEndpoint
|
|
1783
|
+
tokenEndpoint: "https://api.polar.sh/v1/oauth2/token"
|
|
1556
1784
|
});
|
|
1557
1785
|
},
|
|
1558
1786
|
async getUserInfo(token) {
|
|
1559
1787
|
if (options.getUserInfo) return options.getUserInfo(token);
|
|
1560
|
-
const { data: profile, error } = await (0, __better_fetch_fetch.betterFetch)(
|
|
1561
|
-
if (error
|
|
1788
|
+
const { data: profile, error } = await (0, __better_fetch_fetch.betterFetch)("https://api.polar.sh/v1/oauth2/userinfo", { headers: { Authorization: `Bearer ${token.accessToken}` } });
|
|
1789
|
+
if (error) return null;
|
|
1562
1790
|
const userMap = await options.mapProfileToUser?.(profile);
|
|
1563
1791
|
return {
|
|
1564
1792
|
user: {
|
|
1565
1793
|
id: profile.id,
|
|
1566
|
-
name: profile.
|
|
1794
|
+
name: profile.public_name || profile.username,
|
|
1567
1795
|
email: profile.email,
|
|
1568
1796
|
image: profile.avatar_url,
|
|
1569
1797
|
emailVerified: true,
|
|
@@ -1576,62 +1804,6 @@ const gitlab = (options) => {
|
|
|
1576
1804
|
};
|
|
1577
1805
|
};
|
|
1578
1806
|
|
|
1579
|
-
//#endregion
|
|
1580
|
-
//#region src/social-providers/tiktok.ts
|
|
1581
|
-
const tiktok = (options) => {
|
|
1582
|
-
return {
|
|
1583
|
-
id: "tiktok",
|
|
1584
|
-
name: "TikTok",
|
|
1585
|
-
createAuthorizationURL({ state, scopes, redirectURI }) {
|
|
1586
|
-
const _scopes = options.disableDefaultScope ? [] : ["user.info.profile"];
|
|
1587
|
-
options.scope && _scopes.push(...options.scope);
|
|
1588
|
-
scopes && _scopes.push(...scopes);
|
|
1589
|
-
return new URL(`https://www.tiktok.com/v2/auth/authorize?scope=${_scopes.join(",")}&response_type=code&client_key=${options.clientKey}&redirect_uri=${encodeURIComponent(options.redirectURI || redirectURI)}&state=${state}`);
|
|
1590
|
-
},
|
|
1591
|
-
validateAuthorizationCode: async ({ code, redirectURI }) => {
|
|
1592
|
-
return require_oauth2.validateAuthorizationCode({
|
|
1593
|
-
code,
|
|
1594
|
-
redirectURI: options.redirectURI || redirectURI,
|
|
1595
|
-
options: {
|
|
1596
|
-
clientKey: options.clientKey,
|
|
1597
|
-
clientSecret: options.clientSecret
|
|
1598
|
-
},
|
|
1599
|
-
tokenEndpoint: "https://open.tiktokapis.com/v2/oauth/token/"
|
|
1600
|
-
});
|
|
1601
|
-
},
|
|
1602
|
-
refreshAccessToken: options.refreshAccessToken ? options.refreshAccessToken : async (refreshToken) => {
|
|
1603
|
-
return require_oauth2.refreshAccessToken({
|
|
1604
|
-
refreshToken,
|
|
1605
|
-
options: { clientSecret: options.clientSecret },
|
|
1606
|
-
tokenEndpoint: "https://open.tiktokapis.com/v2/oauth/token/",
|
|
1607
|
-
authentication: "post",
|
|
1608
|
-
extraParams: { client_key: options.clientKey }
|
|
1609
|
-
});
|
|
1610
|
-
},
|
|
1611
|
-
async getUserInfo(token) {
|
|
1612
|
-
if (options.getUserInfo) return options.getUserInfo(token);
|
|
1613
|
-
const { data: profile, error } = await (0, __better_fetch_fetch.betterFetch)(`https://open.tiktokapis.com/v2/user/info/?fields=${[
|
|
1614
|
-
"open_id",
|
|
1615
|
-
"avatar_large_url",
|
|
1616
|
-
"display_name",
|
|
1617
|
-
"username"
|
|
1618
|
-
].join(",")}`, { headers: { authorization: `Bearer ${token.accessToken}` } });
|
|
1619
|
-
if (error) return null;
|
|
1620
|
-
return {
|
|
1621
|
-
user: {
|
|
1622
|
-
email: profile.data.user.email || profile.data.user.username,
|
|
1623
|
-
id: profile.data.user.open_id,
|
|
1624
|
-
name: profile.data.user.display_name || profile.data.user.username,
|
|
1625
|
-
image: profile.data.user.avatar_large_url,
|
|
1626
|
-
emailVerified: profile.data.user.email ? true : false
|
|
1627
|
-
},
|
|
1628
|
-
data: profile
|
|
1629
|
-
};
|
|
1630
|
-
},
|
|
1631
|
-
options
|
|
1632
|
-
};
|
|
1633
|
-
};
|
|
1634
|
-
|
|
1635
1807
|
//#endregion
|
|
1636
1808
|
//#region src/social-providers/reddit.ts
|
|
1637
1809
|
const reddit = (options) => {
|
|
@@ -1640,8 +1812,8 @@ const reddit = (options) => {
|
|
|
1640
1812
|
name: "Reddit",
|
|
1641
1813
|
createAuthorizationURL({ state, scopes, redirectURI }) {
|
|
1642
1814
|
const _scopes = options.disableDefaultScope ? [] : ["identity"];
|
|
1643
|
-
options.scope
|
|
1644
|
-
scopes
|
|
1815
|
+
if (options.scope) _scopes.push(...options.scope);
|
|
1816
|
+
if (scopes) _scopes.push(...scopes);
|
|
1645
1817
|
return require_oauth2.createAuthorizationURL({
|
|
1646
1818
|
id: "reddit",
|
|
1647
1819
|
options,
|
|
@@ -1715,8 +1887,8 @@ const roblox = (options) => {
|
|
|
1715
1887
|
name: "Roblox",
|
|
1716
1888
|
createAuthorizationURL({ state, scopes, redirectURI }) {
|
|
1717
1889
|
const _scopes = options.disableDefaultScope ? [] : ["openid", "profile"];
|
|
1718
|
-
options.scope
|
|
1719
|
-
scopes
|
|
1890
|
+
if (options.scope) _scopes.push(...options.scope);
|
|
1891
|
+
if (scopes) _scopes.push(...scopes);
|
|
1720
1892
|
return new URL(`https://apis.roblox.com/oauth/v1/authorize?scope=${_scopes.join("+")}&response_type=code&client_id=${options.clientId}&redirect_uri=${encodeURIComponent(options.redirectURI || redirectURI)}&state=${state}&prompt=${options.prompt || "select_account consent"}`);
|
|
1721
1893
|
},
|
|
1722
1894
|
validateAuthorizationCode: async ({ code, redirectURI }) => {
|
|
@@ -1781,8 +1953,8 @@ const salesforce = (options) => {
|
|
|
1781
1953
|
"email",
|
|
1782
1954
|
"profile"
|
|
1783
1955
|
];
|
|
1784
|
-
options.scope
|
|
1785
|
-
scopes
|
|
1956
|
+
if (options.scope) _scopes.push(...options.scope);
|
|
1957
|
+
if (scopes) _scopes.push(...scopes);
|
|
1786
1958
|
return require_oauth2.createAuthorizationURL({
|
|
1787
1959
|
id: "salesforce",
|
|
1788
1960
|
options,
|
|
@@ -1842,33 +2014,33 @@ const salesforce = (options) => {
|
|
|
1842
2014
|
};
|
|
1843
2015
|
|
|
1844
2016
|
//#endregion
|
|
1845
|
-
//#region src/social-providers/
|
|
1846
|
-
const
|
|
2017
|
+
//#region src/social-providers/slack.ts
|
|
2018
|
+
const slack = (options) => {
|
|
1847
2019
|
return {
|
|
1848
|
-
id: "
|
|
1849
|
-
name: "
|
|
1850
|
-
|
|
1851
|
-
const _scopes = options.disableDefaultScope ? [] : [
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
2020
|
+
id: "slack",
|
|
2021
|
+
name: "Slack",
|
|
2022
|
+
createAuthorizationURL({ state, scopes, redirectURI }) {
|
|
2023
|
+
const _scopes = options.disableDefaultScope ? [] : [
|
|
2024
|
+
"openid",
|
|
2025
|
+
"profile",
|
|
2026
|
+
"email"
|
|
2027
|
+
];
|
|
2028
|
+
if (scopes) _scopes.push(...scopes);
|
|
2029
|
+
if (options.scope) _scopes.push(...options.scope);
|
|
2030
|
+
const url = new URL("https://slack.com/openid/connect/authorize");
|
|
2031
|
+
url.searchParams.set("scope", _scopes.join(" "));
|
|
2032
|
+
url.searchParams.set("response_type", "code");
|
|
2033
|
+
url.searchParams.set("client_id", options.clientId);
|
|
2034
|
+
url.searchParams.set("redirect_uri", options.redirectURI || redirectURI);
|
|
2035
|
+
url.searchParams.set("state", state);
|
|
2036
|
+
return url;
|
|
1863
2037
|
},
|
|
1864
|
-
validateAuthorizationCode: async ({ code,
|
|
2038
|
+
validateAuthorizationCode: async ({ code, redirectURI }) => {
|
|
1865
2039
|
return require_oauth2.validateAuthorizationCode({
|
|
1866
2040
|
code,
|
|
1867
|
-
|
|
1868
|
-
redirectURI: options.redirectURI || redirectURI,
|
|
2041
|
+
redirectURI,
|
|
1869
2042
|
options,
|
|
1870
|
-
|
|
1871
|
-
tokenEndpoint: "https://id.vk.com/oauth2/auth"
|
|
2043
|
+
tokenEndpoint: "https://slack.com/api/openid.connect.token"
|
|
1872
2044
|
});
|
|
1873
2045
|
},
|
|
1874
2046
|
refreshAccessToken: options.refreshAccessToken ? options.refreshAccessToken : async (refreshToken) => {
|
|
@@ -1879,129 +2051,57 @@ const vk = (options) => {
|
|
|
1879
2051
|
clientKey: options.clientKey,
|
|
1880
2052
|
clientSecret: options.clientSecret
|
|
1881
2053
|
},
|
|
1882
|
-
tokenEndpoint: "https://
|
|
1883
|
-
});
|
|
1884
|
-
},
|
|
1885
|
-
async getUserInfo(data) {
|
|
1886
|
-
if (options.getUserInfo) return options.getUserInfo(data);
|
|
1887
|
-
if (!data.accessToken) return null;
|
|
1888
|
-
const formBody = new URLSearchParams({
|
|
1889
|
-
access_token: data.accessToken,
|
|
1890
|
-
client_id: options.clientId
|
|
1891
|
-
}).toString();
|
|
1892
|
-
const { data: profile, error } = await (0, __better_fetch_fetch.betterFetch)("https://id.vk.com/oauth2/user_info", {
|
|
1893
|
-
method: "POST",
|
|
1894
|
-
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
1895
|
-
body: formBody
|
|
1896
|
-
});
|
|
1897
|
-
if (error) return null;
|
|
1898
|
-
if (!profile.user.email) return null;
|
|
1899
|
-
const userMap = await options.mapProfileToUser?.(profile);
|
|
1900
|
-
return {
|
|
1901
|
-
user: {
|
|
1902
|
-
id: profile.user.user_id,
|
|
1903
|
-
first_name: profile.user.first_name,
|
|
1904
|
-
last_name: profile.user.last_name,
|
|
1905
|
-
email: profile.user.email,
|
|
1906
|
-
image: profile.user.avatar,
|
|
1907
|
-
emailVerified: !!profile.user.email,
|
|
1908
|
-
birthday: profile.user.birthday,
|
|
1909
|
-
sex: profile.user.sex,
|
|
1910
|
-
name: `${profile.user.first_name} ${profile.user.last_name}`,
|
|
1911
|
-
...userMap
|
|
1912
|
-
},
|
|
1913
|
-
data: profile
|
|
1914
|
-
};
|
|
1915
|
-
},
|
|
1916
|
-
options
|
|
1917
|
-
};
|
|
1918
|
-
};
|
|
1919
|
-
|
|
1920
|
-
//#endregion
|
|
1921
|
-
//#region src/social-providers/zoom.ts
|
|
1922
|
-
const zoom = (userOptions) => {
|
|
1923
|
-
const options = {
|
|
1924
|
-
pkce: true,
|
|
1925
|
-
...userOptions
|
|
1926
|
-
};
|
|
1927
|
-
return {
|
|
1928
|
-
id: "zoom",
|
|
1929
|
-
name: "Zoom",
|
|
1930
|
-
createAuthorizationURL: async ({ state, redirectURI, codeVerifier }) => {
|
|
1931
|
-
const params = new URLSearchParams({
|
|
1932
|
-
response_type: "code",
|
|
1933
|
-
redirect_uri: options.redirectURI ? options.redirectURI : redirectURI,
|
|
1934
|
-
client_id: options.clientId,
|
|
1935
|
-
state
|
|
1936
|
-
});
|
|
1937
|
-
if (options.pkce) {
|
|
1938
|
-
const codeChallenge = await require_oauth2.generateCodeChallenge(codeVerifier);
|
|
1939
|
-
params.set("code_challenge_method", "S256");
|
|
1940
|
-
params.set("code_challenge", codeChallenge);
|
|
1941
|
-
}
|
|
1942
|
-
const url = new URL("https://zoom.us/oauth/authorize");
|
|
1943
|
-
url.search = params.toString();
|
|
1944
|
-
return url;
|
|
1945
|
-
},
|
|
1946
|
-
validateAuthorizationCode: async ({ code, redirectURI, codeVerifier }) => {
|
|
1947
|
-
return require_oauth2.validateAuthorizationCode({
|
|
1948
|
-
code,
|
|
1949
|
-
redirectURI: options.redirectURI || redirectURI,
|
|
1950
|
-
codeVerifier,
|
|
1951
|
-
options,
|
|
1952
|
-
tokenEndpoint: "https://zoom.us/oauth/token",
|
|
1953
|
-
authentication: "post"
|
|
2054
|
+
tokenEndpoint: "https://slack.com/api/openid.connect.token"
|
|
1954
2055
|
});
|
|
1955
2056
|
},
|
|
1956
2057
|
async getUserInfo(token) {
|
|
1957
2058
|
if (options.getUserInfo) return options.getUserInfo(token);
|
|
1958
|
-
const { data: profile, error } = await (0, __better_fetch_fetch.betterFetch)("https://api.
|
|
2059
|
+
const { data: profile, error } = await (0, __better_fetch_fetch.betterFetch)("https://slack.com/api/openid.connect.userInfo", { headers: { authorization: `Bearer ${token.accessToken}` } });
|
|
1959
2060
|
if (error) return null;
|
|
1960
2061
|
const userMap = await options.mapProfileToUser?.(profile);
|
|
1961
2062
|
return {
|
|
1962
2063
|
user: {
|
|
1963
|
-
id: profile.
|
|
1964
|
-
name: profile.
|
|
1965
|
-
image: profile.pic_url,
|
|
2064
|
+
id: profile["https://slack.com/user_id"],
|
|
2065
|
+
name: profile.name || "",
|
|
1966
2066
|
email: profile.email,
|
|
1967
|
-
emailVerified:
|
|
2067
|
+
emailVerified: profile.email_verified,
|
|
2068
|
+
image: profile.picture || profile["https://slack.com/user_image_512"],
|
|
1968
2069
|
...userMap
|
|
1969
2070
|
},
|
|
1970
|
-
data:
|
|
2071
|
+
data: profile
|
|
1971
2072
|
};
|
|
1972
|
-
}
|
|
2073
|
+
},
|
|
2074
|
+
options
|
|
1973
2075
|
};
|
|
1974
2076
|
};
|
|
1975
2077
|
|
|
1976
2078
|
//#endregion
|
|
1977
|
-
//#region src/social-providers/
|
|
1978
|
-
const
|
|
2079
|
+
//#region src/social-providers/spotify.ts
|
|
2080
|
+
const spotify = (options) => {
|
|
1979
2081
|
return {
|
|
1980
|
-
id: "
|
|
1981
|
-
name: "
|
|
1982
|
-
createAuthorizationURL({ state, scopes, redirectURI }) {
|
|
1983
|
-
const _scopes = options.disableDefaultScope ? [] : [
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
"profile_nickname"
|
|
1987
|
-
];
|
|
1988
|
-
options.scope && _scopes.push(...options.scope);
|
|
1989
|
-
scopes && _scopes.push(...scopes);
|
|
2082
|
+
id: "spotify",
|
|
2083
|
+
name: "Spotify",
|
|
2084
|
+
createAuthorizationURL({ state, scopes, codeVerifier, redirectURI }) {
|
|
2085
|
+
const _scopes = options.disableDefaultScope ? [] : ["user-read-email"];
|
|
2086
|
+
if (options.scope) _scopes.push(...options.scope);
|
|
2087
|
+
if (scopes) _scopes.push(...scopes);
|
|
1990
2088
|
return require_oauth2.createAuthorizationURL({
|
|
1991
|
-
id: "
|
|
2089
|
+
id: "spotify",
|
|
1992
2090
|
options,
|
|
1993
|
-
authorizationEndpoint: "https://
|
|
2091
|
+
authorizationEndpoint: "https://accounts.spotify.com/authorize",
|
|
1994
2092
|
scopes: _scopes,
|
|
1995
2093
|
state,
|
|
2094
|
+
codeVerifier,
|
|
1996
2095
|
redirectURI
|
|
1997
2096
|
});
|
|
1998
2097
|
},
|
|
1999
|
-
validateAuthorizationCode: async ({ code, redirectURI }) => {
|
|
2098
|
+
validateAuthorizationCode: async ({ code, codeVerifier, redirectURI }) => {
|
|
2000
2099
|
return require_oauth2.validateAuthorizationCode({
|
|
2001
2100
|
code,
|
|
2101
|
+
codeVerifier,
|
|
2002
2102
|
redirectURI,
|
|
2003
2103
|
options,
|
|
2004
|
-
tokenEndpoint: "https://
|
|
2104
|
+
tokenEndpoint: "https://accounts.spotify.com/api/token"
|
|
2005
2105
|
});
|
|
2006
2106
|
},
|
|
2007
2107
|
refreshAccessToken: options.refreshAccessToken ? options.refreshAccessToken : async (refreshToken) => {
|
|
@@ -2012,23 +2112,24 @@ const kakao = (options) => {
|
|
|
2012
2112
|
clientKey: options.clientKey,
|
|
2013
2113
|
clientSecret: options.clientSecret
|
|
2014
2114
|
},
|
|
2015
|
-
tokenEndpoint: "https://
|
|
2115
|
+
tokenEndpoint: "https://accounts.spotify.com/api/token"
|
|
2016
2116
|
});
|
|
2017
2117
|
},
|
|
2018
2118
|
async getUserInfo(token) {
|
|
2019
2119
|
if (options.getUserInfo) return options.getUserInfo(token);
|
|
2020
|
-
const { data: profile, error } = await (0, __better_fetch_fetch.betterFetch)("https://
|
|
2021
|
-
|
|
2120
|
+
const { data: profile, error } = await (0, __better_fetch_fetch.betterFetch)("https://api.spotify.com/v1/me", {
|
|
2121
|
+
method: "GET",
|
|
2122
|
+
headers: { Authorization: `Bearer ${token.accessToken}` }
|
|
2123
|
+
});
|
|
2124
|
+
if (error) return null;
|
|
2022
2125
|
const userMap = await options.mapProfileToUser?.(profile);
|
|
2023
|
-
const account = profile.kakao_account || {};
|
|
2024
|
-
const kakaoProfile = account.profile || {};
|
|
2025
2126
|
return {
|
|
2026
2127
|
user: {
|
|
2027
|
-
id:
|
|
2028
|
-
name:
|
|
2029
|
-
email:
|
|
2030
|
-
image:
|
|
2031
|
-
emailVerified:
|
|
2128
|
+
id: profile.id,
|
|
2129
|
+
name: profile.display_name,
|
|
2130
|
+
email: profile.email,
|
|
2131
|
+
image: profile.images[0]?.url,
|
|
2132
|
+
emailVerified: false,
|
|
2032
2133
|
...userMap
|
|
2033
2134
|
},
|
|
2034
2135
|
data: profile
|
|
@@ -2039,57 +2140,53 @@ const kakao = (options) => {
|
|
|
2039
2140
|
};
|
|
2040
2141
|
|
|
2041
2142
|
//#endregion
|
|
2042
|
-
//#region src/social-providers/
|
|
2043
|
-
const
|
|
2143
|
+
//#region src/social-providers/tiktok.ts
|
|
2144
|
+
const tiktok = (options) => {
|
|
2044
2145
|
return {
|
|
2045
|
-
id: "
|
|
2046
|
-
name: "
|
|
2146
|
+
id: "tiktok",
|
|
2147
|
+
name: "TikTok",
|
|
2047
2148
|
createAuthorizationURL({ state, scopes, redirectURI }) {
|
|
2048
|
-
const _scopes = options.disableDefaultScope ? [] : ["profile"
|
|
2049
|
-
options.scope
|
|
2050
|
-
scopes
|
|
2051
|
-
return
|
|
2052
|
-
id: "naver",
|
|
2053
|
-
options,
|
|
2054
|
-
authorizationEndpoint: "https://nid.naver.com/oauth2.0/authorize",
|
|
2055
|
-
scopes: _scopes,
|
|
2056
|
-
state,
|
|
2057
|
-
redirectURI
|
|
2058
|
-
});
|
|
2149
|
+
const _scopes = options.disableDefaultScope ? [] : ["user.info.profile"];
|
|
2150
|
+
if (options.scope) _scopes.push(...options.scope);
|
|
2151
|
+
if (scopes) _scopes.push(...scopes);
|
|
2152
|
+
return new URL(`https://www.tiktok.com/v2/auth/authorize?scope=${_scopes.join(",")}&response_type=code&client_key=${options.clientKey}&redirect_uri=${encodeURIComponent(options.redirectURI || redirectURI)}&state=${state}`);
|
|
2059
2153
|
},
|
|
2060
2154
|
validateAuthorizationCode: async ({ code, redirectURI }) => {
|
|
2061
2155
|
return require_oauth2.validateAuthorizationCode({
|
|
2062
2156
|
code,
|
|
2063
|
-
redirectURI,
|
|
2064
|
-
options,
|
|
2065
|
-
tokenEndpoint: "https://nid.naver.com/oauth2.0/token"
|
|
2066
|
-
});
|
|
2067
|
-
},
|
|
2068
|
-
refreshAccessToken: options.refreshAccessToken ? options.refreshAccessToken : async (refreshToken) => {
|
|
2069
|
-
return require_oauth2.refreshAccessToken({
|
|
2070
|
-
refreshToken,
|
|
2157
|
+
redirectURI: options.redirectURI || redirectURI,
|
|
2071
2158
|
options: {
|
|
2072
|
-
clientId: options.clientId,
|
|
2073
2159
|
clientKey: options.clientKey,
|
|
2074
2160
|
clientSecret: options.clientSecret
|
|
2075
2161
|
},
|
|
2076
|
-
tokenEndpoint: "https://
|
|
2162
|
+
tokenEndpoint: "https://open.tiktokapis.com/v2/oauth/token/"
|
|
2163
|
+
});
|
|
2164
|
+
},
|
|
2165
|
+
refreshAccessToken: options.refreshAccessToken ? options.refreshAccessToken : async (refreshToken) => {
|
|
2166
|
+
return require_oauth2.refreshAccessToken({
|
|
2167
|
+
refreshToken,
|
|
2168
|
+
options: { clientSecret: options.clientSecret },
|
|
2169
|
+
tokenEndpoint: "https://open.tiktokapis.com/v2/oauth/token/",
|
|
2170
|
+
authentication: "post",
|
|
2171
|
+
extraParams: { client_key: options.clientKey }
|
|
2077
2172
|
});
|
|
2078
2173
|
},
|
|
2079
2174
|
async getUserInfo(token) {
|
|
2080
2175
|
if (options.getUserInfo) return options.getUserInfo(token);
|
|
2081
|
-
const { data: profile, error } = await (0, __better_fetch_fetch.betterFetch)(
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2176
|
+
const { data: profile, error } = await (0, __better_fetch_fetch.betterFetch)(`https://open.tiktokapis.com/v2/user/info/?fields=${[
|
|
2177
|
+
"open_id",
|
|
2178
|
+
"avatar_large_url",
|
|
2179
|
+
"display_name",
|
|
2180
|
+
"username"
|
|
2181
|
+
].join(",")}`, { headers: { authorization: `Bearer ${token.accessToken}` } });
|
|
2182
|
+
if (error) return null;
|
|
2085
2183
|
return {
|
|
2086
2184
|
user: {
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
image:
|
|
2091
|
-
emailVerified: false
|
|
2092
|
-
...userMap
|
|
2185
|
+
email: profile.data.user.email || profile.data.user.username,
|
|
2186
|
+
id: profile.data.user.open_id,
|
|
2187
|
+
name: profile.data.user.display_name || profile.data.user.username,
|
|
2188
|
+
image: profile.data.user.avatar_large_url,
|
|
2189
|
+
emailVerified: profile.data.user.email ? true : false
|
|
2093
2190
|
},
|
|
2094
2191
|
data: profile
|
|
2095
2192
|
};
|
|
@@ -2099,50 +2196,36 @@ const naver = (options) => {
|
|
|
2099
2196
|
};
|
|
2100
2197
|
|
|
2101
2198
|
//#endregion
|
|
2102
|
-
//#region src/social-providers/
|
|
2103
|
-
|
|
2104
|
-
* LINE Login v2.1
|
|
2105
|
-
* - Authorization endpoint: https://access.line.me/oauth2/v2.1/authorize
|
|
2106
|
-
* - Token endpoint: https://api.line.me/oauth2/v2.1/token
|
|
2107
|
-
* - UserInfo endpoint: https://api.line.me/oauth2/v2.1/userinfo
|
|
2108
|
-
* - Verify ID token: https://api.line.me/oauth2/v2.1/verify
|
|
2109
|
-
*
|
|
2110
|
-
* Docs: https://developers.line.biz/en/reference/line-login/#issue-access-token
|
|
2111
|
-
*/
|
|
2112
|
-
const line = (options) => {
|
|
2113
|
-
const authorizationEndpoint = "https://access.line.me/oauth2/v2.1/authorize";
|
|
2114
|
-
const tokenEndpoint = "https://api.line.me/oauth2/v2.1/token";
|
|
2115
|
-
const userInfoEndpoint = "https://api.line.me/oauth2/v2.1/userinfo";
|
|
2116
|
-
const verifyIdTokenEndpoint = "https://api.line.me/oauth2/v2.1/verify";
|
|
2199
|
+
//#region src/social-providers/twitch.ts
|
|
2200
|
+
const twitch = (options) => {
|
|
2117
2201
|
return {
|
|
2118
|
-
id: "
|
|
2119
|
-
name: "
|
|
2120
|
-
|
|
2121
|
-
const _scopes = options.disableDefaultScope ? [] : [
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
scopes && _scopes.push(...scopes);
|
|
2128
|
-
return await require_oauth2.createAuthorizationURL({
|
|
2129
|
-
id: "line",
|
|
2202
|
+
id: "twitch",
|
|
2203
|
+
name: "Twitch",
|
|
2204
|
+
createAuthorizationURL({ state, scopes, redirectURI }) {
|
|
2205
|
+
const _scopes = options.disableDefaultScope ? [] : ["user:read:email", "openid"];
|
|
2206
|
+
if (options.scope) _scopes.push(...options.scope);
|
|
2207
|
+
if (scopes) _scopes.push(...scopes);
|
|
2208
|
+
return require_oauth2.createAuthorizationURL({
|
|
2209
|
+
id: "twitch",
|
|
2210
|
+
redirectURI,
|
|
2130
2211
|
options,
|
|
2131
|
-
authorizationEndpoint,
|
|
2212
|
+
authorizationEndpoint: "https://id.twitch.tv/oauth2/authorize",
|
|
2132
2213
|
scopes: _scopes,
|
|
2133
2214
|
state,
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2215
|
+
claims: options.claims || [
|
|
2216
|
+
"email",
|
|
2217
|
+
"email_verified",
|
|
2218
|
+
"preferred_username",
|
|
2219
|
+
"picture"
|
|
2220
|
+
]
|
|
2137
2221
|
});
|
|
2138
2222
|
},
|
|
2139
|
-
validateAuthorizationCode: async ({ code,
|
|
2223
|
+
validateAuthorizationCode: async ({ code, redirectURI }) => {
|
|
2140
2224
|
return require_oauth2.validateAuthorizationCode({
|
|
2141
2225
|
code,
|
|
2142
|
-
codeVerifier,
|
|
2143
2226
|
redirectURI,
|
|
2144
2227
|
options,
|
|
2145
|
-
tokenEndpoint
|
|
2228
|
+
tokenEndpoint: "https://id.twitch.tv/oauth2/token"
|
|
2146
2229
|
});
|
|
2147
2230
|
},
|
|
2148
2231
|
refreshAccessToken: options.refreshAccessToken ? options.refreshAccessToken : async (refreshToken) => {
|
|
@@ -2150,50 +2233,28 @@ const line = (options) => {
|
|
|
2150
2233
|
refreshToken,
|
|
2151
2234
|
options: {
|
|
2152
2235
|
clientId: options.clientId,
|
|
2236
|
+
clientKey: options.clientKey,
|
|
2153
2237
|
clientSecret: options.clientSecret
|
|
2154
2238
|
},
|
|
2155
|
-
tokenEndpoint
|
|
2239
|
+
tokenEndpoint: "https://id.twitch.tv/oauth2/token"
|
|
2156
2240
|
});
|
|
2157
2241
|
},
|
|
2158
|
-
async verifyIdToken(token, nonce) {
|
|
2159
|
-
if (options.disableIdTokenSignIn) return false;
|
|
2160
|
-
if (options.verifyIdToken) return options.verifyIdToken(token, nonce);
|
|
2161
|
-
const body = new URLSearchParams();
|
|
2162
|
-
body.set("id_token", token);
|
|
2163
|
-
body.set("client_id", options.clientId);
|
|
2164
|
-
if (nonce) body.set("nonce", nonce);
|
|
2165
|
-
const { data, error } = await (0, __better_fetch_fetch.betterFetch)(verifyIdTokenEndpoint, {
|
|
2166
|
-
method: "POST",
|
|
2167
|
-
headers: { "content-type": "application/x-www-form-urlencoded" },
|
|
2168
|
-
body
|
|
2169
|
-
});
|
|
2170
|
-
if (error || !data) return false;
|
|
2171
|
-
if (data.aud !== options.clientId) return false;
|
|
2172
|
-
if (nonce && data.nonce && data.nonce !== nonce) return false;
|
|
2173
|
-
return true;
|
|
2174
|
-
},
|
|
2175
2242
|
async getUserInfo(token) {
|
|
2176
2243
|
if (options.getUserInfo) return options.getUserInfo(token);
|
|
2177
|
-
|
|
2178
|
-
if (
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
if (!profile) {
|
|
2182
|
-
const { data } = await (0, __better_fetch_fetch.betterFetch)(userInfoEndpoint, { headers: { authorization: `Bearer ${token.accessToken}` } });
|
|
2183
|
-
profile = data || null;
|
|
2244
|
+
const idToken = token.idToken;
|
|
2245
|
+
if (!idToken) {
|
|
2246
|
+
require_env.logger.error("No idToken found in token");
|
|
2247
|
+
return null;
|
|
2184
2248
|
}
|
|
2185
|
-
|
|
2249
|
+
const profile = (0, jose.decodeJwt)(idToken);
|
|
2186
2250
|
const userMap = await options.mapProfileToUser?.(profile);
|
|
2187
|
-
const id = profile.sub || profile.userId;
|
|
2188
|
-
const name = profile.name || profile.displayName;
|
|
2189
|
-
const image = profile.picture || profile.pictureUrl || void 0;
|
|
2190
2251
|
return {
|
|
2191
2252
|
user: {
|
|
2192
|
-
id,
|
|
2193
|
-
name,
|
|
2253
|
+
id: profile.sub,
|
|
2254
|
+
name: profile.preferred_username,
|
|
2194
2255
|
email: profile.email,
|
|
2195
|
-
image,
|
|
2196
|
-
emailVerified:
|
|
2256
|
+
image: profile.picture,
|
|
2257
|
+
emailVerified: profile.email_verified,
|
|
2197
2258
|
...userMap
|
|
2198
2259
|
},
|
|
2199
2260
|
data: profile
|
|
@@ -2204,202 +2265,214 @@ const line = (options) => {
|
|
|
2204
2265
|
};
|
|
2205
2266
|
|
|
2206
2267
|
//#endregion
|
|
2207
|
-
//#region src/social-providers/
|
|
2208
|
-
const
|
|
2209
|
-
const isSandbox = (options.environment || "sandbox") === "sandbox";
|
|
2210
|
-
const authorizationEndpoint = isSandbox ? "https://www.sandbox.paypal.com/signin/authorize" : "https://www.paypal.com/signin/authorize";
|
|
2211
|
-
const tokenEndpoint = isSandbox ? "https://api-m.sandbox.paypal.com/v1/oauth2/token" : "https://api-m.paypal.com/v1/oauth2/token";
|
|
2212
|
-
const userInfoEndpoint = isSandbox ? "https://api-m.sandbox.paypal.com/v1/identity/oauth2/userinfo" : "https://api-m.paypal.com/v1/identity/oauth2/userinfo";
|
|
2268
|
+
//#region src/social-providers/twitter.ts
|
|
2269
|
+
const twitter = (options) => {
|
|
2213
2270
|
return {
|
|
2214
|
-
id: "
|
|
2215
|
-
name: "
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2271
|
+
id: "twitter",
|
|
2272
|
+
name: "Twitter",
|
|
2273
|
+
createAuthorizationURL(data) {
|
|
2274
|
+
const _scopes = options.disableDefaultScope ? [] : [
|
|
2275
|
+
"users.read",
|
|
2276
|
+
"tweet.read",
|
|
2277
|
+
"offline.access",
|
|
2278
|
+
"users.email"
|
|
2279
|
+
];
|
|
2280
|
+
if (options.scope) _scopes.push(...options.scope);
|
|
2281
|
+
if (data.scopes) _scopes.push(...data.scopes);
|
|
2282
|
+
return require_oauth2.createAuthorizationURL({
|
|
2283
|
+
id: "twitter",
|
|
2223
2284
|
options,
|
|
2224
|
-
authorizationEndpoint,
|
|
2225
|
-
scopes:
|
|
2226
|
-
state,
|
|
2285
|
+
authorizationEndpoint: "https://x.com/i/oauth2/authorize",
|
|
2286
|
+
scopes: _scopes,
|
|
2287
|
+
state: data.state,
|
|
2288
|
+
codeVerifier: data.codeVerifier,
|
|
2289
|
+
redirectURI: data.redirectURI
|
|
2290
|
+
});
|
|
2291
|
+
},
|
|
2292
|
+
validateAuthorizationCode: async ({ code, codeVerifier, redirectURI }) => {
|
|
2293
|
+
return require_oauth2.validateAuthorizationCode({
|
|
2294
|
+
code,
|
|
2227
2295
|
codeVerifier,
|
|
2296
|
+
authentication: "basic",
|
|
2228
2297
|
redirectURI,
|
|
2229
|
-
|
|
2298
|
+
options,
|
|
2299
|
+
tokenEndpoint: "https://api.x.com/2/oauth2/token"
|
|
2230
2300
|
});
|
|
2231
2301
|
},
|
|
2232
|
-
validateAuthorizationCode: async ({ code, redirectURI }) => {
|
|
2233
|
-
/**
|
|
2234
|
-
* PayPal requires Basic Auth for token exchange
|
|
2235
|
-
**/
|
|
2236
|
-
const credentials = __better_auth_utils_base64.base64.encode(`${options.clientId}:${options.clientSecret}`);
|
|
2237
|
-
try {
|
|
2238
|
-
const response = await (0, __better_fetch_fetch.betterFetch)(tokenEndpoint, {
|
|
2239
|
-
method: "POST",
|
|
2240
|
-
headers: {
|
|
2241
|
-
Authorization: `Basic ${credentials}`,
|
|
2242
|
-
Accept: "application/json",
|
|
2243
|
-
"Accept-Language": "en_US",
|
|
2244
|
-
"Content-Type": "application/x-www-form-urlencoded"
|
|
2245
|
-
},
|
|
2246
|
-
body: new URLSearchParams({
|
|
2247
|
-
grant_type: "authorization_code",
|
|
2248
|
-
code,
|
|
2249
|
-
redirect_uri: redirectURI
|
|
2250
|
-
}).toString()
|
|
2251
|
-
});
|
|
2252
|
-
if (!response.data) throw new require_error.BetterAuthError("FAILED_TO_GET_ACCESS_TOKEN");
|
|
2253
|
-
const data = response.data;
|
|
2254
|
-
return {
|
|
2255
|
-
accessToken: data.access_token,
|
|
2256
|
-
refreshToken: data.refresh_token,
|
|
2257
|
-
accessTokenExpiresAt: data.expires_in ? new Date(Date.now() + data.expires_in * 1e3) : void 0,
|
|
2258
|
-
idToken: data.id_token
|
|
2259
|
-
};
|
|
2260
|
-
} catch (error) {
|
|
2261
|
-
require_env.logger.error("PayPal token exchange failed:", error);
|
|
2262
|
-
throw new require_error.BetterAuthError("FAILED_TO_GET_ACCESS_TOKEN");
|
|
2263
|
-
}
|
|
2264
|
-
},
|
|
2265
2302
|
refreshAccessToken: options.refreshAccessToken ? options.refreshAccessToken : async (refreshToken) => {
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
body: new URLSearchParams({
|
|
2277
|
-
grant_type: "refresh_token",
|
|
2278
|
-
refresh_token: refreshToken
|
|
2279
|
-
}).toString()
|
|
2280
|
-
});
|
|
2281
|
-
if (!response.data) throw new require_error.BetterAuthError("FAILED_TO_REFRESH_ACCESS_TOKEN");
|
|
2282
|
-
const data = response.data;
|
|
2283
|
-
return {
|
|
2284
|
-
accessToken: data.access_token,
|
|
2285
|
-
refreshToken: data.refresh_token,
|
|
2286
|
-
accessTokenExpiresAt: data.expires_in ? new Date(Date.now() + data.expires_in * 1e3) : void 0
|
|
2287
|
-
};
|
|
2288
|
-
} catch (error) {
|
|
2289
|
-
require_env.logger.error("PayPal token refresh failed:", error);
|
|
2290
|
-
throw new require_error.BetterAuthError("FAILED_TO_REFRESH_ACCESS_TOKEN");
|
|
2291
|
-
}
|
|
2292
|
-
},
|
|
2293
|
-
async verifyIdToken(token, nonce) {
|
|
2294
|
-
if (options.disableIdTokenSignIn) return false;
|
|
2295
|
-
if (options.verifyIdToken) return options.verifyIdToken(token, nonce);
|
|
2296
|
-
try {
|
|
2297
|
-
return !!(0, jose.decodeJwt)(token).sub;
|
|
2298
|
-
} catch (error) {
|
|
2299
|
-
require_env.logger.error("Failed to verify PayPal ID token:", error);
|
|
2300
|
-
return false;
|
|
2301
|
-
}
|
|
2303
|
+
return require_oauth2.refreshAccessToken({
|
|
2304
|
+
refreshToken,
|
|
2305
|
+
options: {
|
|
2306
|
+
clientId: options.clientId,
|
|
2307
|
+
clientKey: options.clientKey,
|
|
2308
|
+
clientSecret: options.clientSecret
|
|
2309
|
+
},
|
|
2310
|
+
authentication: "basic",
|
|
2311
|
+
tokenEndpoint: "https://api.x.com/2/oauth2/token"
|
|
2312
|
+
});
|
|
2302
2313
|
},
|
|
2303
2314
|
async getUserInfo(token) {
|
|
2304
2315
|
if (options.getUserInfo) return options.getUserInfo(token);
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
}
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
const userInfo = response.data;
|
|
2319
|
-
const userMap = await options.mapProfileToUser?.(userInfo);
|
|
2320
|
-
return {
|
|
2321
|
-
user: {
|
|
2322
|
-
id: userInfo.user_id,
|
|
2323
|
-
name: userInfo.name,
|
|
2324
|
-
email: userInfo.email,
|
|
2325
|
-
image: userInfo.picture,
|
|
2326
|
-
emailVerified: userInfo.email_verified,
|
|
2327
|
-
...userMap
|
|
2328
|
-
},
|
|
2329
|
-
data: userInfo
|
|
2330
|
-
};
|
|
2331
|
-
} catch (error) {
|
|
2332
|
-
require_env.logger.error("Failed to fetch user info from PayPal:", error);
|
|
2333
|
-
return null;
|
|
2316
|
+
const { data: profile, error: profileError } = await (0, __better_fetch_fetch.betterFetch)("https://api.x.com/2/users/me?user.fields=profile_image_url", {
|
|
2317
|
+
method: "GET",
|
|
2318
|
+
headers: { Authorization: `Bearer ${token.accessToken}` }
|
|
2319
|
+
});
|
|
2320
|
+
if (profileError) return null;
|
|
2321
|
+
const { data: emailData, error: emailError } = await (0, __better_fetch_fetch.betterFetch)("https://api.x.com/2/users/me?user.fields=confirmed_email", {
|
|
2322
|
+
method: "GET",
|
|
2323
|
+
headers: { Authorization: `Bearer ${token.accessToken}` }
|
|
2324
|
+
});
|
|
2325
|
+
let emailVerified = false;
|
|
2326
|
+
if (!emailError && emailData?.data?.confirmed_email) {
|
|
2327
|
+
profile.data.email = emailData.data.confirmed_email;
|
|
2328
|
+
emailVerified = true;
|
|
2334
2329
|
}
|
|
2330
|
+
const userMap = await options.mapProfileToUser?.(profile);
|
|
2331
|
+
return {
|
|
2332
|
+
user: {
|
|
2333
|
+
id: profile.data.id,
|
|
2334
|
+
name: profile.data.name,
|
|
2335
|
+
email: profile.data.email || profile.data.username || null,
|
|
2336
|
+
image: profile.data.profile_image_url,
|
|
2337
|
+
emailVerified,
|
|
2338
|
+
...userMap
|
|
2339
|
+
},
|
|
2340
|
+
data: profile
|
|
2341
|
+
};
|
|
2335
2342
|
},
|
|
2336
2343
|
options
|
|
2337
2344
|
};
|
|
2338
2345
|
};
|
|
2339
2346
|
|
|
2340
2347
|
//#endregion
|
|
2341
|
-
//#region src/social-providers/
|
|
2342
|
-
const
|
|
2348
|
+
//#region src/social-providers/vk.ts
|
|
2349
|
+
const vk = (options) => {
|
|
2343
2350
|
return {
|
|
2344
|
-
id: "
|
|
2345
|
-
name: "
|
|
2346
|
-
createAuthorizationURL({ state, scopes, codeVerifier, redirectURI }) {
|
|
2347
|
-
const _scopes = options.disableDefaultScope ? [] : [
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
options.scope && _scopes.push(...options.scope);
|
|
2353
|
-
scopes && _scopes.push(...scopes);
|
|
2354
|
-
return (0, __better_auth_core_oauth2.createAuthorizationURL)({
|
|
2355
|
-
id: "polar",
|
|
2351
|
+
id: "vk",
|
|
2352
|
+
name: "VK",
|
|
2353
|
+
async createAuthorizationURL({ state, scopes, codeVerifier, redirectURI }) {
|
|
2354
|
+
const _scopes = options.disableDefaultScope ? [] : ["email", "phone"];
|
|
2355
|
+
if (options.scope) _scopes.push(...options.scope);
|
|
2356
|
+
if (scopes) _scopes.push(...scopes);
|
|
2357
|
+
return require_oauth2.createAuthorizationURL({
|
|
2358
|
+
id: "vk",
|
|
2356
2359
|
options,
|
|
2357
|
-
authorizationEndpoint: "https://
|
|
2360
|
+
authorizationEndpoint: "https://id.vk.com/authorize",
|
|
2358
2361
|
scopes: _scopes,
|
|
2359
2362
|
state,
|
|
2360
|
-
codeVerifier,
|
|
2361
2363
|
redirectURI,
|
|
2362
|
-
|
|
2364
|
+
codeVerifier
|
|
2363
2365
|
});
|
|
2364
2366
|
},
|
|
2365
|
-
validateAuthorizationCode: async ({ code, codeVerifier, redirectURI }) => {
|
|
2366
|
-
return
|
|
2367
|
+
validateAuthorizationCode: async ({ code, codeVerifier, redirectURI, deviceId }) => {
|
|
2368
|
+
return require_oauth2.validateAuthorizationCode({
|
|
2367
2369
|
code,
|
|
2368
2370
|
codeVerifier,
|
|
2369
|
-
redirectURI,
|
|
2371
|
+
redirectURI: options.redirectURI || redirectURI,
|
|
2370
2372
|
options,
|
|
2371
|
-
|
|
2373
|
+
deviceId,
|
|
2374
|
+
tokenEndpoint: "https://id.vk.com/oauth2/auth"
|
|
2372
2375
|
});
|
|
2373
2376
|
},
|
|
2374
2377
|
refreshAccessToken: options.refreshAccessToken ? options.refreshAccessToken : async (refreshToken) => {
|
|
2375
|
-
return
|
|
2378
|
+
return require_oauth2.refreshAccessToken({
|
|
2376
2379
|
refreshToken,
|
|
2377
2380
|
options: {
|
|
2378
2381
|
clientId: options.clientId,
|
|
2379
2382
|
clientKey: options.clientKey,
|
|
2380
2383
|
clientSecret: options.clientSecret
|
|
2381
2384
|
},
|
|
2382
|
-
tokenEndpoint: "https://
|
|
2385
|
+
tokenEndpoint: "https://id.vk.com/oauth2/auth"
|
|
2386
|
+
});
|
|
2387
|
+
},
|
|
2388
|
+
async getUserInfo(data) {
|
|
2389
|
+
if (options.getUserInfo) return options.getUserInfo(data);
|
|
2390
|
+
if (!data.accessToken) return null;
|
|
2391
|
+
const formBody = new URLSearchParams({
|
|
2392
|
+
access_token: data.accessToken,
|
|
2393
|
+
client_id: options.clientId
|
|
2394
|
+
}).toString();
|
|
2395
|
+
const { data: profile, error } = await (0, __better_fetch_fetch.betterFetch)("https://id.vk.com/oauth2/user_info", {
|
|
2396
|
+
method: "POST",
|
|
2397
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
2398
|
+
body: formBody
|
|
2399
|
+
});
|
|
2400
|
+
if (error) return null;
|
|
2401
|
+
if (!profile.user.email) return null;
|
|
2402
|
+
const userMap = await options.mapProfileToUser?.(profile);
|
|
2403
|
+
return {
|
|
2404
|
+
user: {
|
|
2405
|
+
id: profile.user.user_id,
|
|
2406
|
+
first_name: profile.user.first_name,
|
|
2407
|
+
last_name: profile.user.last_name,
|
|
2408
|
+
email: profile.user.email,
|
|
2409
|
+
image: profile.user.avatar,
|
|
2410
|
+
emailVerified: !!profile.user.email,
|
|
2411
|
+
birthday: profile.user.birthday,
|
|
2412
|
+
sex: profile.user.sex,
|
|
2413
|
+
name: `${profile.user.first_name} ${profile.user.last_name}`,
|
|
2414
|
+
...userMap
|
|
2415
|
+
},
|
|
2416
|
+
data: profile
|
|
2417
|
+
};
|
|
2418
|
+
},
|
|
2419
|
+
options
|
|
2420
|
+
};
|
|
2421
|
+
};
|
|
2422
|
+
|
|
2423
|
+
//#endregion
|
|
2424
|
+
//#region src/social-providers/zoom.ts
|
|
2425
|
+
const zoom = (userOptions) => {
|
|
2426
|
+
const options = {
|
|
2427
|
+
pkce: true,
|
|
2428
|
+
...userOptions
|
|
2429
|
+
};
|
|
2430
|
+
return {
|
|
2431
|
+
id: "zoom",
|
|
2432
|
+
name: "Zoom",
|
|
2433
|
+
createAuthorizationURL: async ({ state, redirectURI, codeVerifier }) => {
|
|
2434
|
+
const params = new URLSearchParams({
|
|
2435
|
+
response_type: "code",
|
|
2436
|
+
redirect_uri: options.redirectURI ? options.redirectURI : redirectURI,
|
|
2437
|
+
client_id: options.clientId,
|
|
2438
|
+
state
|
|
2439
|
+
});
|
|
2440
|
+
if (options.pkce) {
|
|
2441
|
+
const codeChallenge = await require_oauth2.generateCodeChallenge(codeVerifier);
|
|
2442
|
+
params.set("code_challenge_method", "S256");
|
|
2443
|
+
params.set("code_challenge", codeChallenge);
|
|
2444
|
+
}
|
|
2445
|
+
const url = new URL("https://zoom.us/oauth/authorize");
|
|
2446
|
+
url.search = params.toString();
|
|
2447
|
+
return url;
|
|
2448
|
+
},
|
|
2449
|
+
validateAuthorizationCode: async ({ code, redirectURI, codeVerifier }) => {
|
|
2450
|
+
return require_oauth2.validateAuthorizationCode({
|
|
2451
|
+
code,
|
|
2452
|
+
redirectURI: options.redirectURI || redirectURI,
|
|
2453
|
+
codeVerifier,
|
|
2454
|
+
options,
|
|
2455
|
+
tokenEndpoint: "https://zoom.us/oauth/token",
|
|
2456
|
+
authentication: "post"
|
|
2383
2457
|
});
|
|
2384
2458
|
},
|
|
2385
2459
|
async getUserInfo(token) {
|
|
2386
2460
|
if (options.getUserInfo) return options.getUserInfo(token);
|
|
2387
|
-
const { data: profile, error } = await (0, __better_fetch_fetch.betterFetch)("https://api.
|
|
2461
|
+
const { data: profile, error } = await (0, __better_fetch_fetch.betterFetch)("https://api.zoom.us/v2/users/me", { headers: { authorization: `Bearer ${token.accessToken}` } });
|
|
2388
2462
|
if (error) return null;
|
|
2389
2463
|
const userMap = await options.mapProfileToUser?.(profile);
|
|
2390
2464
|
return {
|
|
2391
2465
|
user: {
|
|
2392
2466
|
id: profile.id,
|
|
2393
|
-
name: profile.
|
|
2467
|
+
name: profile.display_name,
|
|
2468
|
+
image: profile.pic_url,
|
|
2394
2469
|
email: profile.email,
|
|
2395
|
-
|
|
2396
|
-
emailVerified: true,
|
|
2470
|
+
emailVerified: Boolean(profile.verified),
|
|
2397
2471
|
...userMap
|
|
2398
2472
|
},
|
|
2399
|
-
data: profile
|
|
2473
|
+
data: { ...profile }
|
|
2400
2474
|
};
|
|
2401
|
-
}
|
|
2402
|
-
options
|
|
2475
|
+
}
|
|
2403
2476
|
};
|
|
2404
2477
|
};
|
|
2405
2478
|
|
|
@@ -2435,6 +2508,7 @@ const socialProviders = {
|
|
|
2435
2508
|
kakao,
|
|
2436
2509
|
naver,
|
|
2437
2510
|
line,
|
|
2511
|
+
paybin,
|
|
2438
2512
|
paypal,
|
|
2439
2513
|
polar
|
|
2440
2514
|
};
|
|
@@ -2464,6 +2538,7 @@ exports.linkedin = linkedin;
|
|
|
2464
2538
|
exports.microsoft = microsoft;
|
|
2465
2539
|
exports.naver = naver;
|
|
2466
2540
|
exports.notion = notion;
|
|
2541
|
+
exports.paybin = paybin;
|
|
2467
2542
|
exports.paypal = paypal;
|
|
2468
2543
|
exports.polar = polar;
|
|
2469
2544
|
exports.reddit = reddit;
|