@better-auth/core 1.4.17 → 1.4.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +253 -176
- package/dist/api/index.d.mts +11 -5
- package/dist/api/index.mjs +2 -1
- package/dist/api/index.mjs.map +1 -0
- package/dist/async_hooks/index.d.mts +2 -1
- package/dist/async_hooks/index.mjs +2 -1
- package/dist/async_hooks/index.mjs.map +1 -0
- package/dist/async_hooks/pure.index.d.mts +2 -1
- package/dist/async_hooks/pure.index.mjs +2 -1
- package/dist/async_hooks/pure.index.mjs.map +1 -0
- package/dist/context/endpoint-context.d.mts +2 -1
- package/dist/context/endpoint-context.mjs +2 -1
- package/dist/context/endpoint-context.mjs.map +1 -0
- package/dist/context/global.d.mts +2 -1
- package/dist/context/global.mjs +3 -2
- package/dist/context/global.mjs.map +1 -0
- package/dist/context/request-state.d.mts +2 -1
- package/dist/context/request-state.mjs +2 -1
- package/dist/context/request-state.mjs.map +1 -0
- package/dist/context/transaction.d.mts +2 -1
- package/dist/context/transaction.mjs +2 -1
- package/dist/context/transaction.mjs.map +1 -0
- package/dist/db/adapter/factory.d.mts +2 -1
- package/dist/db/adapter/factory.mjs +2 -24
- package/dist/db/adapter/factory.mjs.map +1 -0
- package/dist/db/adapter/get-default-field-name.d.mts +2 -1
- package/dist/db/adapter/get-default-field-name.mjs +2 -1
- package/dist/db/adapter/get-default-field-name.mjs.map +1 -0
- package/dist/db/adapter/get-default-model-name.d.mts +2 -1
- package/dist/db/adapter/get-default-model-name.mjs +2 -1
- package/dist/db/adapter/get-default-model-name.mjs.map +1 -0
- package/dist/db/adapter/get-field-attributes.d.mts +2 -1
- package/dist/db/adapter/get-field-attributes.mjs +2 -1
- package/dist/db/adapter/get-field-attributes.mjs.map +1 -0
- package/dist/db/adapter/get-field-name.d.mts +2 -1
- package/dist/db/adapter/get-field-name.mjs +2 -1
- package/dist/db/adapter/get-field-name.mjs.map +1 -0
- package/dist/db/adapter/get-id-field.d.mts +2 -1
- package/dist/db/adapter/get-id-field.mjs +2 -1
- package/dist/db/adapter/get-id-field.mjs.map +1 -0
- package/dist/db/adapter/get-model-name.d.mts +2 -1
- package/dist/db/adapter/get-model-name.mjs +2 -1
- package/dist/db/adapter/get-model-name.mjs.map +1 -0
- package/dist/db/adapter/index.d.mts +2 -1
- package/dist/db/adapter/types.d.mts +2 -1
- package/dist/db/adapter/utils.d.mts +2 -1
- package/dist/db/adapter/utils.mjs +2 -1
- package/dist/db/adapter/utils.mjs.map +1 -0
- package/dist/db/get-tables.d.mts +2 -1
- package/dist/db/get-tables.mjs +8 -2
- package/dist/db/get-tables.mjs.map +1 -0
- package/dist/db/plugin.d.mts +2 -1
- package/dist/db/schema/account.d.mts +2 -1
- package/dist/db/schema/account.mjs +2 -1
- package/dist/db/schema/account.mjs.map +1 -0
- package/dist/db/schema/rate-limit.d.mts +2 -1
- package/dist/db/schema/rate-limit.mjs +2 -1
- package/dist/db/schema/rate-limit.mjs.map +1 -0
- package/dist/db/schema/session.d.mts +2 -1
- package/dist/db/schema/session.mjs +2 -1
- package/dist/db/schema/session.mjs.map +1 -0
- package/dist/db/schema/shared.d.mts +2 -1
- package/dist/db/schema/shared.mjs +2 -1
- package/dist/db/schema/shared.mjs.map +1 -0
- package/dist/db/schema/user.d.mts +2 -1
- package/dist/db/schema/user.mjs +2 -1
- package/dist/db/schema/user.mjs.map +1 -0
- package/dist/db/schema/verification.d.mts +2 -1
- package/dist/db/schema/verification.mjs +2 -1
- package/dist/db/schema/verification.mjs.map +1 -0
- package/dist/db/type.d.mts +2 -1
- package/dist/env/color-depth.d.mts +2 -1
- package/dist/env/color-depth.mjs +2 -1
- package/dist/env/color-depth.mjs.map +1 -0
- package/dist/env/env-impl.d.mts +3 -2
- package/dist/env/env-impl.mjs +3 -2
- package/dist/env/env-impl.mjs.map +1 -0
- package/dist/env/logger.d.mts +2 -1
- package/dist/env/logger.mjs +3 -2
- package/dist/env/logger.mjs.map +1 -0
- package/dist/error/codes.d.mts +2 -1
- package/dist/error/codes.mjs +2 -1
- package/dist/error/codes.mjs.map +1 -0
- package/dist/error/index.d.mts +2 -1
- package/dist/error/index.mjs +2 -1
- package/dist/error/index.mjs.map +1 -0
- package/dist/index.d.mts +2 -2
- package/dist/oauth2/client-credentials-token.d.mts +2 -1
- package/dist/oauth2/client-credentials-token.mjs +2 -1
- package/dist/oauth2/client-credentials-token.mjs.map +1 -0
- package/dist/oauth2/create-authorization-url.d.mts +2 -1
- package/dist/oauth2/create-authorization-url.mjs +2 -1
- package/dist/oauth2/create-authorization-url.mjs.map +1 -0
- package/dist/oauth2/oauth-provider.d.mts +3 -2
- package/dist/oauth2/refresh-access-token.d.mts +2 -1
- package/dist/oauth2/refresh-access-token.mjs +2 -1
- package/dist/oauth2/refresh-access-token.mjs.map +1 -0
- package/dist/oauth2/utils.d.mts +2 -1
- package/dist/oauth2/utils.mjs +2 -1
- package/dist/oauth2/utils.mjs.map +1 -0
- package/dist/oauth2/validate-authorization-code.d.mts +2 -1
- package/dist/oauth2/validate-authorization-code.mjs +2 -1
- package/dist/oauth2/validate-authorization-code.mjs.map +1 -0
- package/dist/oauth2/verify.d.mts +2 -1
- package/dist/oauth2/verify.mjs +2 -1
- package/dist/oauth2/verify.mjs.map +1 -0
- package/dist/social-providers/apple.d.mts +2 -1
- package/dist/social-providers/apple.mjs +5 -2
- package/dist/social-providers/apple.mjs.map +1 -0
- package/dist/social-providers/atlassian.d.mts +2 -1
- package/dist/social-providers/atlassian.mjs +2 -1
- package/dist/social-providers/atlassian.mjs.map +1 -0
- package/dist/social-providers/cognito.d.mts +2 -1
- package/dist/social-providers/cognito.mjs +2 -1
- package/dist/social-providers/cognito.mjs.map +1 -0
- package/dist/social-providers/discord.d.mts +2 -1
- package/dist/social-providers/discord.mjs +2 -1
- package/dist/social-providers/discord.mjs.map +1 -0
- package/dist/social-providers/dropbox.d.mts +2 -1
- package/dist/social-providers/dropbox.mjs +2 -1
- package/dist/social-providers/dropbox.mjs.map +1 -0
- package/dist/social-providers/facebook.d.mts +2 -1
- package/dist/social-providers/facebook.mjs +5 -4
- package/dist/social-providers/facebook.mjs.map +1 -0
- package/dist/social-providers/figma.d.mts +2 -1
- package/dist/social-providers/figma.mjs +2 -1
- package/dist/social-providers/figma.mjs.map +1 -0
- package/dist/social-providers/github.d.mts +3 -2
- package/dist/social-providers/github.mjs +22 -5
- package/dist/social-providers/github.mjs.map +1 -0
- package/dist/social-providers/gitlab.d.mts +2 -1
- package/dist/social-providers/gitlab.mjs +2 -1
- package/dist/social-providers/gitlab.mjs.map +1 -0
- package/dist/social-providers/google.d.mts +2 -1
- package/dist/social-providers/google.mjs +4 -3
- package/dist/social-providers/google.mjs.map +1 -0
- package/dist/social-providers/huggingface.d.mts +2 -1
- package/dist/social-providers/huggingface.mjs +2 -1
- package/dist/social-providers/huggingface.mjs.map +1 -0
- package/dist/social-providers/index.d.mts +3 -2
- package/dist/social-providers/index.mjs +2 -1
- package/dist/social-providers/index.mjs.map +1 -0
- package/dist/social-providers/kakao.d.mts +2 -1
- package/dist/social-providers/kakao.mjs +2 -1
- package/dist/social-providers/kakao.mjs.map +1 -0
- package/dist/social-providers/kick.d.mts +2 -1
- package/dist/social-providers/kick.mjs +2 -1
- package/dist/social-providers/kick.mjs.map +1 -0
- package/dist/social-providers/line.d.mts +2 -1
- package/dist/social-providers/line.mjs +2 -1
- package/dist/social-providers/line.mjs.map +1 -0
- package/dist/social-providers/linear.d.mts +2 -1
- package/dist/social-providers/linear.mjs +2 -1
- package/dist/social-providers/linear.mjs.map +1 -0
- package/dist/social-providers/linkedin.d.mts +2 -1
- package/dist/social-providers/linkedin.mjs +2 -1
- package/dist/social-providers/linkedin.mjs.map +1 -0
- package/dist/social-providers/microsoft-entra-id.d.mts +2 -1
- package/dist/social-providers/microsoft-entra-id.mjs +2 -1
- package/dist/social-providers/microsoft-entra-id.mjs.map +1 -0
- package/dist/social-providers/naver.d.mts +2 -1
- package/dist/social-providers/naver.mjs +2 -1
- package/dist/social-providers/naver.mjs.map +1 -0
- package/dist/social-providers/notion.d.mts +2 -1
- package/dist/social-providers/notion.mjs +2 -1
- package/dist/social-providers/notion.mjs.map +1 -0
- package/dist/social-providers/paybin.d.mts +2 -1
- package/dist/social-providers/paybin.mjs +2 -1
- package/dist/social-providers/paybin.mjs.map +1 -0
- package/dist/social-providers/paypal.d.mts +2 -1
- package/dist/social-providers/paypal.mjs +2 -1
- package/dist/social-providers/paypal.mjs.map +1 -0
- package/dist/social-providers/polar.d.mts +2 -1
- package/dist/social-providers/polar.mjs +2 -1
- package/dist/social-providers/polar.mjs.map +1 -0
- package/dist/social-providers/reddit.d.mts +2 -1
- package/dist/social-providers/reddit.mjs +2 -1
- package/dist/social-providers/reddit.mjs.map +1 -0
- package/dist/social-providers/roblox.d.mts +2 -1
- package/dist/social-providers/roblox.mjs +2 -1
- package/dist/social-providers/roblox.mjs.map +1 -0
- package/dist/social-providers/salesforce.d.mts +2 -1
- package/dist/social-providers/salesforce.mjs +2 -1
- package/dist/social-providers/salesforce.mjs.map +1 -0
- package/dist/social-providers/slack.d.mts +2 -1
- package/dist/social-providers/slack.mjs +2 -1
- package/dist/social-providers/slack.mjs.map +1 -0
- package/dist/social-providers/spotify.d.mts +2 -1
- package/dist/social-providers/spotify.mjs +2 -1
- package/dist/social-providers/spotify.mjs.map +1 -0
- package/dist/social-providers/tiktok.d.mts +2 -1
- package/dist/social-providers/tiktok.mjs +2 -1
- package/dist/social-providers/tiktok.mjs.map +1 -0
- package/dist/social-providers/twitch.d.mts +2 -1
- package/dist/social-providers/twitch.mjs +2 -1
- package/dist/social-providers/twitch.mjs.map +1 -0
- package/dist/social-providers/twitter.d.mts +3 -2
- package/dist/social-providers/twitter.mjs +2 -1
- package/dist/social-providers/twitter.mjs.map +1 -0
- package/dist/social-providers/vercel.d.mts +2 -1
- package/dist/social-providers/vercel.mjs +2 -1
- package/dist/social-providers/vercel.mjs.map +1 -0
- package/dist/social-providers/vk.d.mts +2 -1
- package/dist/social-providers/vk.mjs +2 -1
- package/dist/social-providers/vk.mjs.map +1 -0
- package/dist/social-providers/zoom.d.mts +3 -3
- package/dist/social-providers/zoom.mjs +2 -1
- package/dist/social-providers/zoom.mjs.map +1 -0
- package/dist/types/context.d.mts +7 -3
- package/dist/types/cookie.d.mts +2 -1
- package/dist/types/helper.d.mts +2 -1
- package/dist/types/index.d.mts +1 -1
- package/dist/types/init-options.d.mts +36 -33
- package/dist/types/plugin-client.d.mts +2 -1
- package/dist/types/plugin.d.mts +2 -1
- package/dist/utils/db.d.mts +13 -0
- package/dist/utils/db.mjs +17 -0
- package/dist/utils/db.mjs.map +1 -0
- package/dist/utils/deprecate.d.mts +2 -1
- package/dist/utils/deprecate.mjs +2 -1
- package/dist/utils/deprecate.mjs.map +1 -0
- package/dist/utils/error-codes.d.mts +2 -1
- package/dist/utils/error-codes.mjs +2 -1
- package/dist/utils/error-codes.mjs.map +1 -0
- package/dist/utils/id.d.mts +2 -1
- package/dist/utils/id.mjs +2 -1
- package/dist/utils/id.mjs.map +1 -0
- package/dist/utils/index.d.mts +2 -1
- package/dist/utils/index.mjs +2 -1
- package/dist/utils/ip.d.mts +2 -1
- package/dist/utils/ip.mjs +2 -1
- package/dist/utils/ip.mjs.map +1 -0
- package/dist/utils/json.d.mts +2 -1
- package/dist/utils/json.mjs +2 -1
- package/dist/utils/json.mjs.map +1 -0
- package/dist/utils/string.d.mts +2 -1
- package/dist/utils/string.mjs +2 -1
- package/dist/utils/string.mjs.map +1 -0
- package/dist/utils/url.d.mts +2 -1
- package/dist/utils/url.mjs +2 -1
- package/dist/utils/url.mjs.map +1 -0
- package/package.json +1 -1
- package/src/db/adapter/factory.ts +0 -36
- package/src/db/get-tables.ts +5 -0
- package/src/env/env-impl.ts +2 -2
- package/src/env/logger.ts +1 -1
- package/src/oauth2/oauth-provider.ts +1 -1
- package/src/social-providers/apple.ts +12 -3
- package/src/social-providers/facebook.ts +3 -3
- package/src/social-providers/github.ts +25 -3
- package/src/social-providers/google.ts +2 -2
- package/src/types/context.ts +6 -3
- package/src/types/index.ts +6 -1
- package/src/types/init-options.ts +44 -36
- package/src/utils/db.ts +20 -0
- package/src/utils/index.ts +1 -0
- package/tsdown.config.ts +3 -0
|
@@ -116,4 +116,5 @@ declare const apple: (options: AppleOptions) => {
|
|
|
116
116
|
};
|
|
117
117
|
declare const getApplePublicKey: (kid: string) => Promise<Uint8Array<ArrayBufferLike> | CryptoKey>;
|
|
118
118
|
//#endregion
|
|
119
|
-
export { AppleNonConformUser, AppleOptions, AppleProfile, apple, getApplePublicKey };
|
|
119
|
+
export { AppleNonConformUser, AppleOptions, AppleProfile, apple, getApplePublicKey };
|
|
120
|
+
//# sourceMappingURL=apple.d.mts.map
|
|
@@ -69,7 +69,9 @@ const apple = (options) => {
|
|
|
69
69
|
if (!token.idToken) return null;
|
|
70
70
|
const profile = decodeJwt(token.idToken);
|
|
71
71
|
if (!profile) return null;
|
|
72
|
-
|
|
72
|
+
let name;
|
|
73
|
+
if (token.user?.name) name = `${token.user.name.firstName || ""} ${token.user.name.lastName || ""}`.trim() || " ";
|
|
74
|
+
else name = profile.name || " ";
|
|
73
75
|
const emailVerified = typeof profile.email_verified === "boolean" ? profile.email_verified : profile.email_verified === "true";
|
|
74
76
|
const enrichedProfile = {
|
|
75
77
|
...profile,
|
|
@@ -99,4 +101,5 @@ const getApplePublicKey = async (kid) => {
|
|
|
99
101
|
};
|
|
100
102
|
|
|
101
103
|
//#endregion
|
|
102
|
-
export { apple, getApplePublicKey };
|
|
104
|
+
export { apple, getApplePublicKey };
|
|
105
|
+
//# sourceMappingURL=apple.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apple.mjs","names":["name: string"],"sources":["../../src/social-providers/apple.ts"],"sourcesContent":["import { betterFetch } from \"@better-fetch/fetch\";\nimport { APIError } from \"better-call\";\nimport { decodeJwt, decodeProtectedHeader, importJWK, jwtVerify } from \"jose\";\nimport type { OAuthProvider, ProviderOptions } from \"../oauth2\";\nimport {\n\tcreateAuthorizationURL,\n\trefreshAccessToken,\n\tvalidateAuthorizationCode,\n} from \"../oauth2\";\nexport interface AppleProfile {\n\t/**\n\t * The subject registered claim identifies the principal that’s the subject\n\t * of the identity token. Because this token is for your app, the value is\n\t * the unique identifier for the user.\n\t */\n\tsub: string;\n\t/**\n\t * A String value representing the user's email address.\n\t * The email address is either the user's real email address or the proxy\n\t * address, depending on their status private email relay service.\n\t */\n\temail: string;\n\t/**\n\t * A string or Boolean value that indicates whether the service verifies\n\t * the email. The value can either be a string (\"true\" or \"false\") or a\n\t * Boolean (true or false). The system may not verify email addresses for\n\t * Sign in with Apple at Work & School users, and this claim is \"false\" or\n\t * false for those users.\n\t */\n\temail_verified: true | \"true\";\n\t/**\n\t * A string or Boolean value that indicates whether the email that the user\n\t * shares is the proxy address. The value can either be a string (\"true\" or\n\t * \"false\") or a Boolean (true or false).\n\t */\n\tis_private_email: boolean;\n\t/**\n\t * An Integer value that indicates whether the user appears to be a real\n\t * person. Use the value of this claim to mitigate fraud. The possible\n\t * values are: 0 (or Unsupported), 1 (or Unknown), 2 (or LikelyReal). For\n\t * more information, see ASUserDetectionStatus. This claim is present only\n\t * in iOS 14 and later, macOS 11 and later, watchOS 7 and later, tvOS 14\n\t * and later. The claim isn’t present or supported for web-based apps.\n\t */\n\treal_user_status: number;\n\t/**\n\t * The user’s full name in the format provided during the authorization\n\t * process.\n\t */\n\tname: string;\n\t/**\n\t * The URL to the user's profile picture.\n\t */\n\tpicture: string;\n\tuser?: AppleNonConformUser | undefined;\n}\n\n/**\n * This is the shape of the `user` query parameter that Apple sends the first\n * time the user consents to the app.\n * @see https://developer.apple.com/documentation/signinwithapplerestapi/request-an-authorization-to-the-sign-in-with-apple-server./\n */\nexport interface AppleNonConformUser {\n\tname: {\n\t\tfirstName: string;\n\t\tlastName: string;\n\t};\n\temail: string;\n}\n\nexport interface AppleOptions extends ProviderOptions<AppleProfile> {\n\tclientId: string;\n\tappBundleIdentifier?: string | undefined;\n\taudience?: (string | string[]) | undefined;\n}\n\nexport const apple = (options: AppleOptions) => {\n\tconst tokenEndpoint = \"https://appleid.apple.com/auth/token\";\n\treturn {\n\t\tid: \"apple\",\n\t\tname: \"Apple\",\n\t\tasync createAuthorizationURL({ state, scopes, redirectURI }) {\n\t\t\tconst _scope = options.disableDefaultScope ? [] : [\"email\", \"name\"];\n\t\t\tif (options.scope) _scope.push(...options.scope);\n\t\t\tif (scopes) _scope.push(...scopes);\n\t\t\tconst url = await createAuthorizationURL({\n\t\t\t\tid: \"apple\",\n\t\t\t\toptions,\n\t\t\t\tauthorizationEndpoint: \"https://appleid.apple.com/auth/authorize\",\n\t\t\t\tscopes: _scope,\n\t\t\t\tstate,\n\t\t\t\tredirectURI,\n\t\t\t\tresponseMode: \"form_post\",\n\t\t\t\tresponseType: \"code id_token\",\n\t\t\t});\n\t\t\treturn url;\n\t\t},\n\t\tvalidateAuthorizationCode: async ({ code, codeVerifier, redirectURI }) => {\n\t\t\treturn validateAuthorizationCode({\n\t\t\t\tcode,\n\t\t\t\tcodeVerifier,\n\t\t\t\tredirectURI,\n\t\t\t\toptions,\n\t\t\t\ttokenEndpoint,\n\t\t\t});\n\t\t},\n\t\tasync verifyIdToken(token, nonce) {\n\t\t\tif (options.disableIdTokenSignIn) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (options.verifyIdToken) {\n\t\t\t\treturn options.verifyIdToken(token, nonce);\n\t\t\t}\n\t\t\tconst decodedHeader = decodeProtectedHeader(token);\n\t\t\tconst { kid, alg: jwtAlg } = decodedHeader;\n\t\t\tif (!kid || !jwtAlg) return false;\n\t\t\tconst publicKey = await getApplePublicKey(kid);\n\t\t\tconst { payload: jwtClaims } = await jwtVerify(token, publicKey, {\n\t\t\t\talgorithms: [jwtAlg],\n\t\t\t\tissuer: \"https://appleid.apple.com\",\n\t\t\t\taudience:\n\t\t\t\t\toptions.audience && options.audience.length\n\t\t\t\t\t\t? options.audience\n\t\t\t\t\t\t: options.appBundleIdentifier\n\t\t\t\t\t\t\t? options.appBundleIdentifier\n\t\t\t\t\t\t\t: options.clientId,\n\t\t\t\tmaxTokenAge: \"1h\",\n\t\t\t});\n\t\t\t[\"email_verified\", \"is_private_email\"].forEach((field) => {\n\t\t\t\tif (jwtClaims[field] !== undefined) {\n\t\t\t\t\tjwtClaims[field] = Boolean(jwtClaims[field]);\n\t\t\t\t}\n\t\t\t});\n\t\t\tif (nonce && jwtClaims.nonce !== nonce) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\treturn !!jwtClaims;\n\t\t},\n\t\trefreshAccessToken: options.refreshAccessToken\n\t\t\t? options.refreshAccessToken\n\t\t\t: async (refreshToken) => {\n\t\t\t\t\treturn refreshAccessToken({\n\t\t\t\t\t\trefreshToken,\n\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\tclientId: options.clientId,\n\t\t\t\t\t\t\tclientKey: options.clientKey,\n\t\t\t\t\t\t\tclientSecret: options.clientSecret,\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttokenEndpoint: \"https://appleid.apple.com/auth/token\",\n\t\t\t\t\t});\n\t\t\t\t},\n\t\tasync getUserInfo(token) {\n\t\t\tif (options.getUserInfo) {\n\t\t\t\treturn options.getUserInfo(token);\n\t\t\t}\n\t\t\tif (!token.idToken) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst profile = decodeJwt<AppleProfile>(token.idToken);\n\t\t\tif (!profile) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\t// TODO: \" \" masking will be removed when the name field is made optional\n\t\t\tlet name: string;\n\t\t\tif (token.user?.name) {\n\t\t\t\tconst firstName = token.user.name.firstName || \"\";\n\t\t\t\tconst lastName = token.user.name.lastName || \"\";\n\t\t\t\tconst fullName = `${firstName} ${lastName}`.trim();\n\t\t\t\tname = fullName || \" \";\n\t\t\t} else {\n\t\t\t\tname = profile.name || \" \";\n\t\t\t}\n\n\t\t\tconst emailVerified =\n\t\t\t\ttypeof profile.email_verified === \"boolean\"\n\t\t\t\t\t? profile.email_verified\n\t\t\t\t\t: profile.email_verified === \"true\";\n\t\t\tconst enrichedProfile = {\n\t\t\t\t...profile,\n\t\t\t\tname,\n\t\t\t};\n\t\t\tconst userMap = await options.mapProfileToUser?.(enrichedProfile);\n\t\t\treturn {\n\t\t\t\tuser: {\n\t\t\t\t\tid: profile.sub,\n\t\t\t\t\tname: enrichedProfile.name,\n\t\t\t\t\temailVerified: emailVerified,\n\t\t\t\t\temail: profile.email,\n\t\t\t\t\t...userMap,\n\t\t\t\t},\n\t\t\t\tdata: enrichedProfile,\n\t\t\t};\n\t\t},\n\t\toptions,\n\t} satisfies OAuthProvider<AppleProfile>;\n};\n\nexport const getApplePublicKey = async (kid: string) => {\n\tconst APPLE_BASE_URL = \"https://appleid.apple.com\";\n\tconst JWKS_APPLE_URI = \"/auth/keys\";\n\tconst { data } = await betterFetch<{\n\t\tkeys: Array<{\n\t\t\tkid: string;\n\t\t\talg: string;\n\t\t\tkty: string;\n\t\t\tuse: string;\n\t\t\tn: string;\n\t\t\te: string;\n\t\t}>;\n\t}>(`${APPLE_BASE_URL}${JWKS_APPLE_URI}`);\n\tif (!data?.keys) {\n\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\tmessage: \"Keys not found\",\n\t\t});\n\t}\n\tconst jwk = data.keys.find((key) => key.kid === kid);\n\tif (!jwk) {\n\t\tthrow new Error(`JWK with kid ${kid} not found`);\n\t}\n\treturn await importJWK(jwk, jwk.alg);\n};\n"],"mappings":";;;;;;;;;AA4EA,MAAa,SAAS,YAA0B;CAC/C,MAAM,gBAAgB;AACtB,QAAO;EACN,IAAI;EACJ,MAAM;EACN,MAAM,uBAAuB,EAAE,OAAO,QAAQ,eAAe;GAC5D,MAAM,SAAS,QAAQ,sBAAsB,EAAE,GAAG,CAAC,SAAS,OAAO;AACnE,OAAI,QAAQ,MAAO,QAAO,KAAK,GAAG,QAAQ,MAAM;AAChD,OAAI,OAAQ,QAAO,KAAK,GAAG,OAAO;AAWlC,UAVY,MAAM,uBAAuB;IACxC,IAAI;IACJ;IACA,uBAAuB;IACvB,QAAQ;IACR;IACA;IACA,cAAc;IACd,cAAc;IACd,CAAC;;EAGH,2BAA2B,OAAO,EAAE,MAAM,cAAc,kBAAkB;AACzE,UAAO,0BAA0B;IAChC;IACA;IACA;IACA;IACA;IACA,CAAC;;EAEH,MAAM,cAAc,OAAO,OAAO;AACjC,OAAI,QAAQ,qBACX,QAAO;AAER,OAAI,QAAQ,cACX,QAAO,QAAQ,cAAc,OAAO,MAAM;GAG3C,MAAM,EAAE,KAAK,KAAK,WADI,sBAAsB,MAAM;AAElD,OAAI,CAAC,OAAO,CAAC,OAAQ,QAAO;GAE5B,MAAM,EAAE,SAAS,cAAc,MAAM,UAAU,OAD7B,MAAM,kBAAkB,IAAI,EACmB;IAChE,YAAY,CAAC,OAAO;IACpB,QAAQ;IACR,UACC,QAAQ,YAAY,QAAQ,SAAS,SAClC,QAAQ,WACR,QAAQ,sBACP,QAAQ,sBACR,QAAQ;IACb,aAAa;IACb,CAAC;AACF,IAAC,kBAAkB,mBAAmB,CAAC,SAAS,UAAU;AACzD,QAAI,UAAU,WAAW,OACxB,WAAU,SAAS,QAAQ,UAAU,OAAO;KAE5C;AACF,OAAI,SAAS,UAAU,UAAU,MAChC,QAAO;AAER,UAAO,CAAC,CAAC;;EAEV,oBAAoB,QAAQ,qBACzB,QAAQ,qBACR,OAAO,iBAAiB;AACxB,UAAO,mBAAmB;IACzB;IACA,SAAS;KACR,UAAU,QAAQ;KAClB,WAAW,QAAQ;KACnB,cAAc,QAAQ;KACtB;IACD,eAAe;IACf,CAAC;;EAEL,MAAM,YAAY,OAAO;AACxB,OAAI,QAAQ,YACX,QAAO,QAAQ,YAAY,MAAM;AAElC,OAAI,CAAC,MAAM,QACV,QAAO;GAER,MAAM,UAAU,UAAwB,MAAM,QAAQ;AACtD,OAAI,CAAC,QACJ,QAAO;GAIR,IAAIA;AACJ,OAAI,MAAM,MAAM,KAIf,QADiB,GAFC,MAAM,KAAK,KAAK,aAAa,GAEjB,GADb,MAAM,KAAK,KAAK,YAAY,KACD,MAAM,IAC/B;OAEnB,QAAO,QAAQ,QAAQ;GAGxB,MAAM,gBACL,OAAO,QAAQ,mBAAmB,YAC/B,QAAQ,iBACR,QAAQ,mBAAmB;GAC/B,MAAM,kBAAkB;IACvB,GAAG;IACH;IACA;GACD,MAAM,UAAU,MAAM,QAAQ,mBAAmB,gBAAgB;AACjE,UAAO;IACN,MAAM;KACL,IAAI,QAAQ;KACZ,MAAM,gBAAgB;KACP;KACf,OAAO,QAAQ;KACf,GAAG;KACH;IACD,MAAM;IACN;;EAEF;EACA;;AAGF,MAAa,oBAAoB,OAAO,QAAgB;CAGvD,MAAM,EAAE,SAAS,MAAM,YASpB,sCAAqC;AACxC,KAAI,CAAC,MAAM,KACV,OAAM,IAAI,SAAS,eAAe,EACjC,SAAS,kBACT,CAAC;CAEH,MAAM,MAAM,KAAK,KAAK,MAAM,QAAQ,IAAI,QAAQ,IAAI;AACpD,KAAI,CAAC,IACJ,OAAM,IAAI,MAAM,gBAAgB,IAAI,YAAY;AAEjD,QAAO,MAAM,UAAU,KAAK,IAAI,IAAI"}
|
|
@@ -69,4 +69,5 @@ declare const atlassian: (options: AtlassianOptions) => {
|
|
|
69
69
|
options: AtlassianOptions;
|
|
70
70
|
};
|
|
71
71
|
//#endregion
|
|
72
|
-
export { AtlassianOptions, AtlassianProfile, atlassian };
|
|
72
|
+
export { AtlassianOptions, AtlassianProfile, atlassian };
|
|
73
|
+
//# sourceMappingURL=atlassian.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"atlassian.mjs","names":[],"sources":["../../src/social-providers/atlassian.ts"],"sourcesContent":["import { betterFetch } from \"@better-fetch/fetch\";\nimport { logger } from \"../env\";\nimport { BetterAuthError } from \"../error\";\nimport type { OAuthProvider, ProviderOptions } from \"../oauth2\";\nimport {\n\tcreateAuthorizationURL,\n\trefreshAccessToken,\n\tvalidateAuthorizationCode,\n} from \"../oauth2\";\n\nexport interface AtlassianProfile {\n\taccount_type?: string | undefined;\n\taccount_id: string;\n\temail?: string | undefined;\n\tname: string;\n\tpicture?: string | undefined;\n\tnickname?: string | undefined;\n\tlocale?: string | undefined;\n\textended_profile?:\n\t\t| {\n\t\t\t\tjob_title?: string;\n\t\t\t\torganization?: string;\n\t\t\t\tdepartment?: string;\n\t\t\t\tlocation?: string;\n\t\t }\n\t\t| undefined;\n}\nexport interface AtlassianOptions extends ProviderOptions<AtlassianProfile> {\n\tclientId: string;\n}\n\nexport const atlassian = (options: AtlassianOptions) => {\n\treturn {\n\t\tid: \"atlassian\",\n\t\tname: \"Atlassian\",\n\n\t\tasync createAuthorizationURL({ state, scopes, codeVerifier, redirectURI }) {\n\t\t\tif (!options.clientId || !options.clientSecret) {\n\t\t\t\tlogger.error(\"Client Id and Secret are required for Atlassian\");\n\t\t\t\tthrow new BetterAuthError(\"CLIENT_ID_AND_SECRET_REQUIRED\");\n\t\t\t}\n\t\t\tif (!codeVerifier) {\n\t\t\t\tthrow new BetterAuthError(\"codeVerifier is required for Atlassian\");\n\t\t\t}\n\n\t\t\tconst _scopes = options.disableDefaultScope\n\t\t\t\t? []\n\t\t\t\t: [\"read:jira-user\", \"offline_access\"];\n\t\t\tif (options.scope) _scopes.push(...options.scope);\n\t\t\tif (scopes) _scopes.push(...scopes);\n\n\t\t\treturn createAuthorizationURL({\n\t\t\t\tid: \"atlassian\",\n\t\t\t\toptions,\n\t\t\t\tauthorizationEndpoint: \"https://auth.atlassian.com/authorize\",\n\t\t\t\tscopes: _scopes,\n\t\t\t\tstate,\n\t\t\t\tcodeVerifier,\n\t\t\t\tredirectURI,\n\t\t\t\tadditionalParams: {\n\t\t\t\t\taudience: \"api.atlassian.com\",\n\t\t\t\t},\n\t\t\t\tprompt: options.prompt,\n\t\t\t});\n\t\t},\n\n\t\tvalidateAuthorizationCode: async ({ code, codeVerifier, redirectURI }) => {\n\t\t\treturn validateAuthorizationCode({\n\t\t\t\tcode,\n\t\t\t\tcodeVerifier,\n\t\t\t\tredirectURI,\n\t\t\t\toptions,\n\t\t\t\ttokenEndpoint: \"https://auth.atlassian.com/oauth/token\",\n\t\t\t});\n\t\t},\n\n\t\trefreshAccessToken: options.refreshAccessToken\n\t\t\t? options.refreshAccessToken\n\t\t\t: async (refreshToken) => {\n\t\t\t\t\treturn refreshAccessToken({\n\t\t\t\t\t\trefreshToken,\n\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\tclientId: options.clientId,\n\t\t\t\t\t\t\tclientSecret: options.clientSecret,\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttokenEndpoint: \"https://auth.atlassian.com/oauth/token\",\n\t\t\t\t\t});\n\t\t\t\t},\n\n\t\tasync getUserInfo(token) {\n\t\t\tif (options.getUserInfo) {\n\t\t\t\treturn options.getUserInfo(token);\n\t\t\t}\n\n\t\t\tif (!token.accessToken) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst { data: profile } = await betterFetch<{\n\t\t\t\t\taccount_id: string;\n\t\t\t\t\tname: string;\n\t\t\t\t\temail?: string | undefined;\n\t\t\t\t\tpicture?: string | undefined;\n\t\t\t\t}>(\"https://api.atlassian.com/me\", {\n\t\t\t\t\theaders: { Authorization: `Bearer ${token.accessToken}` },\n\t\t\t\t});\n\n\t\t\t\tif (!profile) return null;\n\n\t\t\t\tconst userMap = await options.mapProfileToUser?.(profile);\n\n\t\t\t\treturn {\n\t\t\t\t\tuser: {\n\t\t\t\t\t\tid: profile.account_id,\n\t\t\t\t\t\tname: profile.name,\n\t\t\t\t\t\temail: profile.email,\n\t\t\t\t\t\timage: profile.picture,\n\t\t\t\t\t\temailVerified: false,\n\t\t\t\t\t\t...userMap,\n\t\t\t\t\t},\n\t\t\t\t\tdata: profile,\n\t\t\t\t};\n\t\t\t} catch (error) {\n\t\t\t\tlogger.error(\"Failed to fetch user info from Figma:\", error);\n\t\t\t\treturn null;\n\t\t\t}\n\t\t},\n\n\t\toptions,\n\t} satisfies OAuthProvider<AtlassianProfile>;\n};\n"],"mappings":";;;;;;;;;;AA+BA,MAAa,aAAa,YAA8B;AACvD,QAAO;EACN,IAAI;EACJ,MAAM;EAEN,MAAM,uBAAuB,EAAE,OAAO,QAAQ,cAAc,eAAe;AAC1E,OAAI,CAAC,QAAQ,YAAY,CAAC,QAAQ,cAAc;AAC/C,WAAO,MAAM,kDAAkD;AAC/D,UAAM,IAAI,gBAAgB,gCAAgC;;AAE3D,OAAI,CAAC,aACJ,OAAM,IAAI,gBAAgB,yCAAyC;GAGpE,MAAM,UAAU,QAAQ,sBACrB,EAAE,GACF,CAAC,kBAAkB,iBAAiB;AACvC,OAAI,QAAQ,MAAO,SAAQ,KAAK,GAAG,QAAQ,MAAM;AACjD,OAAI,OAAQ,SAAQ,KAAK,GAAG,OAAO;AAEnC,UAAO,uBAAuB;IAC7B,IAAI;IACJ;IACA,uBAAuB;IACvB,QAAQ;IACR;IACA;IACA;IACA,kBAAkB,EACjB,UAAU,qBACV;IACD,QAAQ,QAAQ;IAChB,CAAC;;EAGH,2BAA2B,OAAO,EAAE,MAAM,cAAc,kBAAkB;AACzE,UAAO,0BAA0B;IAChC;IACA;IACA;IACA;IACA,eAAe;IACf,CAAC;;EAGH,oBAAoB,QAAQ,qBACzB,QAAQ,qBACR,OAAO,iBAAiB;AACxB,UAAO,mBAAmB;IACzB;IACA,SAAS;KACR,UAAU,QAAQ;KAClB,cAAc,QAAQ;KACtB;IACD,eAAe;IACf,CAAC;;EAGL,MAAM,YAAY,OAAO;AACxB,OAAI,QAAQ,YACX,QAAO,QAAQ,YAAY,MAAM;AAGlC,OAAI,CAAC,MAAM,YACV,QAAO;AAGR,OAAI;IACH,MAAM,EAAE,MAAM,YAAY,MAAM,YAK7B,gCAAgC,EAClC,SAAS,EAAE,eAAe,UAAU,MAAM,eAAe,EACzD,CAAC;AAEF,QAAI,CAAC,QAAS,QAAO;IAErB,MAAM,UAAU,MAAM,QAAQ,mBAAmB,QAAQ;AAEzD,WAAO;KACN,MAAM;MACL,IAAI,QAAQ;MACZ,MAAM,QAAQ;MACd,OAAO,QAAQ;MACf,OAAO,QAAQ;MACf,eAAe;MACf,GAAG;MACH;KACD,MAAM;KACN;YACO,OAAO;AACf,WAAO,MAAM,yCAAyC,MAAM;AAC5D,WAAO;;;EAIT;EACA"}
|
|
@@ -84,4 +84,5 @@ declare const cognito: (options: CognitoOptions) => {
|
|
|
84
84
|
};
|
|
85
85
|
declare const getCognitoPublicKey: (kid: string, region: string, userPoolId: string) => Promise<Uint8Array<ArrayBufferLike> | CryptoKey>;
|
|
86
86
|
//#endregion
|
|
87
|
-
export { CognitoOptions, CognitoProfile, cognito, getCognitoPublicKey };
|
|
87
|
+
export { CognitoOptions, CognitoProfile, cognito, getCognitoPublicKey };
|
|
88
|
+
//# sourceMappingURL=cognito.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cognito.mjs","names":[],"sources":["../../src/social-providers/cognito.ts"],"sourcesContent":["import { betterFetch } from \"@better-fetch/fetch\";\nimport { APIError } from \"better-call\";\nimport { decodeJwt, decodeProtectedHeader, importJWK, jwtVerify } from \"jose\";\nimport { logger } from \"../env\";\nimport { BetterAuthError } from \"../error\";\nimport type { OAuthProvider, ProviderOptions } from \"../oauth2\";\nimport {\n\tcreateAuthorizationURL,\n\trefreshAccessToken,\n\tvalidateAuthorizationCode,\n} from \"../oauth2\";\n\nexport interface CognitoProfile {\n\tsub: string;\n\temail: string;\n\temail_verified: boolean;\n\tname: string;\n\tgiven_name?: string | undefined;\n\tfamily_name?: string | undefined;\n\tpicture?: string | undefined;\n\tusername?: string | undefined;\n\tlocale?: string | undefined;\n\tphone_number?: string | undefined;\n\tphone_number_verified?: boolean | undefined;\n\taud: string;\n\tiss: string;\n\texp: number;\n\tiat: number;\n\t// Custom attributes from Cognito can be added here\n\t[key: string]: any;\n}\n\nexport interface CognitoOptions extends ProviderOptions<CognitoProfile> {\n\tclientId: string;\n\t/**\n\t * The Cognito domain (e.g., \"your-app.auth.us-east-1.amazoncognito.com\")\n\t */\n\tdomain: string;\n\t/**\n\t * AWS region where User Pool is hosted (e.g., \"us-east-1\")\n\t */\n\tregion: string;\n\tuserPoolId: string;\n\trequireClientSecret?: boolean | undefined;\n}\n\nexport const cognito = (options: CognitoOptions) => {\n\tif (!options.domain || !options.region || !options.userPoolId) {\n\t\tlogger.error(\n\t\t\t\"Domain, region and userPoolId are required for Amazon Cognito. Make sure to provide them in the options.\",\n\t\t);\n\t\tthrow new BetterAuthError(\"DOMAIN_AND_REGION_REQUIRED\");\n\t}\n\n\tconst cleanDomain = options.domain.replace(/^https?:\\/\\//, \"\");\n\tconst authorizationEndpoint = `https://${cleanDomain}/oauth2/authorize`;\n\tconst tokenEndpoint = `https://${cleanDomain}/oauth2/token`;\n\tconst userInfoEndpoint = `https://${cleanDomain}/oauth2/userinfo`;\n\n\treturn {\n\t\tid: \"cognito\",\n\t\tname: \"Cognito\",\n\t\tasync createAuthorizationURL({ state, scopes, codeVerifier, redirectURI }) {\n\t\t\tif (!options.clientId) {\n\t\t\t\tlogger.error(\n\t\t\t\t\t\"ClientId is required for Amazon Cognito. Make sure to provide them in the options.\",\n\t\t\t\t);\n\t\t\t\tthrow new BetterAuthError(\"CLIENT_ID_AND_SECRET_REQUIRED\");\n\t\t\t}\n\n\t\t\tif (options.requireClientSecret && !options.clientSecret) {\n\t\t\t\tlogger.error(\n\t\t\t\t\t\"Client Secret is required when requireClientSecret is true. Make sure to provide it in the options.\",\n\t\t\t\t);\n\t\t\t\tthrow new BetterAuthError(\"CLIENT_SECRET_REQUIRED\");\n\t\t\t}\n\t\t\tconst _scopes = options.disableDefaultScope\n\t\t\t\t? []\n\t\t\t\t: [\"openid\", \"profile\", \"email\"];\n\t\t\tif (options.scope) _scopes.push(...options.scope);\n\t\t\tif (scopes) _scopes.push(...scopes);\n\n\t\t\tconst url = await createAuthorizationURL({\n\t\t\t\tid: \"cognito\",\n\t\t\t\toptions: {\n\t\t\t\t\t...options,\n\t\t\t\t},\n\t\t\t\tauthorizationEndpoint,\n\t\t\t\tscopes: _scopes,\n\t\t\t\tstate,\n\t\t\t\tcodeVerifier,\n\t\t\t\tredirectURI,\n\t\t\t\tprompt: options.prompt,\n\t\t\t});\n\t\t\t// AWS Cognito requires scopes to be encoded with %20 instead of +\n\t\t\t// URLSearchParams encodes spaces as + by default, so we need to fix this\n\t\t\tconst scopeValue = url.searchParams.get(\"scope\");\n\t\t\tif (scopeValue) {\n\t\t\t\turl.searchParams.delete(\"scope\");\n\t\t\t\tconst encodedScope = encodeURIComponent(scopeValue);\n\t\t\t\t// Manually append the scope with proper encoding to the URL\n\t\t\t\tconst urlString = url.toString();\n\t\t\t\tconst separator = urlString.includes(\"?\") ? \"&\" : \"?\";\n\t\t\t\treturn new URL(`${urlString}${separator}scope=${encodedScope}`);\n\t\t\t}\n\t\t\treturn url;\n\t\t},\n\n\t\tvalidateAuthorizationCode: async ({ code, codeVerifier, redirectURI }) => {\n\t\t\treturn validateAuthorizationCode({\n\t\t\t\tcode,\n\t\t\t\tcodeVerifier,\n\t\t\t\tredirectURI,\n\t\t\t\toptions,\n\t\t\t\ttokenEndpoint,\n\t\t\t});\n\t\t},\n\n\t\trefreshAccessToken: options.refreshAccessToken\n\t\t\t? options.refreshAccessToken\n\t\t\t: async (refreshToken) => {\n\t\t\t\t\treturn refreshAccessToken({\n\t\t\t\t\t\trefreshToken,\n\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\tclientId: options.clientId,\n\t\t\t\t\t\t\tclientKey: options.clientKey,\n\t\t\t\t\t\t\tclientSecret: options.clientSecret,\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttokenEndpoint,\n\t\t\t\t\t});\n\t\t\t\t},\n\n\t\tasync verifyIdToken(token, nonce) {\n\t\t\tif (options.disableIdTokenSignIn) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (options.verifyIdToken) {\n\t\t\t\treturn options.verifyIdToken(token, nonce);\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst decodedHeader = decodeProtectedHeader(token);\n\t\t\t\tconst { kid, alg: jwtAlg } = decodedHeader;\n\t\t\t\tif (!kid || !jwtAlg) return false;\n\n\t\t\t\tconst publicKey = await getCognitoPublicKey(\n\t\t\t\t\tkid,\n\t\t\t\t\toptions.region,\n\t\t\t\t\toptions.userPoolId,\n\t\t\t\t);\n\t\t\t\tconst expectedIssuer = `https://cognito-idp.${options.region}.amazonaws.com/${options.userPoolId}`;\n\n\t\t\t\tconst { payload: jwtClaims } = await jwtVerify(token, publicKey, {\n\t\t\t\t\talgorithms: [jwtAlg],\n\t\t\t\t\tissuer: expectedIssuer,\n\t\t\t\t\taudience: options.clientId,\n\t\t\t\t\tmaxTokenAge: \"1h\",\n\t\t\t\t});\n\n\t\t\t\tif (nonce && jwtClaims.nonce !== nonce) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t} catch (error) {\n\t\t\t\tlogger.error(\"Failed to verify ID token:\", error);\n\t\t\t\treturn false;\n\t\t\t}\n\t\t},\n\n\t\tasync getUserInfo(token) {\n\t\t\tif (options.getUserInfo) {\n\t\t\t\treturn options.getUserInfo(token);\n\t\t\t}\n\n\t\t\tif (token.idToken) {\n\t\t\t\ttry {\n\t\t\t\t\tconst profile = decodeJwt<CognitoProfile>(token.idToken);\n\t\t\t\t\tif (!profile) {\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\t\t\t\t\tconst name =\n\t\t\t\t\t\tprofile.name ||\n\t\t\t\t\t\tprofile.given_name ||\n\t\t\t\t\t\tprofile.username ||\n\t\t\t\t\t\tprofile.email;\n\t\t\t\t\tconst enrichedProfile = {\n\t\t\t\t\t\t...profile,\n\t\t\t\t\t\tname,\n\t\t\t\t\t};\n\t\t\t\t\tconst userMap = await options.mapProfileToUser?.(enrichedProfile);\n\n\t\t\t\t\treturn {\n\t\t\t\t\t\tuser: {\n\t\t\t\t\t\t\tid: profile.sub,\n\t\t\t\t\t\t\tname: enrichedProfile.name,\n\t\t\t\t\t\t\temail: profile.email,\n\t\t\t\t\t\t\timage: profile.picture,\n\t\t\t\t\t\t\temailVerified: profile.email_verified,\n\t\t\t\t\t\t\t...userMap,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tdata: enrichedProfile,\n\t\t\t\t\t};\n\t\t\t\t} catch (error) {\n\t\t\t\t\tlogger.error(\"Failed to decode ID token:\", error);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (token.accessToken) {\n\t\t\t\ttry {\n\t\t\t\t\tconst { data: userInfo } = await betterFetch<CognitoProfile>(\n\t\t\t\t\t\tuserInfoEndpoint,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\t\tAuthorization: `Bearer ${token.accessToken}`,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\n\t\t\t\t\tif (userInfo) {\n\t\t\t\t\t\tconst userMap = await options.mapProfileToUser?.(userInfo);\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tuser: {\n\t\t\t\t\t\t\t\tid: userInfo.sub,\n\t\t\t\t\t\t\t\tname: userInfo.name || userInfo.given_name || userInfo.username,\n\t\t\t\t\t\t\t\temail: userInfo.email,\n\t\t\t\t\t\t\t\timage: userInfo.picture,\n\t\t\t\t\t\t\t\temailVerified: userInfo.email_verified,\n\t\t\t\t\t\t\t\t...userMap,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tdata: userInfo,\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t} catch (error) {\n\t\t\t\t\tlogger.error(\"Failed to fetch user info from Cognito:\", error);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn null;\n\t\t},\n\n\t\toptions,\n\t} satisfies OAuthProvider<CognitoProfile>;\n};\n\nexport const getCognitoPublicKey = async (\n\tkid: string,\n\tregion: string,\n\tuserPoolId: string,\n) => {\n\tconst COGNITO_JWKS_URI = `https://cognito-idp.${region}.amazonaws.com/${userPoolId}/.well-known/jwks.json`;\n\n\ttry {\n\t\tconst { data } = await betterFetch<{\n\t\t\tkeys: Array<{\n\t\t\t\tkid: string;\n\t\t\t\talg: string;\n\t\t\t\tkty: string;\n\t\t\t\tuse: string;\n\t\t\t\tn: string;\n\t\t\t\te: string;\n\t\t\t}>;\n\t\t}>(COGNITO_JWKS_URI);\n\n\t\tif (!data?.keys) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"Keys not found\",\n\t\t\t});\n\t\t}\n\n\t\tconst jwk = data.keys.find((key) => key.kid === kid);\n\t\tif (!jwk) {\n\t\t\tthrow new Error(`JWK with kid ${kid} not found`);\n\t\t}\n\n\t\treturn await importJWK(jwk, jwk.alg);\n\t} catch (error) {\n\t\tlogger.error(\"Failed to fetch Cognito public key:\", error);\n\t\tthrow error;\n\t}\n};\n"],"mappings":";;;;;;;;;;;;AA8CA,MAAa,WAAW,YAA4B;AACnD,KAAI,CAAC,QAAQ,UAAU,CAAC,QAAQ,UAAU,CAAC,QAAQ,YAAY;AAC9D,SAAO,MACN,2GACA;AACD,QAAM,IAAI,gBAAgB,6BAA6B;;CAGxD,MAAM,cAAc,QAAQ,OAAO,QAAQ,gBAAgB,GAAG;CAC9D,MAAM,wBAAwB,WAAW,YAAY;CACrD,MAAM,gBAAgB,WAAW,YAAY;CAC7C,MAAM,mBAAmB,WAAW,YAAY;AAEhD,QAAO;EACN,IAAI;EACJ,MAAM;EACN,MAAM,uBAAuB,EAAE,OAAO,QAAQ,cAAc,eAAe;AAC1E,OAAI,CAAC,QAAQ,UAAU;AACtB,WAAO,MACN,qFACA;AACD,UAAM,IAAI,gBAAgB,gCAAgC;;AAG3D,OAAI,QAAQ,uBAAuB,CAAC,QAAQ,cAAc;AACzD,WAAO,MACN,sGACA;AACD,UAAM,IAAI,gBAAgB,yBAAyB;;GAEpD,MAAM,UAAU,QAAQ,sBACrB,EAAE,GACF;IAAC;IAAU;IAAW;IAAQ;AACjC,OAAI,QAAQ,MAAO,SAAQ,KAAK,GAAG,QAAQ,MAAM;AACjD,OAAI,OAAQ,SAAQ,KAAK,GAAG,OAAO;GAEnC,MAAM,MAAM,MAAM,uBAAuB;IACxC,IAAI;IACJ,SAAS,EACR,GAAG,SACH;IACD;IACA,QAAQ;IACR;IACA;IACA;IACA,QAAQ,QAAQ;IAChB,CAAC;GAGF,MAAM,aAAa,IAAI,aAAa,IAAI,QAAQ;AAChD,OAAI,YAAY;AACf,QAAI,aAAa,OAAO,QAAQ;IAChC,MAAM,eAAe,mBAAmB,WAAW;IAEnD,MAAM,YAAY,IAAI,UAAU;IAChC,MAAM,YAAY,UAAU,SAAS,IAAI,GAAG,MAAM;AAClD,WAAO,IAAI,IAAI,GAAG,YAAY,UAAU,QAAQ,eAAe;;AAEhE,UAAO;;EAGR,2BAA2B,OAAO,EAAE,MAAM,cAAc,kBAAkB;AACzE,UAAO,0BAA0B;IAChC;IACA;IACA;IACA;IACA;IACA,CAAC;;EAGH,oBAAoB,QAAQ,qBACzB,QAAQ,qBACR,OAAO,iBAAiB;AACxB,UAAO,mBAAmB;IACzB;IACA,SAAS;KACR,UAAU,QAAQ;KAClB,WAAW,QAAQ;KACnB,cAAc,QAAQ;KACtB;IACD;IACA,CAAC;;EAGL,MAAM,cAAc,OAAO,OAAO;AACjC,OAAI,QAAQ,qBACX,QAAO;AAER,OAAI,QAAQ,cACX,QAAO,QAAQ,cAAc,OAAO,MAAM;AAG3C,OAAI;IAEH,MAAM,EAAE,KAAK,KAAK,WADI,sBAAsB,MAAM;AAElD,QAAI,CAAC,OAAO,CAAC,OAAQ,QAAO;IAE5B,MAAM,YAAY,MAAM,oBACvB,KACA,QAAQ,QACR,QAAQ,WACR;IACD,MAAM,iBAAiB,uBAAuB,QAAQ,OAAO,iBAAiB,QAAQ;IAEtF,MAAM,EAAE,SAAS,cAAc,MAAM,UAAU,OAAO,WAAW;KAChE,YAAY,CAAC,OAAO;KACpB,QAAQ;KACR,UAAU,QAAQ;KAClB,aAAa;KACb,CAAC;AAEF,QAAI,SAAS,UAAU,UAAU,MAChC,QAAO;AAER,WAAO;YACC,OAAO;AACf,WAAO,MAAM,8BAA8B,MAAM;AACjD,WAAO;;;EAIT,MAAM,YAAY,OAAO;AACxB,OAAI,QAAQ,YACX,QAAO,QAAQ,YAAY,MAAM;AAGlC,OAAI,MAAM,QACT,KAAI;IACH,MAAM,UAAU,UAA0B,MAAM,QAAQ;AACxD,QAAI,CAAC,QACJ,QAAO;IAER,MAAM,OACL,QAAQ,QACR,QAAQ,cACR,QAAQ,YACR,QAAQ;IACT,MAAM,kBAAkB;KACvB,GAAG;KACH;KACA;IACD,MAAM,UAAU,MAAM,QAAQ,mBAAmB,gBAAgB;AAEjE,WAAO;KACN,MAAM;MACL,IAAI,QAAQ;MACZ,MAAM,gBAAgB;MACtB,OAAO,QAAQ;MACf,OAAO,QAAQ;MACf,eAAe,QAAQ;MACvB,GAAG;MACH;KACD,MAAM;KACN;YACO,OAAO;AACf,WAAO,MAAM,8BAA8B,MAAM;;AAInD,OAAI,MAAM,YACT,KAAI;IACH,MAAM,EAAE,MAAM,aAAa,MAAM,YAChC,kBACA,EACC,SAAS,EACR,eAAe,UAAU,MAAM,eAC/B,EACD,CACD;AAED,QAAI,UAAU;KACb,MAAM,UAAU,MAAM,QAAQ,mBAAmB,SAAS;AAC1D,YAAO;MACN,MAAM;OACL,IAAI,SAAS;OACb,MAAM,SAAS,QAAQ,SAAS,cAAc,SAAS;OACvD,OAAO,SAAS;OAChB,OAAO,SAAS;OAChB,eAAe,SAAS;OACxB,GAAG;OACH;MACD,MAAM;MACN;;YAEM,OAAO;AACf,WAAO,MAAM,2CAA2C,MAAM;;AAIhE,UAAO;;EAGR;EACA;;AAGF,MAAa,sBAAsB,OAClC,KACA,QACA,eACI;CACJ,MAAM,mBAAmB,uBAAuB,OAAO,iBAAiB,WAAW;AAEnF,KAAI;EACH,MAAM,EAAE,SAAS,MAAM,YASpB,iBAAiB;AAEpB,MAAI,CAAC,MAAM,KACV,OAAM,IAAI,SAAS,eAAe,EACjC,SAAS,kBACT,CAAC;EAGH,MAAM,MAAM,KAAK,KAAK,MAAM,QAAQ,IAAI,QAAQ,IAAI;AACpD,MAAI,CAAC,IACJ,OAAM,IAAI,MAAM,gBAAgB,IAAI,YAAY;AAGjD,SAAO,MAAM,UAAU,KAAK,IAAI,IAAI;UAC5B,OAAO;AACf,SAAO,MAAM,uCAAuC,MAAM;AAC1D,QAAM"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discord.mjs","names":[],"sources":["../../src/social-providers/discord.ts"],"sourcesContent":["import { betterFetch } from \"@better-fetch/fetch\";\nimport type { OAuthProvider, ProviderOptions } from \"../oauth2\";\nimport { refreshAccessToken, validateAuthorizationCode } from \"../oauth2\";\nexport interface DiscordProfile extends Record<string, any> {\n\t/** the user's id (i.e. the numerical snowflake) */\n\tid: string;\n\t/** the user's username, not unique across the platform */\n\tusername: string;\n\t/** the user's Discord-tag */\n\tdiscriminator: string;\n\t/** the user's display name, if it is set */\n\tglobal_name: string | null;\n\t/**\n\t * the user's avatar hash:\n\t * https://discord.com/developers/docs/reference#image-formatting\n\t */\n\tavatar: string | null;\n\t/** whether the user belongs to an OAuth2 application */\n\tbot?: boolean | undefined;\n\t/**\n\t * whether the user is an Official Discord System user (part of the urgent\n\t * message system)\n\t */\n\tsystem?: boolean | undefined;\n\t/** whether the user has two factor enabled on their account */\n\tmfa_enabled: boolean;\n\t/**\n\t * the user's banner hash:\n\t * https://discord.com/developers/docs/reference#image-formatting\n\t */\n\tbanner: string | null;\n\n\t/** the user's banner color encoded as an integer representation of hexadecimal color code */\n\taccent_color: number | null;\n\n\t/**\n\t * the user's chosen language option:\n\t * https://discord.com/developers/docs/reference#locales\n\t */\n\tlocale: string;\n\t/** whether the email on this account has been verified */\n\tverified: boolean;\n\t/** the user's email */\n\temail: string;\n\t/**\n\t * the flags on a user's account:\n\t * https://discord.com/developers/docs/resources/user#user-object-user-flags\n\t */\n\tflags: number;\n\t/**\n\t * the type of Nitro subscription on a user's account:\n\t * https://discord.com/developers/docs/resources/user#user-object-premium-types\n\t */\n\tpremium_type: number;\n\t/**\n\t * the public flags on a user's account:\n\t * https://discord.com/developers/docs/resources/user#user-object-user-flags\n\t */\n\tpublic_flags: number;\n\t/** undocumented field; corresponds to the user's custom nickname */\n\tdisplay_name: string | null;\n\t/**\n\t * undocumented field; corresponds to the Discord feature where you can e.g.\n\t * put your avatar inside of an ice cube\n\t */\n\tavatar_decoration: string | null;\n\t/**\n\t * undocumented field; corresponds to the premium feature where you can\n\t * select a custom banner color\n\t */\n\tbanner_color: string | null;\n\t/** undocumented field; the CDN URL of their profile picture */\n\timage_url: string;\n}\n\nexport interface DiscordOptions extends ProviderOptions<DiscordProfile> {\n\tclientId: string;\n\tprompt?: (\"none\" | \"consent\") | undefined;\n\tpermissions?: number | undefined;\n}\n\nexport const discord = (options: DiscordOptions) => {\n\treturn {\n\t\tid: \"discord\",\n\t\tname: \"Discord\",\n\t\tcreateAuthorizationURL({ state, scopes, redirectURI }) {\n\t\t\tconst _scopes = options.disableDefaultScope ? [] : [\"identify\", \"email\"];\n\t\t\tif (scopes) _scopes.push(...scopes);\n\t\t\tif (options.scope) _scopes.push(...options.scope);\n\t\t\tconst hasBotScope = _scopes.includes(\"bot\");\n\t\t\tconst permissionsParam =\n\t\t\t\thasBotScope && options.permissions !== undefined\n\t\t\t\t\t? `&permissions=${options.permissions}`\n\t\t\t\t\t: \"\";\n\t\t\treturn new URL(\n\t\t\t\t`https://discord.com/api/oauth2/authorize?scope=${_scopes.join(\n\t\t\t\t\t\"+\",\n\t\t\t\t)}&response_type=code&client_id=${\n\t\t\t\t\toptions.clientId\n\t\t\t\t}&redirect_uri=${encodeURIComponent(\n\t\t\t\t\toptions.redirectURI || redirectURI,\n\t\t\t\t)}&state=${state}&prompt=${\n\t\t\t\t\toptions.prompt || \"none\"\n\t\t\t\t}${permissionsParam}`,\n\t\t\t);\n\t\t},\n\t\tvalidateAuthorizationCode: async ({ code, redirectURI }) => {\n\t\t\treturn validateAuthorizationCode({\n\t\t\t\tcode,\n\t\t\t\tredirectURI,\n\t\t\t\toptions,\n\t\t\t\ttokenEndpoint: \"https://discord.com/api/oauth2/token\",\n\t\t\t});\n\t\t},\n\t\trefreshAccessToken: options.refreshAccessToken\n\t\t\t? options.refreshAccessToken\n\t\t\t: async (refreshToken) => {\n\t\t\t\t\treturn refreshAccessToken({\n\t\t\t\t\t\trefreshToken,\n\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\tclientId: options.clientId,\n\t\t\t\t\t\t\tclientKey: options.clientKey,\n\t\t\t\t\t\t\tclientSecret: options.clientSecret,\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttokenEndpoint: \"https://discord.com/api/oauth2/token\",\n\t\t\t\t\t});\n\t\t\t\t},\n\t\tasync getUserInfo(token) {\n\t\t\tif (options.getUserInfo) {\n\t\t\t\treturn options.getUserInfo(token);\n\t\t\t}\n\t\t\tconst { data: profile, error } = await betterFetch<DiscordProfile>(\n\t\t\t\t\"https://discord.com/api/users/@me\",\n\t\t\t\t{\n\t\t\t\t\theaders: {\n\t\t\t\t\t\tauthorization: `Bearer ${token.accessToken}`,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tif (error) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tif (profile.avatar === null) {\n\t\t\t\tconst defaultAvatarNumber =\n\t\t\t\t\tprofile.discriminator === \"0\"\n\t\t\t\t\t\t? Number(BigInt(profile.id) >> BigInt(22)) % 6\n\t\t\t\t\t\t: parseInt(profile.discriminator) % 5;\n\t\t\t\tprofile.image_url = `https://cdn.discordapp.com/embed/avatars/${defaultAvatarNumber}.png`;\n\t\t\t} else {\n\t\t\t\tconst format = profile.avatar.startsWith(\"a_\") ? \"gif\" : \"png\";\n\t\t\t\tprofile.image_url = `https://cdn.discordapp.com/avatars/${profile.id}/${profile.avatar}.${format}`;\n\t\t\t}\n\t\t\tconst userMap = await options.mapProfileToUser?.(profile);\n\t\t\treturn {\n\t\t\t\tuser: {\n\t\t\t\t\tid: profile.id,\n\t\t\t\t\tname: profile.global_name || profile.username || \"\",\n\t\t\t\t\temail: profile.email,\n\t\t\t\t\temailVerified: profile.verified,\n\t\t\t\t\timage: profile.image_url,\n\t\t\t\t\t...userMap,\n\t\t\t\t},\n\t\t\t\tdata: profile,\n\t\t\t};\n\t\t},\n\t\toptions,\n\t} satisfies OAuthProvider<DiscordProfile>;\n};\n"],"mappings":";;;;;;AAiFA,MAAa,WAAW,YAA4B;AACnD,QAAO;EACN,IAAI;EACJ,MAAM;EACN,uBAAuB,EAAE,OAAO,QAAQ,eAAe;GACtD,MAAM,UAAU,QAAQ,sBAAsB,EAAE,GAAG,CAAC,YAAY,QAAQ;AACxE,OAAI,OAAQ,SAAQ,KAAK,GAAG,OAAO;AACnC,OAAI,QAAQ,MAAO,SAAQ,KAAK,GAAG,QAAQ,MAAM;GAEjD,MAAM,mBADc,QAAQ,SAAS,MAAM,IAE3B,QAAQ,gBAAgB,SACpC,gBAAgB,QAAQ,gBACxB;AACJ,UAAO,IAAI,IACV,kDAAkD,QAAQ,KACzD,IACA,CAAC,gCACD,QAAQ,SACR,gBAAgB,mBAChB,QAAQ,eAAe,YACvB,CAAC,SAAS,MAAM,UAChB,QAAQ,UAAU,SAChB,mBACH;;EAEF,2BAA2B,OAAO,EAAE,MAAM,kBAAkB;AAC3D,UAAO,0BAA0B;IAChC;IACA;IACA;IACA,eAAe;IACf,CAAC;;EAEH,oBAAoB,QAAQ,qBACzB,QAAQ,qBACR,OAAO,iBAAiB;AACxB,UAAO,mBAAmB;IACzB;IACA,SAAS;KACR,UAAU,QAAQ;KAClB,WAAW,QAAQ;KACnB,cAAc,QAAQ;KACtB;IACD,eAAe;IACf,CAAC;;EAEL,MAAM,YAAY,OAAO;AACxB,OAAI,QAAQ,YACX,QAAO,QAAQ,YAAY,MAAM;GAElC,MAAM,EAAE,MAAM,SAAS,UAAU,MAAM,YACtC,qCACA,EACC,SAAS,EACR,eAAe,UAAU,MAAM,eAC/B,EACD,CACD;AAED,OAAI,MACH,QAAO;AAER,OAAI,QAAQ,WAAW,KAKtB,SAAQ,YAAY,4CAHnB,QAAQ,kBAAkB,MACvB,OAAO,OAAO,QAAQ,GAAG,IAAI,OAAO,GAAG,CAAC,GAAG,IAC3C,SAAS,QAAQ,cAAc,GAAG,EAC8C;QAC9E;IACN,MAAM,SAAS,QAAQ,OAAO,WAAW,KAAK,GAAG,QAAQ;AACzD,YAAQ,YAAY,sCAAsC,QAAQ,GAAG,GAAG,QAAQ,OAAO,GAAG;;GAE3F,MAAM,UAAU,MAAM,QAAQ,mBAAmB,QAAQ;AACzD,UAAO;IACN,MAAM;KACL,IAAI,QAAQ;KACZ,MAAM,QAAQ,eAAe,QAAQ,YAAY;KACjD,OAAO,QAAQ;KACf,eAAe,QAAQ;KACvB,OAAO,QAAQ;KACf,GAAG;KACH;IACD,MAAM;IACN;;EAEF;EACA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dropbox.mjs","names":["additionalParams: Record<string, string>"],"sources":["../../src/social-providers/dropbox.ts"],"sourcesContent":["import { betterFetch } from \"@better-fetch/fetch\";\nimport type { OAuthProvider, ProviderOptions } from \"../oauth2\";\nimport {\n\tcreateAuthorizationURL,\n\trefreshAccessToken,\n\tvalidateAuthorizationCode,\n} from \"../oauth2\";\n\nexport interface DropboxProfile {\n\taccount_id: string;\n\tname: {\n\t\tgiven_name: string;\n\t\tsurname: string;\n\t\tfamiliar_name: string;\n\t\tdisplay_name: string;\n\t\tabbreviated_name: string;\n\t};\n\temail: string;\n\temail_verified: boolean;\n\tprofile_photo_url: string;\n}\n\nexport interface DropboxOptions extends ProviderOptions<DropboxProfile> {\n\tclientId: string;\n\taccessType?: (\"offline\" | \"online\" | \"legacy\") | undefined;\n}\n\nexport const dropbox = (options: DropboxOptions) => {\n\tconst tokenEndpoint = \"https://api.dropboxapi.com/oauth2/token\";\n\n\treturn {\n\t\tid: \"dropbox\",\n\t\tname: \"Dropbox\",\n\t\tcreateAuthorizationURL: async ({\n\t\t\tstate,\n\t\t\tscopes,\n\t\t\tcodeVerifier,\n\t\t\tredirectURI,\n\t\t}) => {\n\t\t\tconst _scopes = options.disableDefaultScope ? [] : [\"account_info.read\"];\n\t\t\tif (options.scope) _scopes.push(...options.scope);\n\t\t\tif (scopes) _scopes.push(...scopes);\n\t\t\tconst additionalParams: Record<string, string> = {};\n\t\t\tif (options.accessType) {\n\t\t\t\tadditionalParams.token_access_type = options.accessType;\n\t\t\t}\n\t\t\treturn await createAuthorizationURL({\n\t\t\t\tid: \"dropbox\",\n\t\t\t\toptions,\n\t\t\t\tauthorizationEndpoint: \"https://www.dropbox.com/oauth2/authorize\",\n\t\t\t\tscopes: _scopes,\n\t\t\t\tstate,\n\t\t\t\tredirectURI,\n\t\t\t\tcodeVerifier,\n\t\t\t\tadditionalParams,\n\t\t\t});\n\t\t},\n\t\tvalidateAuthorizationCode: async ({ code, codeVerifier, redirectURI }) => {\n\t\t\treturn await validateAuthorizationCode({\n\t\t\t\tcode,\n\t\t\t\tcodeVerifier,\n\t\t\t\tredirectURI,\n\t\t\t\toptions,\n\t\t\t\ttokenEndpoint,\n\t\t\t});\n\t\t},\n\t\trefreshAccessToken: options.refreshAccessToken\n\t\t\t? options.refreshAccessToken\n\t\t\t: async (refreshToken) => {\n\t\t\t\t\treturn refreshAccessToken({\n\t\t\t\t\t\trefreshToken,\n\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\tclientId: options.clientId,\n\t\t\t\t\t\t\tclientKey: options.clientKey,\n\t\t\t\t\t\t\tclientSecret: options.clientSecret,\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttokenEndpoint: \"https://api.dropbox.com/oauth2/token\",\n\t\t\t\t\t});\n\t\t\t\t},\n\t\tasync getUserInfo(token) {\n\t\t\tif (options.getUserInfo) {\n\t\t\t\treturn options.getUserInfo(token);\n\t\t\t}\n\t\t\tconst { data: profile, error } = await betterFetch<DropboxProfile>(\n\t\t\t\t\"https://api.dropboxapi.com/2/users/get_current_account\",\n\t\t\t\t{\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\theaders: {\n\t\t\t\t\t\tAuthorization: `Bearer ${token.accessToken}`,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tif (error) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst userMap = await options.mapProfileToUser?.(profile);\n\t\t\treturn {\n\t\t\t\tuser: {\n\t\t\t\t\tid: profile.account_id,\n\t\t\t\t\tname: profile.name?.display_name,\n\t\t\t\t\temail: profile.email,\n\t\t\t\t\temailVerified: profile.email_verified || false,\n\t\t\t\t\timage: profile.profile_photo_url,\n\t\t\t\t\t...userMap,\n\t\t\t\t},\n\t\t\t\tdata: profile,\n\t\t\t};\n\t\t},\n\t\toptions,\n\t} satisfies OAuthProvider<DropboxProfile>;\n};\n"],"mappings":";;;;;;;AA2BA,MAAa,WAAW,YAA4B;CACnD,MAAM,gBAAgB;AAEtB,QAAO;EACN,IAAI;EACJ,MAAM;EACN,wBAAwB,OAAO,EAC9B,OACA,QACA,cACA,kBACK;GACL,MAAM,UAAU,QAAQ,sBAAsB,EAAE,GAAG,CAAC,oBAAoB;AACxE,OAAI,QAAQ,MAAO,SAAQ,KAAK,GAAG,QAAQ,MAAM;AACjD,OAAI,OAAQ,SAAQ,KAAK,GAAG,OAAO;GACnC,MAAMA,mBAA2C,EAAE;AACnD,OAAI,QAAQ,WACX,kBAAiB,oBAAoB,QAAQ;AAE9C,UAAO,MAAM,uBAAuB;IACnC,IAAI;IACJ;IACA,uBAAuB;IACvB,QAAQ;IACR;IACA;IACA;IACA;IACA,CAAC;;EAEH,2BAA2B,OAAO,EAAE,MAAM,cAAc,kBAAkB;AACzE,UAAO,MAAM,0BAA0B;IACtC;IACA;IACA;IACA;IACA;IACA,CAAC;;EAEH,oBAAoB,QAAQ,qBACzB,QAAQ,qBACR,OAAO,iBAAiB;AACxB,UAAO,mBAAmB;IACzB;IACA,SAAS;KACR,UAAU,QAAQ;KAClB,WAAW,QAAQ;KACnB,cAAc,QAAQ;KACtB;IACD,eAAe;IACf,CAAC;;EAEL,MAAM,YAAY,OAAO;AACxB,OAAI,QAAQ,YACX,QAAO,QAAQ,YAAY,MAAM;GAElC,MAAM,EAAE,MAAM,SAAS,UAAU,MAAM,YACtC,0DACA;IACC,QAAQ;IACR,SAAS,EACR,eAAe,UAAU,MAAM,eAC/B;IACD,CACD;AAED,OAAI,MACH,QAAO;GAER,MAAM,UAAU,MAAM,QAAQ,mBAAmB,QAAQ;AACzD,UAAO;IACN,MAAM;KACL,IAAI,QAAQ;KACZ,MAAM,QAAQ,MAAM;KACpB,OAAO,QAAQ;KACf,eAAe,QAAQ,kBAAkB;KACzC,OAAO,QAAQ;KACf,GAAG;KACH;IACD,MAAM;IACN;;EAEF;EACA"}
|
|
@@ -17,7 +17,7 @@ const facebook = (options) => {
|
|
|
17
17
|
return await createAuthorizationURL({
|
|
18
18
|
id: "facebook",
|
|
19
19
|
options,
|
|
20
|
-
authorizationEndpoint: "https://www.facebook.com/
|
|
20
|
+
authorizationEndpoint: "https://www.facebook.com/v24.0/dialog/oauth",
|
|
21
21
|
scopes: _scopes,
|
|
22
22
|
state,
|
|
23
23
|
redirectURI,
|
|
@@ -30,7 +30,7 @@ const facebook = (options) => {
|
|
|
30
30
|
code,
|
|
31
31
|
redirectURI,
|
|
32
32
|
options,
|
|
33
|
-
tokenEndpoint: "https://graph.facebook.com/oauth/access_token"
|
|
33
|
+
tokenEndpoint: "https://graph.facebook.com/v24.0/oauth/access_token"
|
|
34
34
|
});
|
|
35
35
|
},
|
|
36
36
|
async verifyIdToken(token, nonce) {
|
|
@@ -57,7 +57,7 @@ const facebook = (options) => {
|
|
|
57
57
|
clientKey: options.clientKey,
|
|
58
58
|
clientSecret: options.clientSecret
|
|
59
59
|
},
|
|
60
|
-
tokenEndpoint: "https://graph.facebook.com/
|
|
60
|
+
tokenEndpoint: "https://graph.facebook.com/v24.0/oauth/access_token"
|
|
61
61
|
});
|
|
62
62
|
},
|
|
63
63
|
async getUserInfo(token) {
|
|
@@ -117,4 +117,5 @@ const facebook = (options) => {
|
|
|
117
117
|
};
|
|
118
118
|
|
|
119
119
|
//#endregion
|
|
120
|
-
export { facebook };
|
|
120
|
+
export { facebook };
|
|
121
|
+
//# sourceMappingURL=facebook.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"facebook.mjs","names":["profile","userMap"],"sources":["../../src/social-providers/facebook.ts"],"sourcesContent":["import { betterFetch } from \"@better-fetch/fetch\";\nimport { createRemoteJWKSet, decodeJwt, jwtVerify } from \"jose\";\nimport type { OAuthProvider, ProviderOptions } from \"../oauth2\";\nimport {\n\tcreateAuthorizationURL,\n\trefreshAccessToken,\n\tvalidateAuthorizationCode,\n} from \"../oauth2\";\nexport interface FacebookProfile {\n\tid: string;\n\tname: string;\n\temail: string;\n\temail_verified: boolean;\n\tpicture: {\n\t\tdata: {\n\t\t\theight: number;\n\t\t\tis_silhouette: boolean;\n\t\t\turl: string;\n\t\t\twidth: number;\n\t\t};\n\t};\n}\n\nexport interface FacebookOptions extends ProviderOptions<FacebookProfile> {\n\tclientId: string;\n\t/**\n\t * Extend list of fields to retrieve from the Facebook user profile.\n\t *\n\t * @default [\"id\", \"name\", \"email\", \"picture\"]\n\t */\n\tfields?: string[] | undefined;\n\n\t/**\n\t * The config id to use when undergoing oauth\n\t */\n\tconfigId?: string | undefined;\n}\n\nexport const facebook = (options: FacebookOptions) => {\n\treturn {\n\t\tid: \"facebook\",\n\t\tname: \"Facebook\",\n\t\tasync createAuthorizationURL({ state, scopes, redirectURI, loginHint }) {\n\t\t\tconst _scopes = options.disableDefaultScope\n\t\t\t\t? []\n\t\t\t\t: [\"email\", \"public_profile\"];\n\t\t\tif (options.scope) _scopes.push(...options.scope);\n\t\t\tif (scopes) _scopes.push(...scopes);\n\t\t\treturn await createAuthorizationURL({\n\t\t\t\tid: \"facebook\",\n\t\t\t\toptions,\n\t\t\t\tauthorizationEndpoint: \"https://www.facebook.com/v24.0/dialog/oauth\",\n\t\t\t\tscopes: _scopes,\n\t\t\t\tstate,\n\t\t\t\tredirectURI,\n\t\t\t\tloginHint,\n\t\t\t\tadditionalParams: options.configId\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tconfig_id: options.configId,\n\t\t\t\t\t\t}\n\t\t\t\t\t: {},\n\t\t\t});\n\t\t},\n\t\tvalidateAuthorizationCode: async ({ code, redirectURI }) => {\n\t\t\treturn validateAuthorizationCode({\n\t\t\t\tcode,\n\t\t\t\tredirectURI,\n\t\t\t\toptions,\n\t\t\t\ttokenEndpoint: \"https://graph.facebook.com/v24.0/oauth/access_token\",\n\t\t\t});\n\t\t},\n\t\tasync verifyIdToken(token, nonce) {\n\t\t\tif (options.disableIdTokenSignIn) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tif (options.verifyIdToken) {\n\t\t\t\treturn options.verifyIdToken(token, nonce);\n\t\t\t}\n\n\t\t\t/* limited login */\n\t\t\t// check is limited token\n\t\t\tif (token.split(\".\").length === 3) {\n\t\t\t\ttry {\n\t\t\t\t\tconst { payload: jwtClaims } = await jwtVerify(\n\t\t\t\t\t\ttoken,\n\t\t\t\t\t\tcreateRemoteJWKSet(\n\t\t\t\t\t\t\t// https://developers.facebook.com/docs/facebook-login/limited-login/token/#jwks\n\t\t\t\t\t\t\tnew URL(\n\t\t\t\t\t\t\t\t\"https://limited.facebook.com/.well-known/oauth/openid/jwks/\",\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t),\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\talgorithms: [\"RS256\"],\n\t\t\t\t\t\t\taudience: options.clientId,\n\t\t\t\t\t\t\tissuer: \"https://www.facebook.com\",\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\n\t\t\t\t\tif (nonce && jwtClaims.nonce !== nonce) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn !!jwtClaims;\n\t\t\t\t} catch {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/* access_token */\n\t\t\treturn true;\n\t\t},\n\t\trefreshAccessToken: options.refreshAccessToken\n\t\t\t? options.refreshAccessToken\n\t\t\t: async (refreshToken) => {\n\t\t\t\t\treturn refreshAccessToken({\n\t\t\t\t\t\trefreshToken,\n\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\tclientId: options.clientId,\n\t\t\t\t\t\t\tclientKey: options.clientKey,\n\t\t\t\t\t\t\tclientSecret: options.clientSecret,\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttokenEndpoint:\n\t\t\t\t\t\t\t\"https://graph.facebook.com/v24.0/oauth/access_token\",\n\t\t\t\t\t});\n\t\t\t\t},\n\t\tasync getUserInfo(token) {\n\t\t\tif (options.getUserInfo) {\n\t\t\t\treturn options.getUserInfo(token);\n\t\t\t}\n\n\t\t\tif (token.idToken && token.idToken.split(\".\").length === 3) {\n\t\t\t\tconst profile = decodeJwt(token.idToken) as {\n\t\t\t\t\tsub: string;\n\t\t\t\t\temail: string;\n\t\t\t\t\tname: string;\n\t\t\t\t\tpicture: string;\n\t\t\t\t};\n\n\t\t\t\tconst user = {\n\t\t\t\t\tid: profile.sub,\n\t\t\t\t\tname: profile.name,\n\t\t\t\t\temail: profile.email,\n\t\t\t\t\tpicture: {\n\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\turl: profile.picture,\n\t\t\t\t\t\t\theight: 100,\n\t\t\t\t\t\t\twidth: 100,\n\t\t\t\t\t\t\tis_silhouette: false,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t};\n\n\t\t\t\t// https://developers.facebook.com/docs/facebook-login/limited-login/permissions\n\t\t\t\t// Facebook ID token does not include email_verified claim.\n\t\t\t\t// We default to false for security consistency.\n\t\t\t\tconst userMap = await options.mapProfileToUser?.({\n\t\t\t\t\t...user,\n\t\t\t\t\temail_verified: false,\n\t\t\t\t});\n\n\t\t\t\treturn {\n\t\t\t\t\tuser: {\n\t\t\t\t\t\t...user,\n\t\t\t\t\t\temailVerified: false,\n\t\t\t\t\t\t...userMap,\n\t\t\t\t\t},\n\t\t\t\t\tdata: profile,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst fields = [\n\t\t\t\t\"id\",\n\t\t\t\t\"name\",\n\t\t\t\t\"email\",\n\t\t\t\t\"picture\",\n\t\t\t\t...(options?.fields || []),\n\t\t\t];\n\t\t\tconst { data: profile, error } = await betterFetch<FacebookProfile>(\n\t\t\t\t\"https://graph.facebook.com/me?fields=\" + fields.join(\",\"),\n\t\t\t\t{\n\t\t\t\t\tauth: {\n\t\t\t\t\t\ttype: \"Bearer\",\n\t\t\t\t\t\ttoken: token.accessToken,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\t\t\tif (error) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst userMap = await options.mapProfileToUser?.(profile);\n\t\t\treturn {\n\t\t\t\tuser: {\n\t\t\t\t\tid: profile.id,\n\t\t\t\t\tname: profile.name,\n\t\t\t\t\temail: profile.email,\n\t\t\t\t\timage: profile.picture.data.url,\n\t\t\t\t\temailVerified: profile.email_verified,\n\t\t\t\t\t...userMap,\n\t\t\t\t},\n\t\t\t\tdata: profile,\n\t\t\t};\n\t\t},\n\t\toptions,\n\t} satisfies OAuthProvider<FacebookProfile>;\n};\n"],"mappings":";;;;;;;;AAsCA,MAAa,YAAY,YAA6B;AACrD,QAAO;EACN,IAAI;EACJ,MAAM;EACN,MAAM,uBAAuB,EAAE,OAAO,QAAQ,aAAa,aAAa;GACvE,MAAM,UAAU,QAAQ,sBACrB,EAAE,GACF,CAAC,SAAS,iBAAiB;AAC9B,OAAI,QAAQ,MAAO,SAAQ,KAAK,GAAG,QAAQ,MAAM;AACjD,OAAI,OAAQ,SAAQ,KAAK,GAAG,OAAO;AACnC,UAAO,MAAM,uBAAuB;IACnC,IAAI;IACJ;IACA,uBAAuB;IACvB,QAAQ;IACR;IACA;IACA;IACA,kBAAkB,QAAQ,WACvB,EACA,WAAW,QAAQ,UACnB,GACA,EAAE;IACL,CAAC;;EAEH,2BAA2B,OAAO,EAAE,MAAM,kBAAkB;AAC3D,UAAO,0BAA0B;IAChC;IACA;IACA;IACA,eAAe;IACf,CAAC;;EAEH,MAAM,cAAc,OAAO,OAAO;AACjC,OAAI,QAAQ,qBACX,QAAO;AAGR,OAAI,QAAQ,cACX,QAAO,QAAQ,cAAc,OAAO,MAAM;AAK3C,OAAI,MAAM,MAAM,IAAI,CAAC,WAAW,EAC/B,KAAI;IACH,MAAM,EAAE,SAAS,cAAc,MAAM,UACpC,OACA,mBAEC,IAAI,IACH,8DACA,CACD,EACD;KACC,YAAY,CAAC,QAAQ;KACrB,UAAU,QAAQ;KAClB,QAAQ;KACR,CACD;AAED,QAAI,SAAS,UAAU,UAAU,MAChC,QAAO;AAGR,WAAO,CAAC,CAAC;WACF;AACP,WAAO;;AAKT,UAAO;;EAER,oBAAoB,QAAQ,qBACzB,QAAQ,qBACR,OAAO,iBAAiB;AACxB,UAAO,mBAAmB;IACzB;IACA,SAAS;KACR,UAAU,QAAQ;KAClB,WAAW,QAAQ;KACnB,cAAc,QAAQ;KACtB;IACD,eACC;IACD,CAAC;;EAEL,MAAM,YAAY,OAAO;AACxB,OAAI,QAAQ,YACX,QAAO,QAAQ,YAAY,MAAM;AAGlC,OAAI,MAAM,WAAW,MAAM,QAAQ,MAAM,IAAI,CAAC,WAAW,GAAG;IAC3D,MAAMA,YAAU,UAAU,MAAM,QAAQ;IAOxC,MAAM,OAAO;KACZ,IAAIA,UAAQ;KACZ,MAAMA,UAAQ;KACd,OAAOA,UAAQ;KACf,SAAS,EACR,MAAM;MACL,KAAKA,UAAQ;MACb,QAAQ;MACR,OAAO;MACP,eAAe;MACf,EACD;KACD;IAKD,MAAMC,YAAU,MAAM,QAAQ,mBAAmB;KAChD,GAAG;KACH,gBAAgB;KAChB,CAAC;AAEF,WAAO;KACN,MAAM;MACL,GAAG;MACH,eAAe;MACf,GAAGA;MACH;KACD,MAAMD;KACN;;GAUF,MAAM,EAAE,MAAM,SAAS,UAAU,MAAM,YACtC,0CARc;IACd;IACA;IACA;IACA;IACA,GAAI,SAAS,UAAU,EAAE;IACzB,CAEiD,KAAK,IAAI,EAC1D,EACC,MAAM;IACL,MAAM;IACN,OAAO,MAAM;IACb,EACD,CACD;AACD,OAAI,MACH,QAAO;GAER,MAAM,UAAU,MAAM,QAAQ,mBAAmB,QAAQ;AACzD,UAAO;IACN,MAAM;KACL,IAAI,QAAQ;KACZ,MAAM,QAAQ;KACd,OAAO,QAAQ;KACf,OAAO,QAAQ,QAAQ,KAAK;KAC5B,eAAe,QAAQ;KACvB,GAAG;KACH;IACD,MAAM;IACN;;EAEF;EACA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"figma.mjs","names":[],"sources":["../../src/social-providers/figma.ts"],"sourcesContent":["import { betterFetch } from \"@better-fetch/fetch\";\nimport { logger } from \"../env\";\nimport { BetterAuthError } from \"../error\";\nimport type { OAuthProvider, ProviderOptions } from \"../oauth2\";\nimport {\n\tcreateAuthorizationURL,\n\trefreshAccessToken,\n\tvalidateAuthorizationCode,\n} from \"../oauth2\";\n\nexport interface FigmaProfile {\n\tid: string;\n\temail: string;\n\thandle: string;\n\timg_url: string;\n}\n\nexport interface FigmaOptions extends ProviderOptions<FigmaProfile> {\n\tclientId: string;\n}\n\nexport const figma = (options: FigmaOptions) => {\n\treturn {\n\t\tid: \"figma\",\n\t\tname: \"Figma\",\n\t\tasync createAuthorizationURL({ state, scopes, codeVerifier, redirectURI }) {\n\t\t\tif (!options.clientId || !options.clientSecret) {\n\t\t\t\tlogger.error(\n\t\t\t\t\t\"Client Id and Client Secret are required for Figma. Make sure to provide them in the options.\",\n\t\t\t\t);\n\t\t\t\tthrow new BetterAuthError(\"CLIENT_ID_AND_SECRET_REQUIRED\");\n\t\t\t}\n\t\t\tif (!codeVerifier) {\n\t\t\t\tthrow new BetterAuthError(\"codeVerifier is required for Figma\");\n\t\t\t}\n\n\t\t\tconst _scopes = options.disableDefaultScope ? [] : [\"current_user:read\"];\n\t\t\tif (options.scope) _scopes.push(...options.scope);\n\t\t\tif (scopes) _scopes.push(...scopes);\n\n\t\t\tconst url = await createAuthorizationURL({\n\t\t\t\tid: \"figma\",\n\t\t\t\toptions,\n\t\t\t\tauthorizationEndpoint: \"https://www.figma.com/oauth\",\n\t\t\t\tscopes: _scopes,\n\t\t\t\tstate,\n\t\t\t\tcodeVerifier,\n\t\t\t\tredirectURI,\n\t\t\t});\n\n\t\t\treturn url;\n\t\t},\n\t\tvalidateAuthorizationCode: async ({ code, codeVerifier, redirectURI }) => {\n\t\t\treturn validateAuthorizationCode({\n\t\t\t\tcode,\n\t\t\t\tcodeVerifier,\n\t\t\t\tredirectURI,\n\t\t\t\toptions,\n\t\t\t\ttokenEndpoint: \"https://api.figma.com/v1/oauth/token\",\n\t\t\t\tauthentication: \"basic\",\n\t\t\t});\n\t\t},\n\t\trefreshAccessToken: options.refreshAccessToken\n\t\t\t? options.refreshAccessToken\n\t\t\t: async (refreshToken) => {\n\t\t\t\t\treturn refreshAccessToken({\n\t\t\t\t\t\trefreshToken,\n\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\tclientId: options.clientId,\n\t\t\t\t\t\t\tclientKey: options.clientKey,\n\t\t\t\t\t\t\tclientSecret: options.clientSecret,\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttokenEndpoint: \"https://api.figma.com/v1/oauth/token\",\n\t\t\t\t\t\tauthentication: \"basic\",\n\t\t\t\t\t});\n\t\t\t\t},\n\t\tasync getUserInfo(token) {\n\t\t\tif (options.getUserInfo) {\n\t\t\t\treturn options.getUserInfo(token);\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst { data: profile } = await betterFetch<FigmaProfile>(\n\t\t\t\t\t\"https://api.figma.com/v1/me\",\n\t\t\t\t\t{\n\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\tAuthorization: `Bearer ${token.accessToken}`,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t);\n\n\t\t\t\tif (!profile) {\n\t\t\t\t\tlogger.error(\"Failed to fetch user from Figma\");\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\tconst userMap = await options.mapProfileToUser?.(profile);\n\n\t\t\t\treturn {\n\t\t\t\t\tuser: {\n\t\t\t\t\t\tid: profile.id,\n\t\t\t\t\t\tname: profile.handle,\n\t\t\t\t\t\temail: profile.email,\n\t\t\t\t\t\timage: profile.img_url,\n\t\t\t\t\t\temailVerified: false,\n\t\t\t\t\t\t...userMap,\n\t\t\t\t\t},\n\t\t\t\t\tdata: profile,\n\t\t\t\t};\n\t\t\t} catch (error) {\n\t\t\t\tlogger.error(\"Failed to fetch user info from Figma:\", error);\n\t\t\t\treturn null;\n\t\t\t}\n\t\t},\n\t\toptions,\n\t} satisfies OAuthProvider<FigmaProfile>;\n};\n"],"mappings":";;;;;;;;;;AAqBA,MAAa,SAAS,YAA0B;AAC/C,QAAO;EACN,IAAI;EACJ,MAAM;EACN,MAAM,uBAAuB,EAAE,OAAO,QAAQ,cAAc,eAAe;AAC1E,OAAI,CAAC,QAAQ,YAAY,CAAC,QAAQ,cAAc;AAC/C,WAAO,MACN,gGACA;AACD,UAAM,IAAI,gBAAgB,gCAAgC;;AAE3D,OAAI,CAAC,aACJ,OAAM,IAAI,gBAAgB,qCAAqC;GAGhE,MAAM,UAAU,QAAQ,sBAAsB,EAAE,GAAG,CAAC,oBAAoB;AACxE,OAAI,QAAQ,MAAO,SAAQ,KAAK,GAAG,QAAQ,MAAM;AACjD,OAAI,OAAQ,SAAQ,KAAK,GAAG,OAAO;AAYnC,UAVY,MAAM,uBAAuB;IACxC,IAAI;IACJ;IACA,uBAAuB;IACvB,QAAQ;IACR;IACA;IACA;IACA,CAAC;;EAIH,2BAA2B,OAAO,EAAE,MAAM,cAAc,kBAAkB;AACzE,UAAO,0BAA0B;IAChC;IACA;IACA;IACA;IACA,eAAe;IACf,gBAAgB;IAChB,CAAC;;EAEH,oBAAoB,QAAQ,qBACzB,QAAQ,qBACR,OAAO,iBAAiB;AACxB,UAAO,mBAAmB;IACzB;IACA,SAAS;KACR,UAAU,QAAQ;KAClB,WAAW,QAAQ;KACnB,cAAc,QAAQ;KACtB;IACD,eAAe;IACf,gBAAgB;IAChB,CAAC;;EAEL,MAAM,YAAY,OAAO;AACxB,OAAI,QAAQ,YACX,QAAO,QAAQ,YAAY,MAAM;AAGlC,OAAI;IACH,MAAM,EAAE,MAAM,YAAY,MAAM,YAC/B,+BACA,EACC,SAAS,EACR,eAAe,UAAU,MAAM,eAC/B,EACD,CACD;AAED,QAAI,CAAC,SAAS;AACb,YAAO,MAAM,kCAAkC;AAC/C,YAAO;;IAGR,MAAM,UAAU,MAAM,QAAQ,mBAAmB,QAAQ;AAEzD,WAAO;KACN,MAAM;MACL,IAAI,QAAQ;MACZ,MAAM,QAAQ;MACd,OAAO,QAAQ;MACf,OAAO,QAAQ;MACf,eAAe;MACf,GAAG;MACH;KACD,MAAM;KACN;YACO,OAAO;AACf,WAAO,MAAM,yCAAyC,MAAM;AAC5D,WAAO;;;EAGT;EACA"}
|
|
@@ -77,7 +77,7 @@ declare const github: (options: GithubOptions) => {
|
|
|
77
77
|
redirectURI: string;
|
|
78
78
|
codeVerifier?: string | undefined;
|
|
79
79
|
deviceId?: string | undefined;
|
|
80
|
-
}) => Promise<OAuth2Tokens>;
|
|
80
|
+
}) => Promise<OAuth2Tokens | null>;
|
|
81
81
|
refreshAccessToken: (refreshToken: string) => Promise<OAuth2Tokens>;
|
|
82
82
|
getUserInfo(token: OAuth2Tokens & {
|
|
83
83
|
user?: {
|
|
@@ -101,4 +101,5 @@ declare const github: (options: GithubOptions) => {
|
|
|
101
101
|
options: GithubOptions;
|
|
102
102
|
};
|
|
103
103
|
//#endregion
|
|
104
|
-
export { GithubOptions, GithubProfile, github };
|
|
104
|
+
export { GithubOptions, GithubProfile, github };
|
|
105
|
+
//# sourceMappingURL=github.d.mts.map
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
import { logger } from "../env/logger.mjs";
|
|
2
|
+
import "../env/index.mjs";
|
|
3
|
+
import { getOAuth2Tokens } from "../oauth2/utils.mjs";
|
|
1
4
|
import { createAuthorizationURL } from "../oauth2/create-authorization-url.mjs";
|
|
2
5
|
import { refreshAccessToken } from "../oauth2/refresh-access-token.mjs";
|
|
3
|
-
import {
|
|
6
|
+
import { createAuthorizationCodeRequest } from "../oauth2/validate-authorization-code.mjs";
|
|
4
7
|
import "../oauth2/index.mjs";
|
|
5
8
|
import { betterFetch } from "@better-fetch/fetch";
|
|
6
9
|
|
|
@@ -27,13 +30,26 @@ const github = (options) => {
|
|
|
27
30
|
});
|
|
28
31
|
},
|
|
29
32
|
validateAuthorizationCode: async ({ code, codeVerifier, redirectURI }) => {
|
|
30
|
-
|
|
33
|
+
const { body, headers: requestHeaders } = createAuthorizationCodeRequest({
|
|
31
34
|
code,
|
|
32
35
|
codeVerifier,
|
|
33
36
|
redirectURI,
|
|
34
|
-
options
|
|
35
|
-
|
|
37
|
+
options
|
|
38
|
+
});
|
|
39
|
+
const { data, error } = await betterFetch(tokenEndpoint, {
|
|
40
|
+
method: "POST",
|
|
41
|
+
body,
|
|
42
|
+
headers: requestHeaders
|
|
36
43
|
});
|
|
44
|
+
if (error) {
|
|
45
|
+
logger.error("GitHub OAuth token exchange failed:", error);
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
if ("error" in data) {
|
|
49
|
+
logger.error("GitHub OAuth token exchange failed:", data);
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
return getOAuth2Tokens(data);
|
|
37
53
|
},
|
|
38
54
|
refreshAccessToken: options.refreshAccessToken ? options.refreshAccessToken : async (refreshToken) => {
|
|
39
55
|
return refreshAccessToken({
|
|
@@ -77,4 +93,5 @@ const github = (options) => {
|
|
|
77
93
|
};
|
|
78
94
|
|
|
79
95
|
//#endregion
|
|
80
|
-
export { github };
|
|
96
|
+
export { github };
|
|
97
|
+
//# sourceMappingURL=github.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github.mjs","names":[],"sources":["../../src/social-providers/github.ts"],"sourcesContent":["import { betterFetch } from \"@better-fetch/fetch\";\nimport { logger } from \"../env\";\nimport type { OAuthProvider, ProviderOptions } from \"../oauth2\";\nimport {\n\tcreateAuthorizationURL,\n\tgetOAuth2Tokens,\n\trefreshAccessToken,\n} from \"../oauth2\";\nimport { createAuthorizationCodeRequest } from \"../oauth2/validate-authorization-code\";\n\nexport interface GithubProfile {\n\tlogin: string;\n\tid: string;\n\tnode_id: string;\n\tavatar_url: string;\n\tgravatar_id: string;\n\turl: string;\n\thtml_url: string;\n\tfollowers_url: string;\n\tfollowing_url: string;\n\tgists_url: string;\n\tstarred_url: string;\n\tsubscriptions_url: string;\n\torganizations_url: string;\n\trepos_url: string;\n\tevents_url: string;\n\treceived_events_url: string;\n\ttype: string;\n\tsite_admin: boolean;\n\tname: string;\n\tcompany: string;\n\tblog: string;\n\tlocation: string;\n\temail: string;\n\thireable: boolean;\n\tbio: string;\n\ttwitter_username: string;\n\tpublic_repos: string;\n\tpublic_gists: string;\n\tfollowers: string;\n\tfollowing: string;\n\tcreated_at: string;\n\tupdated_at: string;\n\tprivate_gists: string;\n\ttotal_private_repos: string;\n\towned_private_repos: string;\n\tdisk_usage: string;\n\tcollaborators: string;\n\ttwo_factor_authentication: boolean;\n\tplan: {\n\t\tname: string;\n\t\tspace: string;\n\t\tprivate_repos: string;\n\t\tcollaborators: string;\n\t};\n}\n\nexport interface GithubOptions extends ProviderOptions<GithubProfile> {\n\tclientId: string;\n}\nexport const github = (options: GithubOptions) => {\n\tconst tokenEndpoint = \"https://github.com/login/oauth/access_token\";\n\treturn {\n\t\tid: \"github\",\n\t\tname: \"GitHub\",\n\t\tcreateAuthorizationURL({\n\t\t\tstate,\n\t\t\tscopes,\n\t\t\tloginHint,\n\t\t\tcodeVerifier,\n\t\t\tredirectURI,\n\t\t}) {\n\t\t\tconst _scopes = options.disableDefaultScope\n\t\t\t\t? []\n\t\t\t\t: [\"read:user\", \"user:email\"];\n\t\t\tif (options.scope) _scopes.push(...options.scope);\n\t\t\tif (scopes) _scopes.push(...scopes);\n\t\t\treturn createAuthorizationURL({\n\t\t\t\tid: \"github\",\n\t\t\t\toptions,\n\t\t\t\tauthorizationEndpoint: \"https://github.com/login/oauth/authorize\",\n\t\t\t\tscopes: _scopes,\n\t\t\t\tstate,\n\t\t\t\tcodeVerifier,\n\t\t\t\tredirectURI,\n\t\t\t\tloginHint,\n\t\t\t\tprompt: options.prompt,\n\t\t\t});\n\t\t},\n\t\tvalidateAuthorizationCode: async ({ code, codeVerifier, redirectURI }) => {\n\t\t\tconst { body, headers: requestHeaders } = createAuthorizationCodeRequest({\n\t\t\t\tcode,\n\t\t\t\tcodeVerifier,\n\t\t\t\tredirectURI,\n\t\t\t\toptions,\n\t\t\t});\n\n\t\t\tconst { data, error } = await betterFetch<\n\t\t\t\t| { access_token: string; token_type: string; scope: string }\n\t\t\t\t| { error: string; error_description?: string; error_uri?: string }\n\t\t\t>(tokenEndpoint, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\tbody: body,\n\t\t\t\theaders: requestHeaders,\n\t\t\t});\n\n\t\t\tif (error) {\n\t\t\t\tlogger.error(\"GitHub OAuth token exchange failed:\", error);\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tif (\"error\" in data) {\n\t\t\t\tlogger.error(\"GitHub OAuth token exchange failed:\", data);\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\treturn getOAuth2Tokens(data);\n\t\t},\n\t\trefreshAccessToken: options.refreshAccessToken\n\t\t\t? options.refreshAccessToken\n\t\t\t: async (refreshToken) => {\n\t\t\t\t\treturn refreshAccessToken({\n\t\t\t\t\t\trefreshToken,\n\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\tclientId: options.clientId,\n\t\t\t\t\t\t\tclientKey: options.clientKey,\n\t\t\t\t\t\t\tclientSecret: options.clientSecret,\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttokenEndpoint: \"https://github.com/login/oauth/access_token\",\n\t\t\t\t\t});\n\t\t\t\t},\n\t\tasync getUserInfo(token) {\n\t\t\tif (options.getUserInfo) {\n\t\t\t\treturn options.getUserInfo(token);\n\t\t\t}\n\t\t\tconst { data: profile, error } = await betterFetch<GithubProfile>(\n\t\t\t\t\"https://api.github.com/user\",\n\t\t\t\t{\n\t\t\t\t\theaders: {\n\t\t\t\t\t\t\"User-Agent\": \"better-auth\",\n\t\t\t\t\t\tauthorization: `Bearer ${token.accessToken}`,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\t\t\tif (error) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst { data: emails } = await betterFetch<\n\t\t\t\t{\n\t\t\t\t\temail: string;\n\t\t\t\t\tprimary: boolean;\n\t\t\t\t\tverified: boolean;\n\t\t\t\t\tvisibility: \"public\" | \"private\";\n\t\t\t\t}[]\n\t\t\t>(\"https://api.github.com/user/emails\", {\n\t\t\t\theaders: {\n\t\t\t\t\tAuthorization: `Bearer ${token.accessToken}`,\n\t\t\t\t\t\"User-Agent\": \"better-auth\",\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tif (!profile.email && emails) {\n\t\t\t\tprofile.email = (emails.find((e) => e.primary) ?? emails[0])\n\t\t\t\t\t?.email as string;\n\t\t\t}\n\t\t\tconst emailVerified =\n\t\t\t\temails?.find((e) => e.email === profile.email)?.verified ?? false;\n\n\t\t\tconst userMap = await options.mapProfileToUser?.(profile);\n\t\t\treturn {\n\t\t\t\tuser: {\n\t\t\t\t\tid: profile.id,\n\t\t\t\t\tname: profile.name || profile.login,\n\t\t\t\t\temail: profile.email,\n\t\t\t\t\timage: profile.avatar_url,\n\t\t\t\t\temailVerified,\n\t\t\t\t\t...userMap,\n\t\t\t\t},\n\t\t\t\tdata: profile,\n\t\t\t};\n\t\t},\n\t\toptions,\n\t} satisfies OAuthProvider<GithubProfile>;\n};\n"],"mappings":";;;;;;;;;;AA4DA,MAAa,UAAU,YAA2B;CACjD,MAAM,gBAAgB;AACtB,QAAO;EACN,IAAI;EACJ,MAAM;EACN,uBAAuB,EACtB,OACA,QACA,WACA,cACA,eACE;GACF,MAAM,UAAU,QAAQ,sBACrB,EAAE,GACF,CAAC,aAAa,aAAa;AAC9B,OAAI,QAAQ,MAAO,SAAQ,KAAK,GAAG,QAAQ,MAAM;AACjD,OAAI,OAAQ,SAAQ,KAAK,GAAG,OAAO;AACnC,UAAO,uBAAuB;IAC7B,IAAI;IACJ;IACA,uBAAuB;IACvB,QAAQ;IACR;IACA;IACA;IACA;IACA,QAAQ,QAAQ;IAChB,CAAC;;EAEH,2BAA2B,OAAO,EAAE,MAAM,cAAc,kBAAkB;GACzE,MAAM,EAAE,MAAM,SAAS,mBAAmB,+BAA+B;IACxE;IACA;IACA;IACA;IACA,CAAC;GAEF,MAAM,EAAE,MAAM,UAAU,MAAM,YAG5B,eAAe;IAChB,QAAQ;IACF;IACN,SAAS;IACT,CAAC;AAEF,OAAI,OAAO;AACV,WAAO,MAAM,uCAAuC,MAAM;AAC1D,WAAO;;AAGR,OAAI,WAAW,MAAM;AACpB,WAAO,MAAM,uCAAuC,KAAK;AACzD,WAAO;;AAGR,UAAO,gBAAgB,KAAK;;EAE7B,oBAAoB,QAAQ,qBACzB,QAAQ,qBACR,OAAO,iBAAiB;AACxB,UAAO,mBAAmB;IACzB;IACA,SAAS;KACR,UAAU,QAAQ;KAClB,WAAW,QAAQ;KACnB,cAAc,QAAQ;KACtB;IACD,eAAe;IACf,CAAC;;EAEL,MAAM,YAAY,OAAO;AACxB,OAAI,QAAQ,YACX,QAAO,QAAQ,YAAY,MAAM;GAElC,MAAM,EAAE,MAAM,SAAS,UAAU,MAAM,YACtC,+BACA,EACC,SAAS;IACR,cAAc;IACd,eAAe,UAAU,MAAM;IAC/B,EACD,CACD;AACD,OAAI,MACH,QAAO;GAER,MAAM,EAAE,MAAM,WAAW,MAAM,YAO7B,sCAAsC,EACvC,SAAS;IACR,eAAe,UAAU,MAAM;IAC/B,cAAc;IACd,EACD,CAAC;AAEF,OAAI,CAAC,QAAQ,SAAS,OACrB,SAAQ,SAAS,OAAO,MAAM,MAAM,EAAE,QAAQ,IAAI,OAAO,KACtD;GAEJ,MAAM,gBACL,QAAQ,MAAM,MAAM,EAAE,UAAU,QAAQ,MAAM,EAAE,YAAY;GAE7D,MAAM,UAAU,MAAM,QAAQ,mBAAmB,QAAQ;AACzD,UAAO;IACN,MAAM;KACL,IAAI,QAAQ;KACZ,MAAM,QAAQ,QAAQ,QAAQ;KAC9B,OAAO,QAAQ;KACf,OAAO,QAAQ;KACf;KACA,GAAG;KACH;IACD,MAAM;IACN;;EAEF;EACA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gitlab.mjs","names":[],"sources":["../../src/social-providers/gitlab.ts"],"sourcesContent":["import { betterFetch } from \"@better-fetch/fetch\";\nimport type { OAuthProvider, ProviderOptions } from \"../oauth2\";\nimport {\n\tcreateAuthorizationURL,\n\trefreshAccessToken,\n\tvalidateAuthorizationCode,\n} from \"../oauth2\";\n\nexport interface GitlabProfile extends Record<string, any> {\n\tid: number;\n\tusername: string;\n\temail: string;\n\tname: string;\n\tstate: string;\n\tavatar_url: string;\n\tweb_url: string;\n\tcreated_at: string;\n\tbio: string;\n\tlocation?: string | undefined;\n\tpublic_email: string;\n\tskype: string;\n\tlinkedin: string;\n\ttwitter: string;\n\twebsite_url: string;\n\torganization: string;\n\tjob_title: string;\n\tpronouns: string;\n\tbot: boolean;\n\twork_information?: string | undefined;\n\tfollowers: number;\n\tfollowing: number;\n\tlocal_time: string;\n\tlast_sign_in_at: string;\n\tconfirmed_at: string;\n\ttheme_id: number;\n\tlast_activity_on: string;\n\tcolor_scheme_id: number;\n\tprojects_limit: number;\n\tcurrent_sign_in_at: string;\n\tidentities: Array<{\n\t\tprovider: string;\n\t\textern_uid: string;\n\t}>;\n\tcan_create_group: boolean;\n\tcan_create_project: boolean;\n\ttwo_factor_enabled: boolean;\n\texternal: boolean;\n\tprivate_profile: boolean;\n\tcommit_email: string;\n\tshared_runners_minutes_limit: number;\n\textra_shared_runners_minutes_limit: number;\n\temail_verified?: boolean | undefined;\n}\n\nexport interface GitlabOptions extends ProviderOptions<GitlabProfile> {\n\tclientId: string;\n\tissuer?: string | undefined;\n}\n\nconst cleanDoubleSlashes = (input: string = \"\") => {\n\treturn input\n\t\t.split(\"://\")\n\t\t.map((str) => str.replace(/\\/{2,}/g, \"/\"))\n\t\t.join(\"://\");\n};\n\nconst issuerToEndpoints = (issuer?: string | undefined) => {\n\tconst baseUrl = issuer || \"https://gitlab.com\";\n\treturn {\n\t\tauthorizationEndpoint: cleanDoubleSlashes(`${baseUrl}/oauth/authorize`),\n\t\ttokenEndpoint: cleanDoubleSlashes(`${baseUrl}/oauth/token`),\n\t\tuserinfoEndpoint: cleanDoubleSlashes(`${baseUrl}/api/v4/user`),\n\t};\n};\n\nexport const gitlab = (options: GitlabOptions) => {\n\tconst { authorizationEndpoint, tokenEndpoint, userinfoEndpoint } =\n\t\tissuerToEndpoints(options.issuer);\n\tconst issuerId = \"gitlab\";\n\tconst issuerName = \"Gitlab\";\n\treturn {\n\t\tid: issuerId,\n\t\tname: issuerName,\n\t\tcreateAuthorizationURL: async ({\n\t\t\tstate,\n\t\t\tscopes,\n\t\t\tcodeVerifier,\n\t\t\tloginHint,\n\t\t\tredirectURI,\n\t\t}) => {\n\t\t\tconst _scopes = options.disableDefaultScope ? [] : [\"read_user\"];\n\t\t\tif (options.scope) _scopes.push(...options.scope);\n\t\t\tif (scopes) _scopes.push(...scopes);\n\t\t\treturn await createAuthorizationURL({\n\t\t\t\tid: issuerId,\n\t\t\t\toptions,\n\t\t\t\tauthorizationEndpoint,\n\t\t\t\tscopes: _scopes,\n\t\t\t\tstate,\n\t\t\t\tredirectURI,\n\t\t\t\tcodeVerifier,\n\t\t\t\tloginHint,\n\t\t\t});\n\t\t},\n\t\tvalidateAuthorizationCode: async ({ code, redirectURI, codeVerifier }) => {\n\t\t\treturn validateAuthorizationCode({\n\t\t\t\tcode,\n\t\t\t\tredirectURI,\n\t\t\t\toptions,\n\t\t\t\tcodeVerifier,\n\t\t\t\ttokenEndpoint,\n\t\t\t});\n\t\t},\n\t\trefreshAccessToken: options.refreshAccessToken\n\t\t\t? options.refreshAccessToken\n\t\t\t: async (refreshToken) => {\n\t\t\t\t\treturn refreshAccessToken({\n\t\t\t\t\t\trefreshToken,\n\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\tclientId: options.clientId,\n\t\t\t\t\t\t\tclientKey: options.clientKey,\n\t\t\t\t\t\t\tclientSecret: options.clientSecret,\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttokenEndpoint: tokenEndpoint,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\tasync getUserInfo(token) {\n\t\t\tif (options.getUserInfo) {\n\t\t\t\treturn options.getUserInfo(token);\n\t\t\t}\n\t\t\tconst { data: profile, error } = await betterFetch<GitlabProfile>(\n\t\t\t\tuserinfoEndpoint,\n\t\t\t\t{ headers: { authorization: `Bearer ${token.accessToken}` } },\n\t\t\t);\n\t\t\tif (error || profile.state !== \"active\" || profile.locked) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst userMap = await options.mapProfileToUser?.(profile);\n\t\t\t// GitLab may provide email_verified claim, but it's not guaranteed.\n\t\t\t// We check for it first, then default to false for security consistency.\n\t\t\treturn {\n\t\t\t\tuser: {\n\t\t\t\t\tid: profile.id,\n\t\t\t\t\tname: profile.name ?? profile.username,\n\t\t\t\t\temail: profile.email,\n\t\t\t\t\timage: profile.avatar_url,\n\t\t\t\t\temailVerified: profile.email_verified ?? false,\n\t\t\t\t\t...userMap,\n\t\t\t\t},\n\t\t\t\tdata: profile,\n\t\t\t};\n\t\t},\n\t\toptions,\n\t} satisfies OAuthProvider<GitlabProfile>;\n};\n"],"mappings":";;;;;;;AA2DA,MAAM,sBAAsB,QAAgB,OAAO;AAClD,QAAO,MACL,MAAM,MAAM,CACZ,KAAK,QAAQ,IAAI,QAAQ,WAAW,IAAI,CAAC,CACzC,KAAK,MAAM;;AAGd,MAAM,qBAAqB,WAAgC;CAC1D,MAAM,UAAU,UAAU;AAC1B,QAAO;EACN,uBAAuB,mBAAmB,GAAG,QAAQ,kBAAkB;EACvE,eAAe,mBAAmB,GAAG,QAAQ,cAAc;EAC3D,kBAAkB,mBAAmB,GAAG,QAAQ,cAAc;EAC9D;;AAGF,MAAa,UAAU,YAA2B;CACjD,MAAM,EAAE,uBAAuB,eAAe,qBAC7C,kBAAkB,QAAQ,OAAO;CAClC,MAAM,WAAW;AAEjB,QAAO;EACN,IAAI;EACJ,MAHkB;EAIlB,wBAAwB,OAAO,EAC9B,OACA,QACA,cACA,WACA,kBACK;GACL,MAAM,UAAU,QAAQ,sBAAsB,EAAE,GAAG,CAAC,YAAY;AAChE,OAAI,QAAQ,MAAO,SAAQ,KAAK,GAAG,QAAQ,MAAM;AACjD,OAAI,OAAQ,SAAQ,KAAK,GAAG,OAAO;AACnC,UAAO,MAAM,uBAAuB;IACnC,IAAI;IACJ;IACA;IACA,QAAQ;IACR;IACA;IACA;IACA;IACA,CAAC;;EAEH,2BAA2B,OAAO,EAAE,MAAM,aAAa,mBAAmB;AACzE,UAAO,0BAA0B;IAChC;IACA;IACA;IACA;IACA;IACA,CAAC;;EAEH,oBAAoB,QAAQ,qBACzB,QAAQ,qBACR,OAAO,iBAAiB;AACxB,UAAO,mBAAmB;IACzB;IACA,SAAS;KACR,UAAU,QAAQ;KAClB,WAAW,QAAQ;KACnB,cAAc,QAAQ;KACtB;IACc;IACf,CAAC;;EAEL,MAAM,YAAY,OAAO;AACxB,OAAI,QAAQ,YACX,QAAO,QAAQ,YAAY,MAAM;GAElC,MAAM,EAAE,MAAM,SAAS,UAAU,MAAM,YACtC,kBACA,EAAE,SAAS,EAAE,eAAe,UAAU,MAAM,eAAe,EAAE,CAC7D;AACD,OAAI,SAAS,QAAQ,UAAU,YAAY,QAAQ,OAClD,QAAO;GAER,MAAM,UAAU,MAAM,QAAQ,mBAAmB,QAAQ;AAGzD,UAAO;IACN,MAAM;KACL,IAAI,QAAQ;KACZ,MAAM,QAAQ,QAAQ,QAAQ;KAC9B,OAAO,QAAQ;KACf,OAAO,QAAQ;KACf,eAAe,QAAQ,kBAAkB;KACzC,GAAG;KACH;IACD,MAAM;IACN;;EAEF;EACA"}
|
|
@@ -96,4 +96,5 @@ declare const google: (options: GoogleOptions) => {
|
|
|
96
96
|
};
|
|
97
97
|
declare const getGooglePublicKey: (kid: string) => Promise<Uint8Array<ArrayBufferLike> | CryptoKey>;
|
|
98
98
|
//#endregion
|
|
99
|
-
export { GoogleOptions, GoogleProfile, getGooglePublicKey, google };
|
|
99
|
+
export { GoogleOptions, GoogleProfile, getGooglePublicKey, google };
|
|
100
|
+
//# sourceMappingURL=google.d.mts.map
|
|
@@ -30,7 +30,7 @@ const google = (options) => {
|
|
|
30
30
|
return await createAuthorizationURL({
|
|
31
31
|
id: "google",
|
|
32
32
|
options,
|
|
33
|
-
authorizationEndpoint: "https://accounts.google.com/o/oauth2/auth",
|
|
33
|
+
authorizationEndpoint: "https://accounts.google.com/o/oauth2/v2/auth",
|
|
34
34
|
scopes: _scopes,
|
|
35
35
|
state,
|
|
36
36
|
codeVerifier,
|
|
@@ -60,7 +60,7 @@ const google = (options) => {
|
|
|
60
60
|
clientKey: options.clientKey,
|
|
61
61
|
clientSecret: options.clientSecret
|
|
62
62
|
},
|
|
63
|
-
tokenEndpoint: "https://
|
|
63
|
+
tokenEndpoint: "https://oauth2.googleapis.com/token"
|
|
64
64
|
});
|
|
65
65
|
},
|
|
66
66
|
async verifyIdToken(token, nonce) {
|
|
@@ -106,4 +106,5 @@ const getGooglePublicKey = async (kid) => {
|
|
|
106
106
|
};
|
|
107
107
|
|
|
108
108
|
//#endregion
|
|
109
|
-
export { getGooglePublicKey, google };
|
|
109
|
+
export { getGooglePublicKey, google };
|
|
110
|
+
//# sourceMappingURL=google.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"google.mjs","names":[],"sources":["../../src/social-providers/google.ts"],"sourcesContent":["import { betterFetch } from \"@better-fetch/fetch\";\nimport { APIError } from \"better-call\";\nimport { decodeJwt, decodeProtectedHeader, importJWK, jwtVerify } from \"jose\";\nimport { logger } from \"../env\";\nimport { BetterAuthError } from \"../error\";\nimport type { OAuthProvider, ProviderOptions } from \"../oauth2\";\nimport {\n\tcreateAuthorizationURL,\n\trefreshAccessToken,\n\tvalidateAuthorizationCode,\n} from \"../oauth2\";\n\nexport interface GoogleProfile {\n\taud: string;\n\tazp: string;\n\temail: string;\n\temail_verified: boolean;\n\texp: number;\n\t/**\n\t * The family name of the user, or last name in most\n\t * Western languages.\n\t */\n\tfamily_name: string;\n\t/**\n\t * The given name of the user, or first name in most\n\t * Western languages.\n\t */\n\tgiven_name: string;\n\thd?: string | undefined;\n\tiat: number;\n\tiss: string;\n\tjti?: string | undefined;\n\tlocale?: string | undefined;\n\tname: string;\n\tnbf?: number | undefined;\n\tpicture: string;\n\tsub: string;\n}\n\nexport interface GoogleOptions extends ProviderOptions<GoogleProfile> {\n\tclientId: string;\n\t/**\n\t * The access type to use for the authorization code request\n\t */\n\taccessType?: (\"offline\" | \"online\") | undefined;\n\t/**\n\t * The display mode to use for the authorization code request\n\t */\n\tdisplay?: (\"page\" | \"popup\" | \"touch\" | \"wap\") | undefined;\n\t/**\n\t * The hosted domain of the user\n\t */\n\thd?: string | undefined;\n}\n\nexport const google = (options: GoogleOptions) => {\n\treturn {\n\t\tid: \"google\",\n\t\tname: \"Google\",\n\t\tasync createAuthorizationURL({\n\t\t\tstate,\n\t\t\tscopes,\n\t\t\tcodeVerifier,\n\t\t\tredirectURI,\n\t\t\tloginHint,\n\t\t\tdisplay,\n\t\t}) {\n\t\t\tif (!options.clientId || !options.clientSecret) {\n\t\t\t\tlogger.error(\n\t\t\t\t\t\"Client Id and Client Secret is required for Google. Make sure to provide them in the options.\",\n\t\t\t\t);\n\t\t\t\tthrow new BetterAuthError(\"CLIENT_ID_AND_SECRET_REQUIRED\");\n\t\t\t}\n\t\t\tif (!codeVerifier) {\n\t\t\t\tthrow new BetterAuthError(\"codeVerifier is required for Google\");\n\t\t\t}\n\t\t\tconst _scopes = options.disableDefaultScope\n\t\t\t\t? []\n\t\t\t\t: [\"email\", \"profile\", \"openid\"];\n\t\t\tif (options.scope) _scopes.push(...options.scope);\n\t\t\tif (scopes) _scopes.push(...scopes);\n\t\t\tconst url = await createAuthorizationURL({\n\t\t\t\tid: \"google\",\n\t\t\t\toptions,\n\t\t\t\tauthorizationEndpoint: \"https://accounts.google.com/o/oauth2/v2/auth\",\n\t\t\t\tscopes: _scopes,\n\t\t\t\tstate,\n\t\t\t\tcodeVerifier,\n\t\t\t\tredirectURI,\n\t\t\t\tprompt: options.prompt,\n\t\t\t\taccessType: options.accessType,\n\t\t\t\tdisplay: display || options.display,\n\t\t\t\tloginHint,\n\t\t\t\thd: options.hd,\n\t\t\t\tadditionalParams: {\n\t\t\t\t\tinclude_granted_scopes: \"true\",\n\t\t\t\t},\n\t\t\t});\n\t\t\treturn url;\n\t\t},\n\t\tvalidateAuthorizationCode: async ({ code, codeVerifier, redirectURI }) => {\n\t\t\treturn validateAuthorizationCode({\n\t\t\t\tcode,\n\t\t\t\tcodeVerifier,\n\t\t\t\tredirectURI,\n\t\t\t\toptions,\n\t\t\t\ttokenEndpoint: \"https://oauth2.googleapis.com/token\",\n\t\t\t});\n\t\t},\n\t\trefreshAccessToken: options.refreshAccessToken\n\t\t\t? options.refreshAccessToken\n\t\t\t: async (refreshToken) => {\n\t\t\t\t\treturn refreshAccessToken({\n\t\t\t\t\t\trefreshToken,\n\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\tclientId: options.clientId,\n\t\t\t\t\t\t\tclientKey: options.clientKey,\n\t\t\t\t\t\t\tclientSecret: options.clientSecret,\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttokenEndpoint: \"https://oauth2.googleapis.com/token\",\n\t\t\t\t\t});\n\t\t\t\t},\n\t\tasync verifyIdToken(token, nonce) {\n\t\t\tif (options.disableIdTokenSignIn) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (options.verifyIdToken) {\n\t\t\t\treturn options.verifyIdToken(token, nonce);\n\t\t\t}\n\n\t\t\t// Verify JWT integrity\n\t\t\t// See https://developers.google.com/identity/sign-in/web/backend-auth#verify-the-integrity-of-the-id-token\n\n\t\t\tconst { kid, alg: jwtAlg } = decodeProtectedHeader(token);\n\t\t\tif (!kid || !jwtAlg) return false;\n\n\t\t\tconst publicKey = await getGooglePublicKey(kid);\n\t\t\tconst { payload: jwtClaims } = await jwtVerify(token, publicKey, {\n\t\t\t\talgorithms: [jwtAlg],\n\t\t\t\tissuer: [\"https://accounts.google.com\", \"accounts.google.com\"],\n\t\t\t\taudience: options.clientId,\n\t\t\t\tmaxTokenAge: \"1h\",\n\t\t\t});\n\n\t\t\tif (nonce && jwtClaims.nonce !== nonce) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\treturn true;\n\t\t},\n\t\tasync getUserInfo(token) {\n\t\t\tif (options.getUserInfo) {\n\t\t\t\treturn options.getUserInfo(token);\n\t\t\t}\n\t\t\tif (!token.idToken) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst user = decodeJwt(token.idToken) as GoogleProfile;\n\t\t\tconst userMap = await options.mapProfileToUser?.(user);\n\t\t\treturn {\n\t\t\t\tuser: {\n\t\t\t\t\tid: user.sub,\n\t\t\t\t\tname: user.name,\n\t\t\t\t\temail: user.email,\n\t\t\t\t\timage: user.picture,\n\t\t\t\t\temailVerified: user.email_verified,\n\t\t\t\t\t...userMap,\n\t\t\t\t},\n\t\t\t\tdata: user,\n\t\t\t};\n\t\t},\n\t\toptions,\n\t} satisfies OAuthProvider<GoogleProfile>;\n};\n\nexport const getGooglePublicKey = async (kid: string) => {\n\tconst { data } = await betterFetch<{\n\t\tkeys: Array<{\n\t\t\tkid: string;\n\t\t\talg: string;\n\t\t\tkty: string;\n\t\t\tuse: string;\n\t\t\tn: string;\n\t\t\te: string;\n\t\t}>;\n\t}>(\"https://www.googleapis.com/oauth2/v3/certs\");\n\n\tif (!data?.keys) {\n\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\tmessage: \"Keys not found\",\n\t\t});\n\t}\n\n\tconst jwk = data.keys.find((key) => key.kid === kid);\n\tif (!jwk) {\n\t\tthrow new Error(`JWK with kid ${kid} not found`);\n\t}\n\n\treturn await importJWK(jwk, jwk.alg);\n};\n"],"mappings":";;;;;;;;;;;;AAuDA,MAAa,UAAU,YAA2B;AACjD,QAAO;EACN,IAAI;EACJ,MAAM;EACN,MAAM,uBAAuB,EAC5B,OACA,QACA,cACA,aACA,WACA,WACE;AACF,OAAI,CAAC,QAAQ,YAAY,CAAC,QAAQ,cAAc;AAC/C,WAAO,MACN,gGACA;AACD,UAAM,IAAI,gBAAgB,gCAAgC;;AAE3D,OAAI,CAAC,aACJ,OAAM,IAAI,gBAAgB,sCAAsC;GAEjE,MAAM,UAAU,QAAQ,sBACrB,EAAE,GACF;IAAC;IAAS;IAAW;IAAS;AACjC,OAAI,QAAQ,MAAO,SAAQ,KAAK,GAAG,QAAQ,MAAM;AACjD,OAAI,OAAQ,SAAQ,KAAK,GAAG,OAAO;AAkBnC,UAjBY,MAAM,uBAAuB;IACxC,IAAI;IACJ;IACA,uBAAuB;IACvB,QAAQ;IACR;IACA;IACA;IACA,QAAQ,QAAQ;IAChB,YAAY,QAAQ;IACpB,SAAS,WAAW,QAAQ;IAC5B;IACA,IAAI,QAAQ;IACZ,kBAAkB,EACjB,wBAAwB,QACxB;IACD,CAAC;;EAGH,2BAA2B,OAAO,EAAE,MAAM,cAAc,kBAAkB;AACzE,UAAO,0BAA0B;IAChC;IACA;IACA;IACA;IACA,eAAe;IACf,CAAC;;EAEH,oBAAoB,QAAQ,qBACzB,QAAQ,qBACR,OAAO,iBAAiB;AACxB,UAAO,mBAAmB;IACzB;IACA,SAAS;KACR,UAAU,QAAQ;KAClB,WAAW,QAAQ;KACnB,cAAc,QAAQ;KACtB;IACD,eAAe;IACf,CAAC;;EAEL,MAAM,cAAc,OAAO,OAAO;AACjC,OAAI,QAAQ,qBACX,QAAO;AAER,OAAI,QAAQ,cACX,QAAO,QAAQ,cAAc,OAAO,MAAM;GAM3C,MAAM,EAAE,KAAK,KAAK,WAAW,sBAAsB,MAAM;AACzD,OAAI,CAAC,OAAO,CAAC,OAAQ,QAAO;GAG5B,MAAM,EAAE,SAAS,cAAc,MAAM,UAAU,OAD7B,MAAM,mBAAmB,IAAI,EACkB;IAChE,YAAY,CAAC,OAAO;IACpB,QAAQ,CAAC,+BAA+B,sBAAsB;IAC9D,UAAU,QAAQ;IAClB,aAAa;IACb,CAAC;AAEF,OAAI,SAAS,UAAU,UAAU,MAChC,QAAO;AAGR,UAAO;;EAER,MAAM,YAAY,OAAO;AACxB,OAAI,QAAQ,YACX,QAAO,QAAQ,YAAY,MAAM;AAElC,OAAI,CAAC,MAAM,QACV,QAAO;GAER,MAAM,OAAO,UAAU,MAAM,QAAQ;GACrC,MAAM,UAAU,MAAM,QAAQ,mBAAmB,KAAK;AACtD,UAAO;IACN,MAAM;KACL,IAAI,KAAK;KACT,MAAM,KAAK;KACX,OAAO,KAAK;KACZ,OAAO,KAAK;KACZ,eAAe,KAAK;KACpB,GAAG;KACH;IACD,MAAM;IACN;;EAEF;EACA;;AAGF,MAAa,qBAAqB,OAAO,QAAgB;CACxD,MAAM,EAAE,SAAS,MAAM,YASpB,6CAA6C;AAEhD,KAAI,CAAC,MAAM,KACV,OAAM,IAAI,SAAS,eAAe,EACjC,SAAS,kBACT,CAAC;CAGH,MAAM,MAAM,KAAK,KAAK,MAAM,QAAQ,IAAI,QAAQ,IAAI;AACpD,KAAI,CAAC,IACJ,OAAM,IAAI,MAAM,gBAAgB,IAAI,YAAY;AAGjD,QAAO,MAAM,UAAU,KAAK,IAAI,IAAI"}
|
|
@@ -82,4 +82,5 @@ declare const huggingface: (options: HuggingFaceOptions) => {
|
|
|
82
82
|
options: HuggingFaceOptions;
|
|
83
83
|
};
|
|
84
84
|
//#endregion
|
|
85
|
-
export { HuggingFaceOptions, HuggingFaceProfile, huggingface };
|
|
85
|
+
export { HuggingFaceOptions, HuggingFaceProfile, huggingface };
|
|
86
|
+
//# sourceMappingURL=huggingface.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"huggingface.mjs","names":[],"sources":["../../src/social-providers/huggingface.ts"],"sourcesContent":["import { betterFetch } from \"@better-fetch/fetch\";\nimport type { OAuthProvider, ProviderOptions } from \"../oauth2\";\nimport {\n\tcreateAuthorizationURL,\n\trefreshAccessToken,\n\tvalidateAuthorizationCode,\n} from \"../oauth2\";\n\nexport interface HuggingFaceProfile {\n\tsub: string;\n\tname: string;\n\tpreferred_username: string;\n\tprofile: string;\n\tpicture: string;\n\twebsite?: string | undefined;\n\temail?: string | undefined;\n\temail_verified?: boolean | undefined;\n\tisPro: boolean;\n\tcanPay?: boolean | undefined;\n\torgs?:\n\t\t| {\n\t\t\t\tsub: string;\n\t\t\t\tname: string;\n\t\t\t\tpicture: string;\n\t\t\t\tpreferred_username: string;\n\t\t\t\tisEnterprise: boolean | \"plus\";\n\t\t\t\tcanPay?: boolean;\n\t\t\t\troleInOrg?: \"admin\" | \"write\" | \"contributor\" | \"read\";\n\t\t\t\tpendingSSO?: boolean;\n\t\t\t\tmissingMFA?: boolean;\n\t\t\t\tresourceGroups?: {\n\t\t\t\t\tsub: string;\n\t\t\t\t\tname: string;\n\t\t\t\t\trole: \"admin\" | \"write\" | \"contributor\" | \"read\";\n\t\t\t\t}[];\n\t\t }\n\t\t| undefined;\n}\n\nexport interface HuggingFaceOptions\n\textends ProviderOptions<HuggingFaceProfile> {\n\tclientId: string;\n}\n\nexport const huggingface = (options: HuggingFaceOptions) => {\n\treturn {\n\t\tid: \"huggingface\",\n\t\tname: \"Hugging Face\",\n\t\tcreateAuthorizationURL({ state, scopes, codeVerifier, redirectURI }) {\n\t\t\tconst _scopes = options.disableDefaultScope\n\t\t\t\t? []\n\t\t\t\t: [\"openid\", \"profile\", \"email\"];\n\t\t\tif (options.scope) _scopes.push(...options.scope);\n\t\t\tif (scopes) _scopes.push(...scopes);\n\t\t\treturn createAuthorizationURL({\n\t\t\t\tid: \"huggingface\",\n\t\t\t\toptions,\n\t\t\t\tauthorizationEndpoint: \"https://huggingface.co/oauth/authorize\",\n\t\t\t\tscopes: _scopes,\n\t\t\t\tstate,\n\t\t\t\tcodeVerifier,\n\t\t\t\tredirectURI,\n\t\t\t});\n\t\t},\n\t\tvalidateAuthorizationCode: async ({ code, codeVerifier, redirectURI }) => {\n\t\t\treturn validateAuthorizationCode({\n\t\t\t\tcode,\n\t\t\t\tcodeVerifier,\n\t\t\t\tredirectURI,\n\t\t\t\toptions,\n\t\t\t\ttokenEndpoint: \"https://huggingface.co/oauth/token\",\n\t\t\t});\n\t\t},\n\t\trefreshAccessToken: options.refreshAccessToken\n\t\t\t? options.refreshAccessToken\n\t\t\t: async (refreshToken) => {\n\t\t\t\t\treturn refreshAccessToken({\n\t\t\t\t\t\trefreshToken,\n\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\tclientId: options.clientId,\n\t\t\t\t\t\t\tclientKey: options.clientKey,\n\t\t\t\t\t\t\tclientSecret: options.clientSecret,\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttokenEndpoint: \"https://huggingface.co/oauth/token\",\n\t\t\t\t\t});\n\t\t\t\t},\n\t\tasync getUserInfo(token) {\n\t\t\tif (options.getUserInfo) {\n\t\t\t\treturn options.getUserInfo(token);\n\t\t\t}\n\t\t\tconst { data: profile, error } = await betterFetch<HuggingFaceProfile>(\n\t\t\t\t\"https://huggingface.co/oauth/userinfo\",\n\t\t\t\t{\n\t\t\t\t\tmethod: \"GET\",\n\t\t\t\t\theaders: {\n\t\t\t\t\t\tAuthorization: `Bearer ${token.accessToken}`,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\t\t\tif (error) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst userMap = await options.mapProfileToUser?.(profile);\n\t\t\treturn {\n\t\t\t\tuser: {\n\t\t\t\t\tid: profile.sub,\n\t\t\t\t\tname: profile.name || profile.preferred_username,\n\t\t\t\t\temail: profile.email,\n\t\t\t\t\timage: profile.picture,\n\t\t\t\t\temailVerified: profile.email_verified ?? false,\n\t\t\t\t\t...userMap,\n\t\t\t\t},\n\t\t\t\tdata: profile,\n\t\t\t};\n\t\t},\n\t\toptions,\n\t} satisfies OAuthProvider<HuggingFaceProfile>;\n};\n"],"mappings":";;;;;;;AA4CA,MAAa,eAAe,YAAgC;AAC3D,QAAO;EACN,IAAI;EACJ,MAAM;EACN,uBAAuB,EAAE,OAAO,QAAQ,cAAc,eAAe;GACpE,MAAM,UAAU,QAAQ,sBACrB,EAAE,GACF;IAAC;IAAU;IAAW;IAAQ;AACjC,OAAI,QAAQ,MAAO,SAAQ,KAAK,GAAG,QAAQ,MAAM;AACjD,OAAI,OAAQ,SAAQ,KAAK,GAAG,OAAO;AACnC,UAAO,uBAAuB;IAC7B,IAAI;IACJ;IACA,uBAAuB;IACvB,QAAQ;IACR;IACA;IACA;IACA,CAAC;;EAEH,2BAA2B,OAAO,EAAE,MAAM,cAAc,kBAAkB;AACzE,UAAO,0BAA0B;IAChC;IACA;IACA;IACA;IACA,eAAe;IACf,CAAC;;EAEH,oBAAoB,QAAQ,qBACzB,QAAQ,qBACR,OAAO,iBAAiB;AACxB,UAAO,mBAAmB;IACzB;IACA,SAAS;KACR,UAAU,QAAQ;KAClB,WAAW,QAAQ;KACnB,cAAc,QAAQ;KACtB;IACD,eAAe;IACf,CAAC;;EAEL,MAAM,YAAY,OAAO;AACxB,OAAI,QAAQ,YACX,QAAO,QAAQ,YAAY,MAAM;GAElC,MAAM,EAAE,MAAM,SAAS,UAAU,MAAM,YACtC,yCACA;IACC,QAAQ;IACR,SAAS,EACR,eAAe,UAAU,MAAM,eAC/B;IACD,CACD;AACD,OAAI,MACH,QAAO;GAER,MAAM,UAAU,MAAM,QAAQ,mBAAmB,QAAQ;AACzD,UAAO;IACN,MAAM;KACL,IAAI,QAAQ;KACZ,MAAM,QAAQ,QAAQ,QAAQ;KAC9B,OAAO,QAAQ;KACf,OAAO,QAAQ;KACf,eAAe,QAAQ,kBAAkB;KACzC,GAAG;KACH;IACD,MAAM;IACN;;EAEF;EACA"}
|
|
@@ -350,7 +350,7 @@ declare const socialProviders: {
|
|
|
350
350
|
redirectURI: string;
|
|
351
351
|
codeVerifier?: string | undefined;
|
|
352
352
|
deviceId?: string | undefined;
|
|
353
|
-
}) => Promise<OAuth2Tokens>;
|
|
353
|
+
}) => Promise<OAuth2Tokens | null>;
|
|
354
354
|
refreshAccessToken: (refreshToken: string) => Promise<OAuth2Tokens>;
|
|
355
355
|
getUserInfo(token: OAuth2Tokens & {
|
|
356
356
|
user?: {
|
|
@@ -1721,4 +1721,5 @@ type SocialProviders = { [K in SocialProviderList[number]]?: Parameters<(typeof
|
|
|
1721
1721
|
} };
|
|
1722
1722
|
type SocialProviderList = typeof socialProviderList;
|
|
1723
1723
|
//#endregion
|
|
1724
|
-
export { AccountStatus, AppleNonConformUser, AppleOptions, AppleProfile, AtlassianOptions, AtlassianProfile, CognitoOptions, CognitoProfile, DiscordOptions, DiscordProfile, DropboxOptions, DropboxProfile, FacebookOptions, FacebookProfile, FigmaOptions, FigmaProfile, GithubOptions, GithubProfile, GitlabOptions, GitlabProfile, GoogleOptions, GoogleProfile, HuggingFaceOptions, HuggingFaceProfile, KakaoOptions, KakaoProfile, KickOptions, KickProfile, LineIdTokenPayload, LineOptions, LineUserInfo, LinearOptions, LinearProfile, LinearUser, LinkedInOptions, LinkedInProfile, LoginType, MicrosoftEntraIDProfile, MicrosoftOptions, NaverOptions, NaverProfile, NotionOptions, NotionProfile, PayPalOptions, PayPalProfile, PayPalTokenResponse, PaybinOptions, PaybinProfile, PhoneNumber, PolarOptions, PolarProfile, PronounOption, RedditOptions, RedditProfile, RobloxOptions, RobloxProfile, SalesforceOptions, SalesforceProfile, SlackOptions, SlackProfile, SocialProvider, SocialProviderList, SocialProviderListEnum, SocialProviders, SpotifyOptions, SpotifyProfile, TiktokOptions, TiktokProfile, TwitchOptions, TwitchProfile, TwitterOption, TwitterProfile, VercelOptions, VercelProfile, VkOption, VkProfile, ZoomOptions, ZoomProfile, apple, atlassian, cognito, discord, dropbox, facebook, figma, getApplePublicKey, getCognitoPublicKey, getGooglePublicKey, github, gitlab, google, huggingface, kakao, kick, line, linear, linkedin, microsoft, naver, notion, paybin, paypal, polar, reddit, roblox, salesforce, slack, socialProviderList, socialProviders, spotify, tiktok, twitch, twitter, vercel, vk, zoom };
|
|
1724
|
+
export { AccountStatus, AppleNonConformUser, AppleOptions, AppleProfile, AtlassianOptions, AtlassianProfile, CognitoOptions, CognitoProfile, DiscordOptions, DiscordProfile, DropboxOptions, DropboxProfile, FacebookOptions, FacebookProfile, FigmaOptions, FigmaProfile, GithubOptions, GithubProfile, GitlabOptions, GitlabProfile, GoogleOptions, GoogleProfile, HuggingFaceOptions, HuggingFaceProfile, KakaoOptions, KakaoProfile, KickOptions, KickProfile, LineIdTokenPayload, LineOptions, LineUserInfo, LinearOptions, LinearProfile, LinearUser, LinkedInOptions, LinkedInProfile, LoginType, MicrosoftEntraIDProfile, MicrosoftOptions, NaverOptions, NaverProfile, NotionOptions, NotionProfile, PayPalOptions, PayPalProfile, PayPalTokenResponse, PaybinOptions, PaybinProfile, PhoneNumber, PolarOptions, PolarProfile, PronounOption, RedditOptions, RedditProfile, RobloxOptions, RobloxProfile, SalesforceOptions, SalesforceProfile, SlackOptions, SlackProfile, SocialProvider, SocialProviderList, SocialProviderListEnum, SocialProviders, SpotifyOptions, SpotifyProfile, TiktokOptions, TiktokProfile, TwitchOptions, TwitchProfile, TwitterOption, TwitterProfile, VercelOptions, VercelProfile, VkOption, VkProfile, ZoomOptions, ZoomProfile, apple, atlassian, cognito, discord, dropbox, facebook, figma, getApplePublicKey, getCognitoPublicKey, getGooglePublicKey, github, gitlab, google, huggingface, kakao, kick, line, linear, linkedin, microsoft, naver, notion, paybin, paypal, polar, reddit, roblox, salesforce, slack, socialProviderList, socialProviders, spotify, tiktok, twitch, twitter, vercel, vk, zoom };
|
|
1725
|
+
//# sourceMappingURL=index.d.mts.map
|
|
@@ -73,4 +73,5 @@ const socialProviderList = Object.keys(socialProviders);
|
|
|
73
73
|
const SocialProviderListEnum = z.enum(socialProviderList).or(z.string());
|
|
74
74
|
|
|
75
75
|
//#endregion
|
|
76
|
-
export { SocialProviderListEnum, apple, atlassian, cognito, discord, dropbox, facebook, figma, getApplePublicKey, getCognitoPublicKey, getGooglePublicKey, github, gitlab, google, huggingface, kakao, kick, line, linear, linkedin, microsoft, naver, notion, paybin, paypal, polar, reddit, roblox, salesforce, slack, socialProviderList, socialProviders, spotify, tiktok, twitch, twitter, vercel, vk, zoom };
|
|
76
|
+
export { SocialProviderListEnum, apple, atlassian, cognito, discord, dropbox, facebook, figma, getApplePublicKey, getCognitoPublicKey, getGooglePublicKey, github, gitlab, google, huggingface, kakao, kick, line, linear, linkedin, microsoft, naver, notion, paybin, paypal, polar, reddit, roblox, salesforce, slack, socialProviderList, socialProviders, spotify, tiktok, twitch, twitter, vercel, vk, zoom };
|
|
77
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/social-providers/index.ts"],"sourcesContent":["import * as z from \"zod\";\nimport { apple } from \"./apple\";\nimport { atlassian } from \"./atlassian\";\nimport { cognito } from \"./cognito\";\nimport { discord } from \"./discord\";\nimport { dropbox } from \"./dropbox\";\nimport { facebook } from \"./facebook\";\nimport { figma } from \"./figma\";\nimport { github } from \"./github\";\nimport { gitlab } from \"./gitlab\";\nimport { google } from \"./google\";\nimport { huggingface } from \"./huggingface\";\nimport { kakao } from \"./kakao\";\nimport { kick } from \"./kick\";\nimport { line } from \"./line\";\nimport { linear } from \"./linear\";\nimport { linkedin } from \"./linkedin\";\nimport { microsoft } from \"./microsoft-entra-id\";\nimport { naver } from \"./naver\";\nimport { notion } from \"./notion\";\nimport { paybin } from \"./paybin\";\nimport { paypal } from \"./paypal\";\nimport { polar } from \"./polar\";\nimport { reddit } from \"./reddit\";\nimport { roblox } from \"./roblox\";\nimport { salesforce } from \"./salesforce\";\nimport { slack } from \"./slack\";\nimport { spotify } from \"./spotify\";\nimport { tiktok } from \"./tiktok\";\nimport { twitch } from \"./twitch\";\nimport { twitter } from \"./twitter\";\nimport { vercel } from \"./vercel\";\nimport { vk } from \"./vk\";\nimport { zoom } from \"./zoom\";\n\nexport const socialProviders = {\n\tapple,\n\tatlassian,\n\tcognito,\n\tdiscord,\n\tfacebook,\n\tfigma,\n\tgithub,\n\tmicrosoft,\n\tgoogle,\n\thuggingface,\n\tslack,\n\tspotify,\n\ttwitch,\n\ttwitter,\n\tdropbox,\n\tkick,\n\tlinear,\n\tlinkedin,\n\tgitlab,\n\ttiktok,\n\treddit,\n\troblox,\n\tsalesforce,\n\tvk,\n\tzoom,\n\tnotion,\n\tkakao,\n\tnaver,\n\tline,\n\tpaybin,\n\tpaypal,\n\tpolar,\n\tvercel,\n};\n\nexport const socialProviderList = Object.keys(socialProviders) as [\n\t\"github\",\n\t...(keyof typeof socialProviders)[],\n];\n\nexport const SocialProviderListEnum = z\n\t.enum(socialProviderList)\n\t.or(z.string()) as z.ZodType<SocialProviderList[number] | (string & {})>;\n\nexport type SocialProvider = z.infer<typeof SocialProviderListEnum>;\n\nexport type SocialProviders = {\n\t[K in SocialProviderList[number]]?: Parameters<\n\t\t(typeof socialProviders)[K]\n\t>[0] & {\n\t\tenabled?: boolean | undefined;\n\t};\n};\n\nexport * from \"./apple\";\nexport * from \"./atlassian\";\nexport * from \"./cognito\";\nexport * from \"./discord\";\nexport * from \"./dropbox\";\nexport * from \"./facebook\";\nexport * from \"./figma\";\nexport * from \"./github\";\nexport * from \"./gitlab\";\nexport * from \"./google\";\nexport * from \"./huggingface\";\nexport * from \"./kakao\";\nexport * from \"./kick\";\nexport * from \"./kick\";\nexport * from \"./line\";\nexport * from \"./linear\";\nexport * from \"./linkedin\";\nexport * from \"./linkedin\";\nexport * from \"./microsoft-entra-id\";\nexport * from \"./naver\";\nexport * from \"./notion\";\nexport * from \"./paybin\";\nexport * from \"./paypal\";\nexport * from \"./polar\";\nexport * from \"./reddit\";\nexport * from \"./roblox\";\nexport * from \"./salesforce\";\nexport * from \"./slack\";\nexport * from \"./spotify\";\nexport * from \"./tiktok\";\nexport * from \"./twitch\";\nexport * from \"./twitter\";\nexport * from \"./vercel\";\nexport * from \"./vk\";\nexport * from \"./zoom\";\n\nexport type SocialProviderList = typeof socialProviderList;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmCA,MAAa,kBAAkB;CAC9B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AAED,MAAa,qBAAqB,OAAO,KAAK,gBAAgB;AAK9D,MAAa,yBAAyB,EACpC,KAAK,mBAAmB,CACxB,GAAG,EAAE,QAAQ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kakao.mjs","names":[],"sources":["../../src/social-providers/kakao.ts"],"sourcesContent":["import { betterFetch } from \"@better-fetch/fetch\";\nimport type { OAuthProvider, ProviderOptions } from \"../oauth2\";\nimport {\n\tcreateAuthorizationURL,\n\trefreshAccessToken,\n\tvalidateAuthorizationCode,\n} from \"../oauth2\";\n\ninterface Partner {\n\t/** Partner-specific ID (consent required: kakaotalk_message) */\n\tuuid?: string | undefined;\n}\n\ninterface Profile {\n\t/** Nickname (consent required: profile/nickname) */\n\tnickname?: string | undefined;\n\t/** Thumbnail image URL (consent required: profile/profile image) */\n\tthumbnail_image_url?: string | undefined;\n\t/** Profile image URL (consent required: profile/profile image) */\n\tprofile_image_url?: string | undefined;\n\t/** Whether the profile image is the default */\n\tis_default_image?: boolean | undefined;\n\t/** Whether the nickname is the default */\n\tis_default_nickname?: boolean | undefined;\n}\n\ninterface KakaoAccount {\n\t/** Consent required: profile info (nickname/profile image) */\n\tprofile_needs_agreement?: boolean | undefined;\n\t/** Consent required: nickname */\n\tprofile_nickname_needs_agreement?: boolean | undefined;\n\t/** Consent required: profile image */\n\tprofile_image_needs_agreement?: boolean | undefined;\n\t/** Profile info */\n\tprofile?: Profile | undefined;\n\t/** Consent required: name */\n\tname_needs_agreement?: boolean | undefined;\n\t/** Name */\n\tname?: string | undefined;\n\t/** Consent required: email */\n\temail_needs_agreement?: boolean | undefined;\n\t/** Email valid */\n\tis_email_valid?: boolean | undefined;\n\t/** Email verified */\n\tis_email_verified?: boolean | undefined;\n\t/** Email */\n\temail?: string | undefined;\n\t/** Consent required: age range */\n\tage_range_needs_agreement?: boolean | undefined;\n\t/** Age range */\n\tage_range?: string | undefined;\n\t/** Consent required: birth year */\n\tbirthyear_needs_agreement?: boolean | undefined;\n\t/** Birth year (YYYY) */\n\tbirthyear?: string | undefined;\n\t/** Consent required: birthday */\n\tbirthday_needs_agreement?: boolean | undefined;\n\t/** Birthday (MMDD) */\n\tbirthday?: string | undefined;\n\t/** Birthday type (SOLAR/LUNAR) */\n\tbirthday_type?: string | undefined;\n\t/** Whether birthday is in a leap month */\n\tis_leap_month?: boolean | undefined;\n\t/** Consent required: gender */\n\tgender_needs_agreement?: boolean | undefined;\n\t/** Gender (male/female) */\n\tgender?: string | undefined;\n\t/** Consent required: phone number */\n\tphone_number_needs_agreement?: boolean | undefined;\n\t/** Phone number */\n\tphone_number?: string | undefined;\n\t/** Consent required: CI */\n\tci_needs_agreement?: boolean | undefined;\n\t/** CI (unique identifier) */\n\tci?: string | undefined;\n\t/** CI authentication time (UTC) */\n\tci_authenticated_at?: string | undefined;\n}\n\nexport interface KakaoProfile {\n\t/** Kakao user ID */\n\tid: number;\n\t/**\n\t * Whether the user has signed up (only present if auto-connection is disabled)\n\t * false: preregistered, true: registered\n\t */\n\thas_signed_up?: boolean | undefined;\n\t/** UTC datetime when the user connected the service */\n\tconnected_at?: string | undefined;\n\t/** UTC datetime when the user signed up via Kakao Sync */\n\tsynched_at?: string | undefined;\n\t/** Custom user properties */\n\tproperties?: Record<string, any> | undefined;\n\t/** Kakao account info */\n\tkakao_account: KakaoAccount;\n\t/** Partner info */\n\tfor_partner?: Partner | undefined;\n}\n\nexport interface KakaoOptions extends ProviderOptions<KakaoProfile> {\n\tclientId: string;\n}\n\nexport const kakao = (options: KakaoOptions) => {\n\treturn {\n\t\tid: \"kakao\",\n\t\tname: \"Kakao\",\n\t\tcreateAuthorizationURL({ state, scopes, redirectURI }) {\n\t\t\tconst _scopes = options.disableDefaultScope\n\t\t\t\t? []\n\t\t\t\t: [\"account_email\", \"profile_image\", \"profile_nickname\"];\n\t\t\tif (options.scope) _scopes.push(...options.scope);\n\t\t\tif (scopes) _scopes.push(...scopes);\n\t\t\treturn createAuthorizationURL({\n\t\t\t\tid: \"kakao\",\n\t\t\t\toptions,\n\t\t\t\tauthorizationEndpoint: \"https://kauth.kakao.com/oauth/authorize\",\n\t\t\t\tscopes: _scopes,\n\t\t\t\tstate,\n\t\t\t\tredirectURI,\n\t\t\t});\n\t\t},\n\t\tvalidateAuthorizationCode: async ({ code, redirectURI }) => {\n\t\t\treturn validateAuthorizationCode({\n\t\t\t\tcode,\n\t\t\t\tredirectURI,\n\t\t\t\toptions,\n\t\t\t\ttokenEndpoint: \"https://kauth.kakao.com/oauth/token\",\n\t\t\t});\n\t\t},\n\t\trefreshAccessToken: options.refreshAccessToken\n\t\t\t? options.refreshAccessToken\n\t\t\t: async (refreshToken) => {\n\t\t\t\t\treturn refreshAccessToken({\n\t\t\t\t\t\trefreshToken,\n\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\tclientId: options.clientId,\n\t\t\t\t\t\t\tclientKey: options.clientKey,\n\t\t\t\t\t\t\tclientSecret: options.clientSecret,\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttokenEndpoint: \"https://kauth.kakao.com/oauth/token\",\n\t\t\t\t\t});\n\t\t\t\t},\n\t\tasync getUserInfo(token) {\n\t\t\tif (options.getUserInfo) {\n\t\t\t\treturn options.getUserInfo(token);\n\t\t\t}\n\t\t\tconst { data: profile, error } = await betterFetch<KakaoProfile>(\n\t\t\t\t\"https://kapi.kakao.com/v2/user/me\",\n\t\t\t\t{\n\t\t\t\t\theaders: {\n\t\t\t\t\t\tAuthorization: `Bearer ${token.accessToken}`,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\t\t\tif (error || !profile) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst userMap = await options.mapProfileToUser?.(profile);\n\t\t\tconst account = profile.kakao_account || {};\n\t\t\tconst kakaoProfile = account.profile || {};\n\t\t\tconst user = {\n\t\t\t\tid: String(profile.id),\n\t\t\t\tname: kakaoProfile.nickname || account.name || undefined,\n\t\t\t\temail: account.email,\n\t\t\t\timage:\n\t\t\t\t\tkakaoProfile.profile_image_url || kakaoProfile.thumbnail_image_url,\n\t\t\t\temailVerified: !!account.is_email_valid && !!account.is_email_verified,\n\t\t\t\t...userMap,\n\t\t\t};\n\t\t\treturn {\n\t\t\t\tuser,\n\t\t\t\tdata: profile,\n\t\t\t};\n\t\t},\n\t\toptions,\n\t} satisfies OAuthProvider<KakaoProfile>;\n};\n"],"mappings":";;;;;;;AAuGA,MAAa,SAAS,YAA0B;AAC/C,QAAO;EACN,IAAI;EACJ,MAAM;EACN,uBAAuB,EAAE,OAAO,QAAQ,eAAe;GACtD,MAAM,UAAU,QAAQ,sBACrB,EAAE,GACF;IAAC;IAAiB;IAAiB;IAAmB;AACzD,OAAI,QAAQ,MAAO,SAAQ,KAAK,GAAG,QAAQ,MAAM;AACjD,OAAI,OAAQ,SAAQ,KAAK,GAAG,OAAO;AACnC,UAAO,uBAAuB;IAC7B,IAAI;IACJ;IACA,uBAAuB;IACvB,QAAQ;IACR;IACA;IACA,CAAC;;EAEH,2BAA2B,OAAO,EAAE,MAAM,kBAAkB;AAC3D,UAAO,0BAA0B;IAChC;IACA;IACA;IACA,eAAe;IACf,CAAC;;EAEH,oBAAoB,QAAQ,qBACzB,QAAQ,qBACR,OAAO,iBAAiB;AACxB,UAAO,mBAAmB;IACzB;IACA,SAAS;KACR,UAAU,QAAQ;KAClB,WAAW,QAAQ;KACnB,cAAc,QAAQ;KACtB;IACD,eAAe;IACf,CAAC;;EAEL,MAAM,YAAY,OAAO;AACxB,OAAI,QAAQ,YACX,QAAO,QAAQ,YAAY,MAAM;GAElC,MAAM,EAAE,MAAM,SAAS,UAAU,MAAM,YACtC,qCACA,EACC,SAAS,EACR,eAAe,UAAU,MAAM,eAC/B,EACD,CACD;AACD,OAAI,SAAS,CAAC,QACb,QAAO;GAER,MAAM,UAAU,MAAM,QAAQ,mBAAmB,QAAQ;GACzD,MAAM,UAAU,QAAQ,iBAAiB,EAAE;GAC3C,MAAM,eAAe,QAAQ,WAAW,EAAE;AAU1C,UAAO;IACN,MAVY;KACZ,IAAI,OAAO,QAAQ,GAAG;KACtB,MAAM,aAAa,YAAY,QAAQ,QAAQ;KAC/C,OAAO,QAAQ;KACf,OACC,aAAa,qBAAqB,aAAa;KAChD,eAAe,CAAC,CAAC,QAAQ,kBAAkB,CAAC,CAAC,QAAQ;KACrD,GAAG;KACH;IAGA,MAAM;IACN;;EAEF;EACA"}
|