@better-auth/core 1.4.12-beta.2 → 1.4.13

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 (185) hide show
  1. package/.turbo/turbo-build.log +172 -35
  2. package/dist/api/index.d.mts +178 -1
  3. package/dist/api/index.mjs +2 -1
  4. package/dist/context/endpoint-context.d.mts +19 -0
  5. package/dist/context/endpoint-context.mjs +31 -0
  6. package/dist/context/global.d.mts +7 -0
  7. package/dist/context/global.mjs +37 -0
  8. package/dist/context/index.d.mts +5 -53
  9. package/dist/context/index.mjs +5 -2
  10. package/dist/context/request-state.d.mts +27 -0
  11. package/dist/context/request-state.mjs +49 -0
  12. package/dist/context/transaction.d.mts +16 -0
  13. package/dist/context/transaction.mjs +52 -0
  14. package/dist/db/adapter/factory.d.mts +27 -0
  15. package/dist/db/adapter/factory.mjs +738 -0
  16. package/dist/db/adapter/get-default-field-name.d.mts +18 -0
  17. package/dist/db/adapter/get-default-field-name.mjs +38 -0
  18. package/dist/db/adapter/get-default-model-name.d.mts +12 -0
  19. package/dist/db/adapter/get-default-model-name.mjs +32 -0
  20. package/dist/db/adapter/get-field-attributes.d.mts +29 -0
  21. package/dist/db/adapter/get-field-attributes.mjs +39 -0
  22. package/dist/db/adapter/get-field-name.d.mts +18 -0
  23. package/dist/db/adapter/get-field-name.mjs +33 -0
  24. package/dist/db/adapter/get-id-field.d.mts +39 -0
  25. package/dist/db/adapter/get-id-field.mjs +68 -0
  26. package/dist/db/adapter/get-model-name.d.mts +12 -0
  27. package/dist/db/adapter/get-model-name.mjs +23 -0
  28. package/dist/db/adapter/index.d.mts +513 -1
  29. package/dist/db/adapter/index.mjs +8 -970
  30. package/dist/db/adapter/types.d.mts +139 -0
  31. package/dist/db/adapter/utils.d.mts +7 -0
  32. package/dist/db/adapter/utils.mjs +38 -0
  33. package/dist/db/get-tables.d.mts +8 -0
  34. package/dist/{get-tables-CMc_Emww.mjs → db/get-tables.mjs} +1 -1
  35. package/dist/db/index.d.mts +10 -2
  36. package/dist/db/index.mjs +7 -60
  37. package/dist/db/plugin.d.mts +12 -0
  38. package/dist/db/schema/account.d.mts +26 -0
  39. package/dist/db/schema/account.mjs +19 -0
  40. package/dist/db/schema/rate-limit.d.mts +14 -0
  41. package/dist/db/schema/rate-limit.mjs +11 -0
  42. package/dist/db/schema/session.d.mts +21 -0
  43. package/dist/db/schema/session.mjs +14 -0
  44. package/dist/db/schema/shared.d.mts +10 -0
  45. package/dist/db/schema/shared.mjs +11 -0
  46. package/dist/db/schema/user.d.mts +20 -0
  47. package/dist/db/schema/user.mjs +13 -0
  48. package/dist/db/schema/verification.d.mts +19 -0
  49. package/dist/db/schema/verification.mjs +12 -0
  50. package/dist/db/type.d.mts +143 -0
  51. package/dist/env/color-depth.d.mts +4 -0
  52. package/dist/env/color-depth.mjs +88 -0
  53. package/dist/env/env-impl.d.mts +32 -0
  54. package/dist/env/env-impl.mjs +82 -0
  55. package/dist/env/index.d.mts +4 -2
  56. package/dist/env/index.mjs +3 -1
  57. package/dist/{index-BRBu0-5h.d.mts → env/logger.d.mts} +1 -35
  58. package/dist/env/logger.mjs +81 -0
  59. package/dist/error/codes.d.mts +48 -0
  60. package/dist/{error-DP1xOn7P.mjs → error/codes.mjs} +3 -14
  61. package/dist/error/index.d.mts +5 -48
  62. package/dist/error/index.mjs +12 -3
  63. package/dist/index.d.mts +8 -2
  64. package/dist/oauth2/client-credentials-token.d.mts +36 -0
  65. package/dist/oauth2/client-credentials-token.mjs +54 -0
  66. package/dist/oauth2/create-authorization-url.d.mts +45 -0
  67. package/dist/oauth2/create-authorization-url.mjs +42 -0
  68. package/dist/oauth2/index.d.mts +8 -2
  69. package/dist/oauth2/index.mjs +6 -2
  70. package/dist/oauth2/oauth-provider.d.mts +194 -0
  71. package/dist/oauth2/refresh-access-token.d.mts +36 -0
  72. package/dist/oauth2/refresh-access-token.mjs +58 -0
  73. package/dist/oauth2/utils.d.mts +7 -0
  74. package/dist/oauth2/utils.mjs +27 -0
  75. package/dist/oauth2/validate-authorization-code.d.mts +55 -0
  76. package/dist/oauth2/validate-authorization-code.mjs +71 -0
  77. package/dist/oauth2/verify.d.mts +49 -0
  78. package/dist/oauth2/verify.mjs +95 -0
  79. package/dist/social-providers/apple.d.mts +119 -0
  80. package/dist/social-providers/apple.mjs +102 -0
  81. package/dist/social-providers/atlassian.d.mts +72 -0
  82. package/dist/social-providers/atlassian.mjs +83 -0
  83. package/dist/social-providers/cognito.d.mts +87 -0
  84. package/dist/social-providers/cognito.mjs +166 -0
  85. package/dist/social-providers/discord.d.mts +126 -0
  86. package/dist/social-providers/discord.mjs +64 -0
  87. package/dist/social-providers/dropbox.d.mts +71 -0
  88. package/dist/social-providers/dropbox.mjs +75 -0
  89. package/dist/social-providers/facebook.d.mts +81 -0
  90. package/dist/social-providers/facebook.mjs +120 -0
  91. package/dist/social-providers/figma.d.mts +63 -0
  92. package/dist/social-providers/figma.mjs +84 -0
  93. package/dist/social-providers/github.d.mts +104 -0
  94. package/dist/social-providers/github.mjs +80 -0
  95. package/dist/social-providers/gitlab.d.mts +125 -0
  96. package/dist/social-providers/gitlab.mjs +82 -0
  97. package/dist/social-providers/google.d.mts +99 -0
  98. package/dist/social-providers/google.mjs +109 -0
  99. package/dist/social-providers/huggingface.d.mts +85 -0
  100. package/dist/social-providers/huggingface.mjs +75 -0
  101. package/dist/social-providers/index.d.mts +1723 -1
  102. package/dist/social-providers/index.mjs +33 -2570
  103. package/dist/social-providers/kakao.d.mts +163 -0
  104. package/dist/social-providers/kakao.mjs +72 -0
  105. package/dist/social-providers/kick.d.mts +75 -0
  106. package/dist/social-providers/kick.mjs +71 -0
  107. package/dist/social-providers/line.d.mts +107 -0
  108. package/dist/social-providers/line.mjs +113 -0
  109. package/dist/social-providers/linear.d.mts +70 -0
  110. package/dist/social-providers/linear.mjs +88 -0
  111. package/dist/social-providers/linkedin.d.mts +69 -0
  112. package/dist/social-providers/linkedin.mjs +76 -0
  113. package/dist/social-providers/microsoft-entra-id.d.mts +174 -0
  114. package/dist/social-providers/microsoft-entra-id.mjs +106 -0
  115. package/dist/social-providers/naver.d.mts +104 -0
  116. package/dist/social-providers/naver.mjs +67 -0
  117. package/dist/social-providers/notion.d.mts +66 -0
  118. package/dist/social-providers/notion.mjs +75 -0
  119. package/dist/social-providers/paybin.d.mts +73 -0
  120. package/dist/social-providers/paybin.mjs +85 -0
  121. package/dist/social-providers/paypal.d.mts +131 -0
  122. package/dist/social-providers/paypal.mjs +144 -0
  123. package/dist/social-providers/polar.d.mts +76 -0
  124. package/dist/social-providers/polar.mjs +73 -0
  125. package/dist/social-providers/reddit.d.mts +64 -0
  126. package/dist/social-providers/reddit.mjs +83 -0
  127. package/dist/social-providers/roblox.d.mts +72 -0
  128. package/dist/social-providers/roblox.mjs +59 -0
  129. package/dist/social-providers/salesforce.d.mts +81 -0
  130. package/dist/social-providers/salesforce.mjs +91 -0
  131. package/dist/social-providers/slack.d.mts +85 -0
  132. package/dist/social-providers/slack.mjs +68 -0
  133. package/dist/social-providers/spotify.d.mts +65 -0
  134. package/dist/social-providers/spotify.mjs +71 -0
  135. package/dist/social-providers/tiktok.d.mts +171 -0
  136. package/dist/social-providers/tiktok.mjs +62 -0
  137. package/dist/social-providers/twitch.d.mts +81 -0
  138. package/dist/social-providers/twitch.mjs +78 -0
  139. package/dist/social-providers/twitter.d.mts +140 -0
  140. package/dist/social-providers/twitter.mjs +87 -0
  141. package/dist/social-providers/vercel.d.mts +64 -0
  142. package/dist/social-providers/vercel.mjs +61 -0
  143. package/dist/social-providers/vk.d.mts +72 -0
  144. package/dist/social-providers/vk.mjs +83 -0
  145. package/dist/social-providers/zoom.d.mts +173 -0
  146. package/dist/social-providers/zoom.mjs +72 -0
  147. package/dist/types/context.d.mts +215 -0
  148. package/dist/types/cookie.d.mts +15 -0
  149. package/dist/types/helper.d.mts +8 -0
  150. package/dist/types/index.d.mts +8 -0
  151. package/dist/types/init-options.d.mts +1266 -0
  152. package/dist/types/plugin-client.d.mts +103 -0
  153. package/dist/types/plugin.d.mts +121 -0
  154. package/dist/utils/deprecate.d.mts +10 -0
  155. package/dist/utils/deprecate.mjs +17 -0
  156. package/dist/utils/error-codes.d.mts +9 -0
  157. package/dist/utils/error-codes.mjs +7 -0
  158. package/dist/utils/id.d.mts +4 -0
  159. package/dist/utils/id.mjs +9 -0
  160. package/dist/utils/index.d.mts +5 -26
  161. package/dist/utils/index.mjs +5 -2
  162. package/dist/utils/json.d.mts +4 -0
  163. package/dist/utils/json.mjs +25 -0
  164. package/dist/utils/string.d.mts +4 -0
  165. package/dist/utils/string.mjs +7 -0
  166. package/package.json +1 -1
  167. package/src/context/endpoint-context.ts +7 -15
  168. package/src/context/global.ts +57 -0
  169. package/src/context/index.ts +1 -0
  170. package/src/context/request-state.ts +7 -12
  171. package/src/context/transaction.ts +7 -16
  172. package/src/db/adapter/factory.ts +13 -13
  173. package/src/db/adapter/get-default-model-name.ts +1 -1
  174. package/src/db/adapter/get-id-field.ts +2 -2
  175. package/src/error/index.ts +2 -3
  176. package/src/social-providers/gitlab.ts +1 -1
  177. package/src/types/context.ts +137 -131
  178. package/src/types/cookie.ts +6 -4
  179. package/src/types/index.ts +2 -1
  180. package/tsdown.config.ts +9 -0
  181. package/dist/context-BGZ8V6DD.mjs +0 -126
  182. package/dist/env-DbssmzoK.mjs +0 -245
  183. package/dist/index-zgYuzZ7O.d.mts +0 -8020
  184. package/dist/oauth2-COJkghlT.mjs +0 -326
  185. package/dist/utils-U2L7n92V.mjs +0 -59
