@better-auth/core 1.4.0-beta.13 → 1.4.0-beta.14

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