@@ -0,0 +1,119 @@
1
+ import { OAuth2Tokens, ProviderOptions } from "../oauth2/oauth-provider.mjs";
2
+ import "../oauth2/index.mjs";
3
+
4
+ //#region src/social-providers/apple.d.ts
5
+ interface AppleProfile {
6
+ /**
7
+ * The subject registered claim identifies the principal that’s the subject
8
+ * of the identity token. Because this token is for your app, the value is
9
+ * the unique identifier for the user.
10
+ */
11
+ sub: string;
12
+ /**
13
+ * A String value representing the user's email address.
14
+ * The email address is either the user's real email address or the proxy
15
+ * address, depending on their status private email relay service.
16
+ */
17
+ email: string;
18
+ /**
19
+ * A string or Boolean value that indicates whether the service verifies
20
+ * the email. The value can either be a string ("true" or "false") or a
21
+ * Boolean (true or false). The system may not verify email addresses for
22
+ * Sign in with Apple at Work & School users, and this claim is "false" or
23
+ * false for those users.
24
+ */
25
+ email_verified: true | "true";
26
+ /**
27
+ * A string or Boolean value that indicates whether the email that the user
28
+ * shares is the proxy address. The value can either be a string ("true" or
29
+ * "false") or a Boolean (true or false).
30
+ */
31
+ is_private_email: boolean;
32
+ /**
33
+ * An Integer value that indicates whether the user appears to be a real
34
+ * person. Use the value of this claim to mitigate fraud. The possible
35
+ * values are: 0 (or Unsupported), 1 (or Unknown), 2 (or LikelyReal). For
36
+ * more information, see ASUserDetectionStatus. This claim is present only
37
+ * in iOS 14 and later, macOS 11 and later, watchOS 7 and later, tvOS 14
38
+ * and later. The claim isn’t present or supported for web-based apps.
39
+ */
40
+ real_user_status: number;
41
+ /**
42
+ * The user’s full name in the format provided during the authorization
43
+ * process.
44
+ */
45
+ name: string;
46
+ /**
47
+ * The URL to the user's profile picture.
48
+ */
49
+ picture: string;
50
+ user?: AppleNonConformUser | undefined;
51
+ }
52
+ /**
53
+ * This is the shape of the `user` query parameter that Apple sends the first
54
+ * time the user consents to the app.
55
+ * @see https://developer.apple.com/documentation/signinwithapplerestapi/request-an-authorization-to-the-sign-in-with-apple-server./
56
+ */
57
+ interface AppleNonConformUser {
58
+ name: {
59
+ firstName: string;
60
+ lastName: string;
61
+ };
62
+ email: string;
63
+ }
64
+ interface AppleOptions extends ProviderOptions<AppleProfile> {
65
+ clientId: string;
66
+ appBundleIdentifier?: string | undefined;
67
+ audience?: (string | string[]) | undefined;
68
+ }
69
+ declare const apple: (options: AppleOptions) => {
70
+ id: "apple";
71
+ name: string;
72
+ createAuthorizationURL({
73
+ state,
74
+ scopes,
75
+ redirectURI
76
+ }: {
77
+ state: string;
78
+ codeVerifier: string;
79
+ scopes?: string[] | undefined;
80
+ redirectURI: string;
81
+ display?: string | undefined;
82
+ loginHint?: string | undefined;
83
+ }): Promise<URL>;
84
+ validateAuthorizationCode: ({
85
+ code,
86
+ codeVerifier,
87
+ redirectURI
88
+ }: {
89
+ code: string;
90
+ redirectURI: string;
91
+ codeVerifier?: string | undefined;
92
+ deviceId?: string | undefined;
93
+ }) => Promise<OAuth2Tokens>;
94
+ verifyIdToken(token: string, nonce: string | undefined): Promise<boolean>;
95
+ refreshAccessToken: (refreshToken: string) => Promise<OAuth2Tokens>;
96
+ getUserInfo(token: OAuth2Tokens & {
97
+ user?: {
98
+ name?: {
99
+ firstName?: string;
100
+ lastName?: string;
101
+ };
102
+ email?: string;
103
+ } | undefined;
104
+ }): Promise<{
105
+ user: {
106
+ id: string;
107
+ name?: string;
108
+ email?: string | null;
109
+ image?: string;
110
+ emailVerified: boolean;
111
+ [key: string]: any;
112
+ };
113
+ data: any;
114
+ } | null>;
115
+ options: AppleOptions;
116
+ };
117
+ declare const getApplePublicKey: (kid: string) => Promise<Uint8Array<ArrayBufferLike> | CryptoKey>;
118
+ //#endregion
119
+ export { AppleNonConformUser, AppleOptions, AppleProfile, apple, getApplePublicKey };
@@ -0,0 +1,102 @@
1
+ import { createAuthorizationURL } from "../oauth2/create-authorization-url.mjs";
2
+ import { refreshAccessToken } from "../oauth2/refresh-access-token.mjs";
3
+ import { validateAuthorizationCode } from "../oauth2/validate-authorization-code.mjs";
4
+ import "../oauth2/index.mjs";
5
+ import { betterFetch } from "@better-fetch/fetch";
6
+ import { decodeJwt, decodeProtectedHeader, importJWK, jwtVerify } from "jose";
7
+ import { APIError } from "better-call";
8
+
9
+ //#region src/social-providers/apple.ts
10
+ const apple = (options) => {
11
+ const tokenEndpoint = "https://appleid.apple.com/auth/token";
12
+ return {
13
+ id: "apple",
14
+ name: "Apple",
15
+ async createAuthorizationURL({ state, scopes, redirectURI }) {
16
+ const _scope = options.disableDefaultScope ? [] : ["email", "name"];
17
+ if (options.scope) _scope.push(...options.scope);
18
+ if (scopes) _scope.push(...scopes);
19
+ return await createAuthorizationURL({
20
+ id: "apple",
21
+ options,
22
+ authorizationEndpoint: "https://appleid.apple.com/auth/authorize",
23
+ scopes: _scope,
24
+ state,
25
+ redirectURI,
26
+ responseMode: "form_post",
27
+ responseType: "code id_token"
28
+ });
29
+ },
30
+ validateAuthorizationCode: async ({ code, codeVerifier, redirectURI }) => {
31
+ return validateAuthorizationCode({
32
+ code,
33
+ codeVerifier,
34
+ redirectURI,
35
+ options,
36
+ tokenEndpoint
37
+ });
38
+ },
39
+ async verifyIdToken(token, nonce) {
40
+ if (options.disableIdTokenSignIn) return false;
41
+ if (options.verifyIdToken) return options.verifyIdToken(token, nonce);
42
+ const { kid, alg: jwtAlg } = decodeProtectedHeader(token);
43
+ if (!kid || !jwtAlg) return false;
44
+ const { payload: jwtClaims } = await jwtVerify(token, await getApplePublicKey(kid), {
45
+ algorithms: [jwtAlg],
46
+ issuer: "https://appleid.apple.com",
47
+ audience: options.audience && options.audience.length ? options.audience : options.appBundleIdentifier ? options.appBundleIdentifier : options.clientId,
48
+ maxTokenAge: "1h"
49
+ });
50
+ ["email_verified", "is_private_email"].forEach((field) => {
51
+ if (jwtClaims[field] !== void 0) jwtClaims[field] = Boolean(jwtClaims[field]);
52
+ });
53
+ if (nonce && jwtClaims.nonce !== nonce) return false;
54
+ return !!jwtClaims;
55
+ },
56
+ refreshAccessToken: options.refreshAccessToken ? options.refreshAccessToken : async (refreshToken) => {
57
+ return refreshAccessToken({
58
+ refreshToken,
59
+ options: {
60
+ clientId: options.clientId,
61
+ clientKey: options.clientKey,
62
+ clientSecret: options.clientSecret
63
+ },
64
+ tokenEndpoint: "https://appleid.apple.com/auth/token"
65
+ });
66
+ },
67
+ async getUserInfo(token) {
68
+ if (options.getUserInfo) return options.getUserInfo(token);
69
+ if (!token.idToken) return null;
70
+ const profile = decodeJwt(token.idToken);
71
+ if (!profile) return null;
72
+ const name = token.user ? `${token.user.name?.firstName} ${token.user.name?.lastName}` : profile.name || profile.email;
73
+ const emailVerified = typeof profile.email_verified === "boolean" ? profile.email_verified : profile.email_verified === "true";
74
+ const enrichedProfile = {
75
+ ...profile,
76
+ name
77
+ };
78
+ const userMap = await options.mapProfileToUser?.(enrichedProfile);
79
+ return {
80
+ user: {
81
+ id: profile.sub,
82
+ name: enrichedProfile.name,
83
+ emailVerified,
84
+ email: profile.email,
85
+ ...userMap
86
+ },
87
+ data: enrichedProfile
88
+ };
89
+ },
90
+ options
91
+ };
92
+ };
93
+ const getApplePublicKey = async (kid) => {
94
+ const { data } = await betterFetch(`https://appleid.apple.com/auth/keys`);
95
+ if (!data?.keys) throw new APIError("BAD_REQUEST", { message: "Keys not found" });
96
+ const jwk = data.keys.find((key) => key.kid === kid);
97
+ if (!jwk) throw new Error(`JWK with kid ${kid} not found`);
98
+ return await importJWK(jwk, jwk.alg);
99
+ };
100
+
101
+ //#endregion
102
+ export { apple, getApplePublicKey };
@@ -0,0 +1,72 @@
1
+ import { OAuth2Tokens, ProviderOptions } from "../oauth2/oauth-provider.mjs";
2
+ import "../oauth2/index.mjs";
3
+
4
+ //#region src/social-providers/atlassian.d.ts
5
+ interface AtlassianProfile {
6
+ account_type?: string | undefined;
7
+ account_id: string;
8
+ email?: string | undefined;
9
+ name: string;
10
+ picture?: string | undefined;
11
+ nickname?: string | undefined;
12
+ locale?: string | undefined;
13
+ extended_profile?: {
14
+ job_title?: string;
15
+ organization?: string;
16
+ department?: string;
17
+ location?: string;
18
+ } | undefined;
19
+ }
20
+ interface AtlassianOptions extends ProviderOptions<AtlassianProfile> {
21
+ clientId: string;
22
+ }
23
+ declare const atlassian: (options: AtlassianOptions) => {
24
+ id: "atlassian";
25
+ name: string;
26
+ createAuthorizationURL({
27
+ state,
28
+ scopes,
29
+ codeVerifier,
30
+ redirectURI
31
+ }: {
32
+ state: string;
33
+ codeVerifier: string;
34
+ scopes?: string[] | undefined;
35
+ redirectURI: string;
36
+ display?: string | undefined;
37
+ loginHint?: string | undefined;
38
+ }): Promise<URL>;
39
+ validateAuthorizationCode: ({
40
+ code,
41
+ codeVerifier,
42
+ redirectURI
43
+ }: {
44
+ code: string;
45
+ redirectURI: string;
46
+ codeVerifier?: string | undefined;
47
+ deviceId?: string | undefined;
48
+ }) => Promise<OAuth2Tokens>;
49
+ refreshAccessToken: (refreshToken: string) => Promise<OAuth2Tokens>;
50
+ getUserInfo(token: OAuth2Tokens & {
51
+ user?: {
52
+ name?: {
53
+ firstName?: string;
54
+ lastName?: string;
55
+ };
56
+ email?: string;
57
+ } | undefined;
58
+ }): Promise<{
59
+ user: {
60
+ id: string;
61
+ name?: string;
62
+ email?: string | null;
63
+ image?: string;
64
+ emailVerified: boolean;
65
+ [key: string]: any;
66
+ };
67
+ data: any;
68
+ } | null>;
69
+ options: AtlassianOptions;
70
+ };
71
+ //#endregion
72
+ export { AtlassianOptions, AtlassianProfile, atlassian };
@@ -0,0 +1,83 @@
1
+ import { logger } from "../env/logger.mjs";
2
+ import "../env/index.mjs";
3
+ import { BetterAuthError } from "../error/index.mjs";
4
+ import { createAuthorizationURL } from "../oauth2/create-authorization-url.mjs";
5
+ import { refreshAccessToken } from "../oauth2/refresh-access-token.mjs";
6
+ import { validateAuthorizationCode } from "../oauth2/validate-authorization-code.mjs";
7
+ import "../oauth2/index.mjs";
8
+ import { betterFetch } from "@better-fetch/fetch";
9
+
10
+ //#region src/social-providers/atlassian.ts
11
+ const atlassian = (options) => {
12
+ return {
13
+ id: "atlassian",
14
+ name: "Atlassian",
15
+ async createAuthorizationURL({ state, scopes, codeVerifier, redirectURI }) {
16
+ if (!options.clientId || !options.clientSecret) {
17
+ logger.error("Client Id and Secret are required for Atlassian");
18
+ throw new BetterAuthError("CLIENT_ID_AND_SECRET_REQUIRED");
19
+ }
20
+ if (!codeVerifier) throw new BetterAuthError("codeVerifier is required for Atlassian");
21
+ const _scopes = options.disableDefaultScope ? [] : ["read:jira-user", "offline_access"];
22
+ if (options.scope) _scopes.push(...options.scope);
23
+ if (scopes) _scopes.push(...scopes);
24
+ return createAuthorizationURL({
25
+ id: "atlassian",
26
+ options,
27
+ authorizationEndpoint: "https://auth.atlassian.com/authorize",
28
+ scopes: _scopes,
29
+ state,
30
+ codeVerifier,
31
+ redirectURI,
32
+ additionalParams: { audience: "api.atlassian.com" },
33
+ prompt: options.prompt
34
+ });
35
+ },
36
+ validateAuthorizationCode: async ({ code, codeVerifier, redirectURI }) => {
37
+ return validateAuthorizationCode({
38
+ code,
39
+ codeVerifier,
40
+ redirectURI,
41
+ options,
42
+ tokenEndpoint: "https://auth.atlassian.com/oauth/token"
43
+ });
44
+ },
45
+ refreshAccessToken: options.refreshAccessToken ? options.refreshAccessToken : async (refreshToken) => {
46
+ return refreshAccessToken({
47
+ refreshToken,
48
+ options: {
49
+ clientId: options.clientId,
50
+ clientSecret: options.clientSecret
51
+ },
52
+ tokenEndpoint: "https://auth.atlassian.com/oauth/token"
53
+ });
54
+ },
55
+ async getUserInfo(token) {
56
+ if (options.getUserInfo) return options.getUserInfo(token);
57
+ if (!token.accessToken) return null;
58
+ try {
59
+ const { data: profile } = await betterFetch("https://api.atlassian.com/me", { headers: { Authorization: `Bearer ${token.accessToken}` } });
60
+ if (!profile) return null;
61
+ const userMap = await options.mapProfileToUser?.(profile);
62
+ return {
63
+ user: {
64
+ id: profile.account_id,
65
+ name: profile.name,
66
+ email: profile.email,
67
+ image: profile.picture,
68
+ emailVerified: false,
69
+ ...userMap
70
+ },
71
+ data: profile
72
+ };
73
+ } catch (error) {
74
+ logger.error("Failed to fetch user info from Figma:", error);
75
+ return null;
76
+ }
77
+ },
78
+ options
79
+ };
80
+ };
81
+
82
+ //#endregion
83
+ export { atlassian };
@@ -0,0 +1,87 @@
1
+ import { OAuth2Tokens, ProviderOptions } from "../oauth2/oauth-provider.mjs";
2
+ import "../oauth2/index.mjs";
3
+
4
+ //#region src/social-providers/cognito.d.ts
5
+ interface CognitoProfile {
6
+ sub: string;
7
+ email: string;
8
+ email_verified: boolean;
9
+ name: string;
10
+ given_name?: string | undefined;
11
+ family_name?: string | undefined;
12
+ picture?: string | undefined;
13
+ username?: string | undefined;
14
+ locale?: string | undefined;
15
+ phone_number?: string | undefined;
16
+ phone_number_verified?: boolean | undefined;
17
+ aud: string;
18
+ iss: string;
19
+ exp: number;
20
+ iat: number;
21
+ [key: string]: any;
22
+ }
23
+ interface CognitoOptions extends ProviderOptions<CognitoProfile> {
24
+ clientId: string;
25
+ /**
26
+ * The Cognito domain (e.g., "your-app.auth.us-east-1.amazoncognito.com")
27
+ */
28
+ domain: string;
29
+ /**
30
+ * AWS region where User Pool is hosted (e.g., "us-east-1")
31
+ */
32
+ region: string;
33
+ userPoolId: string;
34
+ requireClientSecret?: boolean | undefined;
35
+ }
36
+ declare const cognito: (options: CognitoOptions) => {
37
+ id: "cognito";
38
+ name: string;
39
+ createAuthorizationURL({
40
+ state,
41
+ scopes,
42
+ codeVerifier,
43
+ redirectURI
44
+ }: {
45
+ state: string;
46
+ codeVerifier: string;
47
+ scopes?: string[] | undefined;
48
+ redirectURI: string;
49
+ display?: string | undefined;
50
+ loginHint?: string | undefined;
51
+ }): Promise<URL>;
52
+ validateAuthorizationCode: ({
53
+ code,
54
+ codeVerifier,
55
+ redirectURI
56
+ }: {
57
+ code: string;
58
+ redirectURI: string;
59
+ codeVerifier?: string | undefined;
60
+ deviceId?: string | undefined;
61
+ }) => Promise<OAuth2Tokens>;
62
+ refreshAccessToken: (refreshToken: string) => Promise<OAuth2Tokens>;
63
+ verifyIdToken(token: string, nonce: string | undefined): Promise<boolean>;
64
+ getUserInfo(token: OAuth2Tokens & {
65
+ user?: {
66
+ name?: {
67
+ firstName?: string;
68
+ lastName?: string;
69
+ };
70
+ email?: string;
71
+ } | undefined;
72
+ }): Promise<{
73
+ user: {
74
+ id: string;
75
+ name?: string;
76
+ email?: string | null;
77
+ image?: string;
78
+ emailVerified: boolean;
79
+ [key: string]: any;
80
+ };
81
+ data: any;
82
+ } | null>;
83
+ options: CognitoOptions;
84
+ };
85
+ declare const getCognitoPublicKey: (kid: string, region: string, userPoolId: string) => Promise<Uint8Array<ArrayBufferLike> | CryptoKey>;
86
+ //#endregion
87
+ export { CognitoOptions, CognitoProfile, cognito, getCognitoPublicKey };
@@ -0,0 +1,166 @@
1
+ import { logger } from "../env/logger.mjs";
2
+ import "../env/index.mjs";
3
+ import { BetterAuthError } from "../error/index.mjs";
4
+ import { createAuthorizationURL } from "../oauth2/create-authorization-url.mjs";
5
+ import { refreshAccessToken } from "../oauth2/refresh-access-token.mjs";
6
+ import { validateAuthorizationCode } from "../oauth2/validate-authorization-code.mjs";
7
+ import "../oauth2/index.mjs";
8
+ import { betterFetch } from "@better-fetch/fetch";
9
+ import { decodeJwt, decodeProtectedHeader, importJWK, jwtVerify } from "jose";
10
+ import { APIError } from "better-call";
11
+
12
+ //#region src/social-providers/cognito.ts
13
+ const cognito = (options) => {
14
+ if (!options.domain || !options.region || !options.userPoolId) {
15
+ logger.error("Domain, region and userPoolId are required for Amazon Cognito. Make sure to provide them in the options.");
16
+ throw new BetterAuthError("DOMAIN_AND_REGION_REQUIRED");
17
+ }
18
+ const cleanDomain = options.domain.replace(/^https?:\/\//, "");
19
+ const authorizationEndpoint = `https://${cleanDomain}/oauth2/authorize`;
20
+ const tokenEndpoint = `https://${cleanDomain}/oauth2/token`;
21
+ const userInfoEndpoint = `https://${cleanDomain}/oauth2/userinfo`;
22
+ return {
23
+ id: "cognito",
24
+ name: "Cognito",
25
+ async createAuthorizationURL({ state, scopes, codeVerifier, redirectURI }) {
26
+ if (!options.clientId) {
27
+ logger.error("ClientId is required for Amazon Cognito. Make sure to provide them in the options.");
28
+ throw new BetterAuthError("CLIENT_ID_AND_SECRET_REQUIRED");
29
+ }
30
+ if (options.requireClientSecret && !options.clientSecret) {
31
+ logger.error("Client Secret is required when requireClientSecret is true. Make sure to provide it in the options.");
32
+ throw new BetterAuthError("CLIENT_SECRET_REQUIRED");
33
+ }
34
+ const _scopes = options.disableDefaultScope ? [] : [
35
+ "openid",
36
+ "profile",
37
+ "email"
38
+ ];
39
+ if (options.scope) _scopes.push(...options.scope);
40
+ if (scopes) _scopes.push(...scopes);
41
+ const url = await createAuthorizationURL({
42
+ id: "cognito",
43
+ options: { ...options },
44
+ authorizationEndpoint,
45
+ scopes: _scopes,
46
+ state,
47
+ codeVerifier,
48
+ redirectURI,
49
+ prompt: options.prompt
50
+ });
51
+ const scopeValue = url.searchParams.get("scope");
52
+ if (scopeValue) {
53
+ url.searchParams.delete("scope");
54
+ const encodedScope = encodeURIComponent(scopeValue);
55
+ const urlString = url.toString();
56
+ const separator = urlString.includes("?") ? "&" : "?";
57
+ return new URL(`${urlString}${separator}scope=${encodedScope}`);
58
+ }
59
+ return url;
60
+ },
61
+ validateAuthorizationCode: async ({ code, codeVerifier, redirectURI }) => {
62
+ return validateAuthorizationCode({
63
+ code,
64
+ codeVerifier,
65
+ redirectURI,
66
+ options,
67
+ tokenEndpoint
68
+ });
69
+ },
70
+ refreshAccessToken: options.refreshAccessToken ? options.refreshAccessToken : async (refreshToken) => {
71
+ return refreshAccessToken({
72
+ refreshToken,
73
+ options: {
74
+ clientId: options.clientId,
75
+ clientKey: options.clientKey,
76
+ clientSecret: options.clientSecret
77
+ },
78
+ tokenEndpoint
79
+ });
80
+ },
81
+ async verifyIdToken(token, nonce) {
82
+ if (options.disableIdTokenSignIn) return false;
83
+ if (options.verifyIdToken) return options.verifyIdToken(token, nonce);
84
+ try {
85
+ const { kid, alg: jwtAlg } = decodeProtectedHeader(token);
86
+ if (!kid || !jwtAlg) return false;
87
+ const publicKey = await getCognitoPublicKey(kid, options.region, options.userPoolId);
88
+ const expectedIssuer = `https://cognito-idp.${options.region}.amazonaws.com/${options.userPoolId}`;
89
+ const { payload: jwtClaims } = await jwtVerify(token, publicKey, {
90
+ algorithms: [jwtAlg],
91
+ issuer: expectedIssuer,
92
+ audience: options.clientId,
93
+ maxTokenAge: "1h"
94
+ });
95
+ if (nonce && jwtClaims.nonce !== nonce) return false;
96
+ return true;
97
+ } catch (error) {
98
+ logger.error("Failed to verify ID token:", error);
99
+ return false;
100
+ }
101
+ },
102
+ async getUserInfo(token) {
103
+ if (options.getUserInfo) return options.getUserInfo(token);
104
+ if (token.idToken) try {
105
+ const profile = decodeJwt(token.idToken);
106
+ if (!profile) return null;
107
+ const name = profile.name || profile.given_name || profile.username || profile.email;
108
+ const enrichedProfile = {
109
+ ...profile,
110
+ name
111
+ };
112
+ const userMap = await options.mapProfileToUser?.(enrichedProfile);
113
+ return {
114
+ user: {
115
+ id: profile.sub,
116
+ name: enrichedProfile.name,
117
+ email: profile.email,
118
+ image: profile.picture,
119
+ emailVerified: profile.email_verified,
120
+ ...userMap
121
+ },
122
+ data: enrichedProfile
123
+ };
124
+ } catch (error) {
125
+ logger.error("Failed to decode ID token:", error);
126
+ }
127
+ if (token.accessToken) try {
128
+ const { data: userInfo } = await betterFetch(userInfoEndpoint, { headers: { Authorization: `Bearer ${token.accessToken}` } });
129
+ if (userInfo) {
130
+ const userMap = await options.mapProfileToUser?.(userInfo);
131
+ return {
132
+ user: {
133
+ id: userInfo.sub,
134
+ name: userInfo.name || userInfo.given_name || userInfo.username,
135
+ email: userInfo.email,
136
+ image: userInfo.picture,
137
+ emailVerified: userInfo.email_verified,
138
+ ...userMap
139
+ },
140
+ data: userInfo
141
+ };
142
+ }
143
+ } catch (error) {
144
+ logger.error("Failed to fetch user info from Cognito:", error);
145
+ }
146
+ return null;
147
+ },
148
+ options
149
+ };
150
+ };
151
+ const getCognitoPublicKey = async (kid, region, userPoolId) => {
152
+ const COGNITO_JWKS_URI = `https://cognito-idp.${region}.amazonaws.com/${userPoolId}/.well-known/jwks.json`;
153
+ try {
154
+ const { data } = await betterFetch(COGNITO_JWKS_URI);
155
+ if (!data?.keys) throw new APIError("BAD_REQUEST", { message: "Keys not found" });
156
+ const jwk = data.keys.find((key) => key.kid === kid);
157
+ if (!jwk) throw new Error(`JWK with kid ${kid} not found`);
158
+ return await importJWK(jwk, jwk.alg);
159
+ } catch (error) {
160
+ logger.error("Failed to fetch Cognito public key:", error);
161
+ throw error;
162
+ }
163
+ };
164
+
165
+ //#endregion
166
+ export { cognito, getCognitoPublicKey };