@better-auth/core 1.5.5 → 1.5.7-beta.1
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/dist/api/index.d.mts +41 -14
- package/dist/api/index.mjs +1 -2
- package/dist/api/index.mjs.map +1 -1
- package/dist/async_hooks/index.mjs +1 -1
- package/dist/async_hooks/pure.index.mjs +1 -1
- package/dist/async_hooks/pure.index.mjs.map +1 -1
- package/dist/context/endpoint-context.d.mts +1 -2
- package/dist/context/endpoint-context.mjs +1 -2
- package/dist/context/endpoint-context.mjs.map +1 -1
- package/dist/context/global.mjs +2 -2
- package/dist/context/global.mjs.map +1 -1
- package/dist/context/index.mjs +1 -2
- package/dist/context/request-state.mjs +1 -2
- package/dist/context/request-state.mjs.map +1 -1
- package/dist/context/transaction.mjs +1 -2
- package/dist/context/transaction.mjs.map +1 -1
- package/dist/db/adapter/factory.d.mts +0 -2
- package/dist/db/adapter/factory.mjs +54 -22
- package/dist/db/adapter/factory.mjs.map +1 -1
- package/dist/db/adapter/get-default-field-name.mjs +1 -2
- package/dist/db/adapter/get-default-field-name.mjs.map +1 -1
- package/dist/db/adapter/get-default-model-name.mjs +1 -2
- package/dist/db/adapter/get-default-model-name.mjs.map +1 -1
- package/dist/db/adapter/get-field-attributes.d.mts +0 -3
- package/dist/db/adapter/get-field-attributes.mjs +1 -2
- package/dist/db/adapter/get-field-attributes.mjs.map +1 -1
- package/dist/db/adapter/get-field-name.mjs +1 -2
- package/dist/db/adapter/get-field-name.mjs.map +1 -1
- package/dist/db/adapter/get-id-field.d.mts +0 -3
- package/dist/db/adapter/get-id-field.mjs +3 -4
- package/dist/db/adapter/get-id-field.mjs.map +1 -1
- package/dist/db/adapter/get-model-name.mjs +1 -2
- package/dist/db/adapter/get-model-name.mjs.map +1 -1
- package/dist/db/adapter/index.d.mts +0 -2
- package/dist/db/adapter/index.mjs +1 -2
- package/dist/db/adapter/index.mjs.map +1 -1
- package/dist/db/adapter/types.d.mts +0 -2
- package/dist/db/adapter/utils.mjs +1 -1
- package/dist/db/adapter/utils.mjs.map +1 -1
- package/dist/db/get-tables.d.mts +0 -2
- package/dist/db/get-tables.mjs +1 -1
- package/dist/db/index.mjs +1 -2
- package/dist/db/schema/account.d.mts +0 -1
- package/dist/db/schema/account.mjs +1 -2
- package/dist/db/schema/account.mjs.map +1 -1
- package/dist/db/schema/rate-limit.d.mts +0 -1
- package/dist/db/schema/rate-limit.mjs +1 -2
- package/dist/db/schema/rate-limit.mjs.map +1 -1
- package/dist/db/schema/session.d.mts +0 -1
- package/dist/db/schema/session.mjs +1 -2
- package/dist/db/schema/session.mjs.map +1 -1
- package/dist/db/schema/shared.mjs +1 -2
- package/dist/db/schema/shared.mjs.map +1 -1
- package/dist/db/schema/user.d.mts +0 -1
- package/dist/db/schema/user.mjs +1 -2
- package/dist/db/schema/user.mjs.map +1 -1
- package/dist/db/schema/verification.d.mts +0 -1
- package/dist/db/schema/verification.mjs +1 -2
- package/dist/db/schema/verification.mjs.map +1 -1
- package/dist/db/type.d.mts +0 -1
- package/dist/env/color-depth.mjs +1 -2
- package/dist/env/color-depth.mjs.map +1 -1
- package/dist/env/env-impl.mjs +1 -1
- package/dist/env/env-impl.mjs.map +1 -1
- package/dist/env/index.mjs +1 -2
- package/dist/env/logger.mjs +1 -2
- package/dist/env/logger.mjs.map +1 -1
- package/dist/error/codes.mjs +1 -2
- package/dist/error/codes.mjs.map +1 -1
- package/dist/error/index.mjs +1 -2
- package/dist/error/index.mjs.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/instrumentation/attributes.d.mts +12 -0
- package/dist/instrumentation/attributes.mjs +12 -0
- package/dist/instrumentation/attributes.mjs.map +1 -0
- package/dist/instrumentation/index.d.mts +3 -0
- package/dist/instrumentation/index.mjs +3 -0
- package/dist/instrumentation/tracer.d.mts +14 -0
- package/dist/instrumentation/tracer.mjs +36 -0
- package/dist/instrumentation/tracer.mjs.map +1 -0
- package/dist/oauth2/client-credentials-token.d.mts +0 -1
- package/dist/oauth2/client-credentials-token.mjs +1 -2
- package/dist/oauth2/client-credentials-token.mjs.map +1 -1
- package/dist/oauth2/create-authorization-url.d.mts +0 -3
- package/dist/oauth2/create-authorization-url.mjs +1 -2
- package/dist/oauth2/create-authorization-url.mjs.map +1 -1
- package/dist/oauth2/index.mjs +1 -2
- package/dist/oauth2/oauth-provider.d.mts +0 -2
- package/dist/oauth2/refresh-access-token.d.mts +0 -1
- package/dist/oauth2/refresh-access-token.mjs +1 -2
- package/dist/oauth2/refresh-access-token.mjs.map +1 -1
- package/dist/oauth2/utils.mjs +1 -2
- package/dist/oauth2/utils.mjs.map +1 -1
- package/dist/oauth2/validate-authorization-code.d.mts +0 -2
- package/dist/oauth2/validate-authorization-code.mjs +1 -2
- package/dist/oauth2/validate-authorization-code.mjs.map +1 -1
- package/dist/oauth2/verify.mjs +1 -2
- package/dist/oauth2/verify.mjs.map +1 -1
- package/dist/social-providers/apple.d.mts +0 -2
- package/dist/social-providers/apple.mjs +2 -3
- package/dist/social-providers/apple.mjs.map +1 -1
- package/dist/social-providers/atlassian.d.mts +0 -2
- package/dist/social-providers/atlassian.mjs +4 -4
- package/dist/social-providers/atlassian.mjs.map +1 -1
- package/dist/social-providers/cognito.d.mts +0 -2
- package/dist/social-providers/cognito.mjs +1 -2
- package/dist/social-providers/cognito.mjs.map +1 -1
- package/dist/social-providers/discord.d.mts +0 -2
- package/dist/social-providers/discord.mjs +4 -4
- package/dist/social-providers/discord.mjs.map +1 -1
- package/dist/social-providers/dropbox.d.mts +0 -2
- package/dist/social-providers/dropbox.mjs +1 -2
- package/dist/social-providers/dropbox.mjs.map +1 -1
- package/dist/social-providers/facebook.d.mts +0 -2
- package/dist/social-providers/facebook.mjs +1 -2
- package/dist/social-providers/facebook.mjs.map +1 -1
- package/dist/social-providers/figma.d.mts +0 -2
- package/dist/social-providers/figma.mjs +4 -4
- package/dist/social-providers/figma.mjs.map +1 -1
- package/dist/social-providers/github.d.mts +0 -2
- package/dist/social-providers/github.mjs +2 -3
- package/dist/social-providers/github.mjs.map +1 -1
- package/dist/social-providers/gitlab.d.mts +0 -2
- package/dist/social-providers/gitlab.mjs +1 -2
- package/dist/social-providers/gitlab.mjs.map +1 -1
- package/dist/social-providers/google.d.mts +0 -2
- package/dist/social-providers/google.mjs +1 -2
- package/dist/social-providers/google.mjs.map +1 -1
- package/dist/social-providers/huggingface.d.mts +0 -2
- package/dist/social-providers/huggingface.mjs +4 -4
- package/dist/social-providers/huggingface.mjs.map +1 -1
- package/dist/social-providers/index.d.mts +61 -3
- package/dist/social-providers/index.mjs +5 -4
- package/dist/social-providers/index.mjs.map +1 -1
- package/dist/social-providers/kakao.d.mts +0 -2
- package/dist/social-providers/kakao.mjs +4 -4
- package/dist/social-providers/kakao.mjs.map +1 -1
- package/dist/social-providers/kick.d.mts +0 -2
- package/dist/social-providers/kick.mjs +1 -2
- package/dist/social-providers/kick.mjs.map +1 -1
- package/dist/social-providers/line.d.mts +0 -2
- package/dist/social-providers/line.mjs +1 -2
- package/dist/social-providers/line.mjs.map +1 -1
- package/dist/social-providers/linear.d.mts +0 -2
- package/dist/social-providers/linear.mjs +1 -2
- package/dist/social-providers/linear.mjs.map +1 -1
- package/dist/social-providers/linkedin.d.mts +0 -2
- package/dist/social-providers/linkedin.mjs +1 -2
- package/dist/social-providers/linkedin.mjs.map +1 -1
- package/dist/social-providers/microsoft-entra-id.d.mts +0 -2
- package/dist/social-providers/microsoft-entra-id.mjs +1 -2
- package/dist/social-providers/microsoft-entra-id.mjs.map +1 -1
- package/dist/social-providers/naver.d.mts +0 -2
- package/dist/social-providers/naver.mjs +4 -4
- package/dist/social-providers/naver.mjs.map +1 -1
- package/dist/social-providers/notion.d.mts +0 -2
- package/dist/social-providers/notion.mjs +1 -2
- package/dist/social-providers/notion.mjs.map +1 -1
- package/dist/social-providers/paybin.d.mts +0 -2
- package/dist/social-providers/paybin.mjs +1 -2
- package/dist/social-providers/paybin.mjs.map +1 -1
- package/dist/social-providers/paypal.d.mts +0 -2
- package/dist/social-providers/paypal.mjs +1 -2
- package/dist/social-providers/paypal.mjs.map +1 -1
- package/dist/social-providers/polar.d.mts +0 -2
- package/dist/social-providers/polar.mjs +4 -4
- package/dist/social-providers/polar.mjs.map +1 -1
- package/dist/social-providers/railway.d.mts +0 -2
- package/dist/social-providers/railway.mjs +1 -2
- package/dist/social-providers/railway.mjs.map +1 -1
- package/dist/social-providers/reddit.d.mts +0 -2
- package/dist/social-providers/reddit.mjs +1 -2
- package/dist/social-providers/reddit.mjs.map +1 -1
- package/dist/social-providers/roblox.d.mts +0 -2
- package/dist/social-providers/roblox.mjs +4 -4
- package/dist/social-providers/roblox.mjs.map +1 -1
- package/dist/social-providers/salesforce.d.mts +0 -2
- package/dist/social-providers/salesforce.mjs +1 -2
- package/dist/social-providers/salesforce.mjs.map +1 -1
- package/dist/social-providers/slack.d.mts +0 -2
- package/dist/social-providers/slack.mjs +4 -4
- package/dist/social-providers/slack.mjs.map +1 -1
- package/dist/social-providers/spotify.d.mts +0 -2
- package/dist/social-providers/spotify.mjs +4 -4
- package/dist/social-providers/spotify.mjs.map +1 -1
- package/dist/social-providers/tiktok.d.mts +0 -2
- package/dist/social-providers/tiktok.mjs +4 -4
- package/dist/social-providers/tiktok.mjs.map +1 -1
- package/dist/social-providers/twitch.d.mts +0 -2
- package/dist/social-providers/twitch.mjs +4 -4
- package/dist/social-providers/twitch.mjs.map +1 -1
- package/dist/social-providers/twitter.d.mts +0 -2
- package/dist/social-providers/twitter.mjs +4 -4
- package/dist/social-providers/twitter.mjs.map +1 -1
- package/dist/social-providers/vercel.d.mts +0 -2
- package/dist/social-providers/vercel.mjs +1 -2
- package/dist/social-providers/vercel.mjs.map +1 -1
- package/dist/social-providers/vk.d.mts +0 -2
- package/dist/social-providers/vk.mjs +4 -4
- package/dist/social-providers/vk.mjs.map +1 -1
- package/dist/social-providers/wechat.d.mts +114 -0
- package/dist/social-providers/wechat.mjs +83 -0
- package/dist/social-providers/wechat.mjs.map +1 -0
- package/dist/social-providers/zoom.d.mts +0 -2
- package/dist/social-providers/zoom.mjs +1 -2
- package/dist/social-providers/zoom.mjs.map +1 -1
- package/dist/types/context.d.mts +1 -5
- package/dist/types/init-options.d.mts +0 -1
- package/dist/types/plugin.d.mts +4 -2
- package/dist/utils/db.d.mts +0 -2
- package/dist/utils/db.mjs +1 -1
- package/dist/utils/deprecate.mjs +1 -1
- package/dist/utils/error-codes.mjs +1 -1
- package/dist/utils/fetch-metadata.mjs +1 -1
- package/dist/utils/id.mjs +1 -2
- package/dist/utils/id.mjs.map +1 -1
- package/dist/utils/ip.mjs +1 -2
- package/dist/utils/ip.mjs.map +1 -1
- package/dist/utils/json.mjs +1 -2
- package/dist/utils/json.mjs.map +1 -1
- package/dist/utils/string.mjs +1 -1
- package/dist/utils/url.mjs +1 -1
- package/package.json +18 -5
- package/src/api/index.ts +151 -41
- package/src/context/endpoint-context.ts +2 -1
- package/src/db/adapter/factory.ts +119 -47
- package/src/db/adapter/get-id-field.test.ts +222 -0
- package/src/db/adapter/get-id-field.ts +15 -4
- package/src/instrumentation/attributes.ts +22 -0
- package/src/instrumentation/index.ts +2 -0
- package/src/instrumentation/instrumentation.test.ts +139 -0
- package/src/instrumentation/tracer.ts +62 -0
- package/src/social-providers/apple.ts +1 -1
- package/src/social-providers/atlassian.ts +3 -2
- package/src/social-providers/discord.ts +3 -2
- package/src/social-providers/figma.ts +3 -2
- package/src/social-providers/github.ts +1 -1
- package/src/social-providers/huggingface.ts +3 -2
- package/src/social-providers/index.ts +3 -0
- package/src/social-providers/kakao.ts +3 -2
- package/src/social-providers/naver.ts +3 -2
- package/src/social-providers/polar.ts +3 -2
- package/src/social-providers/roblox.ts +3 -2
- package/src/social-providers/slack.ts +3 -2
- package/src/social-providers/spotify.ts +3 -2
- package/src/social-providers/tiktok.ts +3 -2
- package/src/social-providers/twitch.ts +3 -2
- package/src/social-providers/twitter.ts +3 -2
- package/src/social-providers/vk.ts +3 -2
- package/src/social-providers/wechat.ts +213 -0
- package/src/types/context.ts +1 -3
- package/src/types/plugin.ts +14 -1
|
@@ -32,10 +32,9 @@ import { PayPalOptions, PayPalProfile, PayPalTokenResponse, paypal } from "./pay
|
|
|
32
32
|
import { PolarOptions, PolarProfile, polar } from "./polar.mjs";
|
|
33
33
|
import { RailwayOptions, RailwayProfile, railway } from "./railway.mjs";
|
|
34
34
|
import { VercelOptions, VercelProfile, vercel } from "./vercel.mjs";
|
|
35
|
+
import { WeChatOptions, WeChatProfile, wechat } from "./wechat.mjs";
|
|
35
36
|
import { AwaitableFunction } from "../types/helper.mjs";
|
|
36
|
-
import "../types/index.mjs";
|
|
37
37
|
import { OAuth2Tokens } from "../oauth2/oauth-provider.mjs";
|
|
38
|
-
import "../oauth2/index.mjs";
|
|
39
38
|
import * as z from "zod";
|
|
40
39
|
|
|
41
40
|
//#region src/social-providers/index.d.ts
|
|
@@ -1764,6 +1763,65 @@ declare const socialProviders: {
|
|
|
1764
1763
|
} | null>;
|
|
1765
1764
|
options: VercelOptions;
|
|
1766
1765
|
};
|
|
1766
|
+
wechat: (options: WeChatOptions) => {
|
|
1767
|
+
id: "wechat";
|
|
1768
|
+
name: string;
|
|
1769
|
+
createAuthorizationURL({
|
|
1770
|
+
state,
|
|
1771
|
+
scopes,
|
|
1772
|
+
redirectURI
|
|
1773
|
+
}: {
|
|
1774
|
+
state: string;
|
|
1775
|
+
codeVerifier: string;
|
|
1776
|
+
scopes?: string[] | undefined;
|
|
1777
|
+
redirectURI: string;
|
|
1778
|
+
display?: string | undefined;
|
|
1779
|
+
loginHint?: string | undefined;
|
|
1780
|
+
}): URL;
|
|
1781
|
+
validateAuthorizationCode: ({
|
|
1782
|
+
code
|
|
1783
|
+
}: {
|
|
1784
|
+
code: string;
|
|
1785
|
+
redirectURI: string;
|
|
1786
|
+
codeVerifier?: string | undefined;
|
|
1787
|
+
deviceId?: string | undefined;
|
|
1788
|
+
}) => Promise<{
|
|
1789
|
+
tokenType: "Bearer";
|
|
1790
|
+
accessToken: string;
|
|
1791
|
+
refreshToken: string;
|
|
1792
|
+
accessTokenExpiresAt: Date;
|
|
1793
|
+
scopes: string[];
|
|
1794
|
+
openid: string;
|
|
1795
|
+
unionid: string | undefined;
|
|
1796
|
+
}>;
|
|
1797
|
+
refreshAccessToken: ((refreshToken: string) => Promise<OAuth2Tokens>) | ((refreshToken: string) => Promise<{
|
|
1798
|
+
tokenType: "Bearer";
|
|
1799
|
+
accessToken: string;
|
|
1800
|
+
refreshToken: string;
|
|
1801
|
+
accessTokenExpiresAt: Date;
|
|
1802
|
+
scopes: string[];
|
|
1803
|
+
}>);
|
|
1804
|
+
getUserInfo(token: OAuth2Tokens & {
|
|
1805
|
+
user?: {
|
|
1806
|
+
name?: {
|
|
1807
|
+
firstName?: string;
|
|
1808
|
+
lastName?: string;
|
|
1809
|
+
};
|
|
1810
|
+
email?: string;
|
|
1811
|
+
} | undefined;
|
|
1812
|
+
}): Promise<{
|
|
1813
|
+
user: {
|
|
1814
|
+
id: string;
|
|
1815
|
+
name?: string;
|
|
1816
|
+
email?: string | null;
|
|
1817
|
+
image?: string;
|
|
1818
|
+
emailVerified: boolean;
|
|
1819
|
+
[key: string]: any;
|
|
1820
|
+
};
|
|
1821
|
+
data: any;
|
|
1822
|
+
} | null>;
|
|
1823
|
+
options: WeChatOptions;
|
|
1824
|
+
};
|
|
1767
1825
|
};
|
|
1768
1826
|
declare const socialProviderList: ["github", ...(keyof typeof socialProviders)[]];
|
|
1769
1827
|
declare const SocialProviderListEnum: z.ZodType<SocialProviderList[number] | (string & {})>;
|
|
@@ -1773,5 +1831,5 @@ type SocialProviders = { [K in SocialProviderList[number]]?: AwaitableFunction<P
|
|
|
1773
1831
|
}> };
|
|
1774
1832
|
type SocialProviderList = typeof socialProviderList;
|
|
1775
1833
|
//#endregion
|
|
1776
|
-
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, RailwayOptions, RailwayProfile, 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, getMicrosoftPublicKey, github, gitlab, google, huggingface, kakao, kick, line, linear, linkedin, microsoft, naver, notion, paybin, paypal, polar, railway, reddit, roblox, salesforce, slack, socialProviderList, socialProviders, spotify, tiktok, twitch, twitter, vercel, vk, zoom };
|
|
1834
|
+
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, RailwayOptions, RailwayProfile, RedditOptions, RedditProfile, RobloxOptions, RobloxProfile, SalesforceOptions, SalesforceProfile, SlackOptions, SlackProfile, SocialProvider, SocialProviderList, SocialProviderListEnum, SocialProviders, SpotifyOptions, SpotifyProfile, TiktokOptions, TiktokProfile, TwitchOptions, TwitchProfile, TwitterOption, TwitterProfile, VercelOptions, VercelProfile, VkOption, VkProfile, WeChatOptions, WeChatProfile, ZoomOptions, ZoomProfile, apple, atlassian, cognito, discord, dropbox, facebook, figma, getApplePublicKey, getCognitoPublicKey, getGooglePublicKey, getMicrosoftPublicKey, github, gitlab, google, huggingface, kakao, kick, line, linear, linkedin, microsoft, naver, notion, paybin, paypal, polar, railway, reddit, roblox, salesforce, slack, socialProviderList, socialProviders, spotify, tiktok, twitch, twitter, vercel, vk, wechat, zoom };
|
|
1777
1835
|
//# sourceMappingURL=index.d.mts.map
|
|
@@ -31,9 +31,9 @@ import { twitch } from "./twitch.mjs";
|
|
|
31
31
|
import { twitter } from "./twitter.mjs";
|
|
32
32
|
import { vercel } from "./vercel.mjs";
|
|
33
33
|
import { vk } from "./vk.mjs";
|
|
34
|
+
import { wechat } from "./wechat.mjs";
|
|
34
35
|
import { zoom } from "./zoom.mjs";
|
|
35
36
|
import * as z from "zod";
|
|
36
|
-
|
|
37
37
|
//#region src/social-providers/index.ts
|
|
38
38
|
const socialProviders = {
|
|
39
39
|
apple,
|
|
@@ -69,11 +69,12 @@ const socialProviders = {
|
|
|
69
69
|
paypal,
|
|
70
70
|
polar,
|
|
71
71
|
railway,
|
|
72
|
-
vercel
|
|
72
|
+
vercel,
|
|
73
|
+
wechat
|
|
73
74
|
};
|
|
74
75
|
const socialProviderList = Object.keys(socialProviders);
|
|
75
76
|
const SocialProviderListEnum = z.enum(socialProviderList).or(z.string());
|
|
76
|
-
|
|
77
77
|
//#endregion
|
|
78
|
-
export { SocialProviderListEnum, apple, atlassian, cognito, discord, dropbox, facebook, figma, getApplePublicKey, getCognitoPublicKey, getGooglePublicKey, getMicrosoftPublicKey, github, gitlab, google, huggingface, kakao, kick, line, linear, linkedin, microsoft, naver, notion, paybin, paypal, polar, railway, reddit, roblox, salesforce, slack, socialProviderList, socialProviders, spotify, tiktok, twitch, twitter, vercel, vk, zoom };
|
|
78
|
+
export { SocialProviderListEnum, apple, atlassian, cognito, discord, dropbox, facebook, figma, getApplePublicKey, getCognitoPublicKey, getGooglePublicKey, getMicrosoftPublicKey, github, gitlab, google, huggingface, kakao, kick, line, linear, linkedin, microsoft, naver, notion, paybin, paypal, polar, railway, reddit, roblox, salesforce, slack, socialProviderList, socialProviders, spotify, tiktok, twitch, twitter, vercel, vk, wechat, zoom };
|
|
79
|
+
|
|
79
80
|
//# sourceMappingURL=index.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/social-providers/index.ts"],"sourcesContent":["import * as z from \"zod\";\nimport type { AwaitableFunction } from \"../types\";\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 { railway } from \"./railway\";\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\trailway,\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]]?: AwaitableFunction<\n\t\tParameters<(typeof socialProviders)[K]>[0] & {\n\t\t\tenabled?: boolean | undefined;\n\t\t}\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 \"./railway\";\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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/social-providers/index.ts"],"sourcesContent":["import * as z from \"zod\";\nimport type { AwaitableFunction } from \"../types\";\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 { railway } from \"./railway\";\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 { wechat } from \"./wechat\";\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\trailway,\n\tvercel,\n\twechat,\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]]?: AwaitableFunction<\n\t\tParameters<(typeof socialProviders)[K]>[0] & {\n\t\t\tenabled?: boolean | undefined;\n\t\t}\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 \"./railway\";\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 \"./wechat\";\nexport * from \"./zoom\";\n\nexport type SocialProviderList = typeof socialProviderList;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsCA,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;CACA;CACA;AAED,MAAa,qBAAqB,OAAO,KAAK,gBAAgB;AAK9D,MAAa,yBAAyB,EACpC,KAAK,mBAAmB,CACxB,GAAG,EAAE,QAAQ,CAAC"}
|
|
@@ -3,9 +3,9 @@ import { refreshAccessToken } from "../oauth2/refresh-access-token.mjs";
|
|
|
3
3
|
import { validateAuthorizationCode } from "../oauth2/validate-authorization-code.mjs";
|
|
4
4
|
import "../oauth2/index.mjs";
|
|
5
5
|
import { betterFetch } from "@better-fetch/fetch";
|
|
6
|
-
|
|
7
6
|
//#region src/social-providers/kakao.ts
|
|
8
7
|
const kakao = (options) => {
|
|
8
|
+
const tokenEndpoint = "https://kauth.kakao.com/oauth/token";
|
|
9
9
|
return {
|
|
10
10
|
id: "kakao",
|
|
11
11
|
name: "Kakao",
|
|
@@ -31,7 +31,7 @@ const kakao = (options) => {
|
|
|
31
31
|
code,
|
|
32
32
|
redirectURI,
|
|
33
33
|
options,
|
|
34
|
-
tokenEndpoint
|
|
34
|
+
tokenEndpoint
|
|
35
35
|
});
|
|
36
36
|
},
|
|
37
37
|
refreshAccessToken: options.refreshAccessToken ? options.refreshAccessToken : async (refreshToken) => {
|
|
@@ -42,7 +42,7 @@ const kakao = (options) => {
|
|
|
42
42
|
clientKey: options.clientKey,
|
|
43
43
|
clientSecret: options.clientSecret
|
|
44
44
|
},
|
|
45
|
-
tokenEndpoint
|
|
45
|
+
tokenEndpoint
|
|
46
46
|
});
|
|
47
47
|
},
|
|
48
48
|
async getUserInfo(token) {
|
|
@@ -67,7 +67,7 @@ const kakao = (options) => {
|
|
|
67
67
|
options
|
|
68
68
|
};
|
|
69
69
|
};
|
|
70
|
-
|
|
71
70
|
//#endregion
|
|
72
71
|
export { kakao };
|
|
72
|
+
|
|
73
73
|
//# sourceMappingURL=kakao.mjs.map
|
|
@@ -1 +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
|
|
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\tconst tokenEndpoint = \"https://kauth.kakao.com/oauth/token\";\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,\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,\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 || \"\",\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;CAC/C,MAAM,gBAAgB;AACtB,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;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;IACA,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"}
|
|
@@ -3,7 +3,6 @@ import { refreshAccessToken } from "../oauth2/refresh-access-token.mjs";
|
|
|
3
3
|
import { validateAuthorizationCode } from "../oauth2/validate-authorization-code.mjs";
|
|
4
4
|
import "../oauth2/index.mjs";
|
|
5
5
|
import { betterFetch } from "@better-fetch/fetch";
|
|
6
|
-
|
|
7
6
|
//#region src/social-providers/kick.ts
|
|
8
7
|
const kick = (options) => {
|
|
9
8
|
return {
|
|
@@ -66,7 +65,7 @@ const kick = (options) => {
|
|
|
66
65
|
options
|
|
67
66
|
};
|
|
68
67
|
};
|
|
69
|
-
|
|
70
68
|
//#endregion
|
|
71
69
|
export { kick };
|
|
70
|
+
|
|
72
71
|
//# sourceMappingURL=kick.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"kick.mjs","names":[],"sources":["../../src/social-providers/kick.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 KickProfile {\n\t/**\n\t * The user id of the user\n\t */\n\tuser_id: string;\n\t/**\n\t * The name of the user\n\t */\n\tname: string;\n\t/**\n\t * The email of the user\n\t */\n\temail: string;\n\t/**\n\t * The picture of the user\n\t */\n\tprofile_picture: string;\n}\n\nexport interface KickOptions extends ProviderOptions<KickProfile> {\n\tclientId: string;\n}\n\nexport const kick = (options: KickOptions) => {\n\treturn {\n\t\tid: \"kick\",\n\t\tname: \"Kick\",\n\t\tcreateAuthorizationURL({ state, scopes, redirectURI, codeVerifier }) {\n\t\t\tconst _scopes = options.disableDefaultScope ? [] : [\"user:read\"];\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: \"kick\",\n\t\t\t\tredirectURI,\n\t\t\t\toptions,\n\t\t\t\tauthorizationEndpoint: \"https://id.kick.com/oauth/authorize\",\n\t\t\t\tscopes: _scopes,\n\t\t\t\tcodeVerifier,\n\t\t\t\tstate,\n\t\t\t});\n\t\t},\n\t\tasync validateAuthorizationCode({ 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\ttokenEndpoint: \"https://id.kick.com/oauth/token\",\n\t\t\t\tcodeVerifier,\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\tclientSecret: options.clientSecret,\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttokenEndpoint: \"https://id.kick.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\n\t\t\tconst { data, error } = await betterFetch<{\n\t\t\t\tdata: KickProfile[];\n\t\t\t}>(\"https://api.kick.com/public/v1/users\", {\n\t\t\t\tmethod: \"GET\",\n\t\t\t\theaders: {\n\t\t\t\t\tAuthorization: `Bearer ${token.accessToken}`,\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\n\t\t\tconst profile = data.data[0]!;\n\n\t\t\tconst userMap = await options.mapProfileToUser?.(profile);\n\t\t\t// Kick does not provide email_verified claim.\n\t\t\t// We default to false for security consistency.\n\t\t\treturn {\n\t\t\t\tuser: {\n\t\t\t\t\tid: profile.user_id,\n\t\t\t\t\tname: profile.name,\n\t\t\t\t\temail: profile.email,\n\t\t\t\t\timage: profile.profile_picture,\n\t\t\t\t\temailVerified: 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<KickProfile>;\n};\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"kick.mjs","names":[],"sources":["../../src/social-providers/kick.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 KickProfile {\n\t/**\n\t * The user id of the user\n\t */\n\tuser_id: string;\n\t/**\n\t * The name of the user\n\t */\n\tname: string;\n\t/**\n\t * The email of the user\n\t */\n\temail: string;\n\t/**\n\t * The picture of the user\n\t */\n\tprofile_picture: string;\n}\n\nexport interface KickOptions extends ProviderOptions<KickProfile> {\n\tclientId: string;\n}\n\nexport const kick = (options: KickOptions) => {\n\treturn {\n\t\tid: \"kick\",\n\t\tname: \"Kick\",\n\t\tcreateAuthorizationURL({ state, scopes, redirectURI, codeVerifier }) {\n\t\t\tconst _scopes = options.disableDefaultScope ? [] : [\"user:read\"];\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: \"kick\",\n\t\t\t\tredirectURI,\n\t\t\t\toptions,\n\t\t\t\tauthorizationEndpoint: \"https://id.kick.com/oauth/authorize\",\n\t\t\t\tscopes: _scopes,\n\t\t\t\tcodeVerifier,\n\t\t\t\tstate,\n\t\t\t});\n\t\t},\n\t\tasync validateAuthorizationCode({ 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\ttokenEndpoint: \"https://id.kick.com/oauth/token\",\n\t\t\t\tcodeVerifier,\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\tclientSecret: options.clientSecret,\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttokenEndpoint: \"https://id.kick.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\n\t\t\tconst { data, error } = await betterFetch<{\n\t\t\t\tdata: KickProfile[];\n\t\t\t}>(\"https://api.kick.com/public/v1/users\", {\n\t\t\t\tmethod: \"GET\",\n\t\t\t\theaders: {\n\t\t\t\t\tAuthorization: `Bearer ${token.accessToken}`,\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\n\t\t\tconst profile = data.data[0]!;\n\n\t\t\tconst userMap = await options.mapProfileToUser?.(profile);\n\t\t\t// Kick does not provide email_verified claim.\n\t\t\t// We default to false for security consistency.\n\t\t\treturn {\n\t\t\t\tuser: {\n\t\t\t\t\tid: profile.user_id,\n\t\t\t\t\tname: profile.name,\n\t\t\t\t\temail: profile.email,\n\t\t\t\t\timage: profile.profile_picture,\n\t\t\t\t\temailVerified: 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<KickProfile>;\n};\n"],"mappings":";;;;;;AA+BA,MAAa,QAAQ,YAAyB;AAC7C,QAAO;EACN,IAAI;EACJ,MAAM;EACN,uBAAuB,EAAE,OAAO,QAAQ,aAAa,gBAAgB;GACpE,MAAM,UAAU,QAAQ,sBAAsB,EAAE,GAAG,CAAC,YAAY;AAChE,OAAI,QAAQ,MAAO,SAAQ,KAAK,GAAG,QAAQ,MAAM;AACjD,OAAI,OAAQ,SAAQ,KAAK,GAAG,OAAO;AAEnC,UAAO,uBAAuB;IAC7B,IAAI;IACJ;IACA;IACA,uBAAuB;IACvB,QAAQ;IACR;IACA;IACA,CAAC;;EAEH,MAAM,0BAA0B,EAAE,MAAM,aAAa,gBAAgB;AACpE,UAAO,0BAA0B;IAChC;IACA;IACA;IACA,eAAe;IACf;IACA,CAAC;;EAEH,oBAAoB,QAAQ,qBACzB,QAAQ,qBACR,OAAO,iBAAiB;AACxB,UAAO,mBAAmB;IACzB;IACA,SAAS;KACR,UAAU,QAAQ;KAClB,cAAc,QAAQ;KACtB;IACD,eAAe;IACf,CAAC;;EAEL,MAAM,YAAY,OAAO;AACxB,OAAI,QAAQ,YACX,QAAO,QAAQ,YAAY,MAAM;GAGlC,MAAM,EAAE,MAAM,UAAU,MAAM,YAE3B,wCAAwC;IAC1C,QAAQ;IACR,SAAS,EACR,eAAe,UAAU,MAAM,eAC/B;IACD,CAAC;AAEF,OAAI,MACH,QAAO;GAGR,MAAM,UAAU,KAAK,KAAK;GAE1B,MAAM,UAAU,MAAM,QAAQ,mBAAmB,QAAQ;AAGzD,UAAO;IACN,MAAM;KACL,IAAI,QAAQ;KACZ,MAAM,QAAQ;KACd,OAAO,QAAQ;KACf,OAAO,QAAQ;KACf,eAAe;KACf,GAAG;KACH;IACD,MAAM;IACN;;EAEF;EACA"}
|
|
@@ -4,7 +4,6 @@ import { validateAuthorizationCode } from "../oauth2/validate-authorization-code
|
|
|
4
4
|
import "../oauth2/index.mjs";
|
|
5
5
|
import { betterFetch } from "@better-fetch/fetch";
|
|
6
6
|
import { decodeJwt } from "jose";
|
|
7
|
-
|
|
8
7
|
//#region src/social-providers/line.ts
|
|
9
8
|
/**
|
|
10
9
|
* LINE Login v2.1
|
|
@@ -108,7 +107,7 @@ const line = (options) => {
|
|
|
108
107
|
options
|
|
109
108
|
};
|
|
110
109
|
};
|
|
111
|
-
|
|
112
110
|
//#endregion
|
|
113
111
|
export { line };
|
|
112
|
+
|
|
114
113
|
//# sourceMappingURL=line.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"line.mjs","names":[],"sources":["../../src/social-providers/line.ts"],"sourcesContent":["import { betterFetch } from \"@better-fetch/fetch\";\nimport { decodeJwt } from \"jose\";\nimport type { OAuthProvider, ProviderOptions } from \"../oauth2\";\nimport {\n\tcreateAuthorizationURL,\n\trefreshAccessToken,\n\tvalidateAuthorizationCode,\n} from \"../oauth2\";\n\nexport interface LineIdTokenPayload {\n\tiss: string;\n\tsub: string;\n\taud: string;\n\texp: number;\n\tiat: number;\n\tname?: string | undefined;\n\tpicture?: string | undefined;\n\temail?: string | undefined;\n\tamr?: string[] | undefined;\n\tnonce?: string | undefined;\n}\n\nexport interface LineUserInfo {\n\tsub: string;\n\tname?: string | undefined;\n\tpicture?: string | undefined;\n\temail?: string | undefined;\n}\n\nexport interface LineOptions\n\textends ProviderOptions<LineUserInfo | LineIdTokenPayload> {\n\tclientId: string;\n}\n\n/**\n * LINE Login v2.1\n * - Authorization endpoint: https://access.line.me/oauth2/v2.1/authorize\n * - Token endpoint: https://api.line.me/oauth2/v2.1/token\n * - UserInfo endpoint: https://api.line.me/oauth2/v2.1/userinfo\n * - Verify ID token: https://api.line.me/oauth2/v2.1/verify\n *\n * Docs: https://developers.line.biz/en/reference/line-login/#issue-access-token\n */\nexport const line = (options: LineOptions) => {\n\tconst authorizationEndpoint = \"https://access.line.me/oauth2/v2.1/authorize\";\n\tconst tokenEndpoint = \"https://api.line.me/oauth2/v2.1/token\";\n\tconst userInfoEndpoint = \"https://api.line.me/oauth2/v2.1/userinfo\";\n\tconst verifyIdTokenEndpoint = \"https://api.line.me/oauth2/v2.1/verify\";\n\n\treturn {\n\t\tid: \"line\",\n\t\tname: \"LINE\",\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}) {\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 await createAuthorizationURL({\n\t\t\t\tid: \"line\",\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\tcodeVerifier,\n\t\t\t\tredirectURI,\n\t\t\t\tloginHint,\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,\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\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\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 body = new URLSearchParams();\n\t\t\tbody.set(\"id_token\", token);\n\t\t\tbody.set(\"client_id\", options.clientId);\n\t\t\tif (nonce) body.set(\"nonce\", nonce);\n\t\t\tconst { data, error } = await betterFetch<LineIdTokenPayload>(\n\t\t\t\tverifyIdTokenEndpoint,\n\t\t\t\t{\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\theaders: {\n\t\t\t\t\t\t\"content-type\": \"application/x-www-form-urlencoded\",\n\t\t\t\t\t},\n\t\t\t\t\tbody,\n\t\t\t\t},\n\t\t\t);\n\t\t\tif (error || !data) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\t// aud must match clientId; nonce (if provided) must also match nonce\n\t\t\tif (data.aud !== options.clientId) return false;\n\t\t\tif (data.nonce && data.nonce !== nonce) return false;\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\tlet profile: LineUserInfo | LineIdTokenPayload | null = null;\n\t\t\t// Prefer ID token if available\n\t\t\tif (token.idToken) {\n\t\t\t\ttry {\n\t\t\t\t\tprofile = decodeJwt(token.idToken) as LineIdTokenPayload;\n\t\t\t\t} catch {}\n\t\t\t}\n\t\t\t// Fallback to UserInfo endpoint\n\t\t\tif (!profile) {\n\t\t\t\tconst { data } = await betterFetch<LineUserInfo>(userInfoEndpoint, {\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\tprofile = data || null;\n\t\t\t}\n\t\t\tif (!profile) return null;\n\t\t\tconst userMap = await options.mapProfileToUser?.(profile as any);\n\t\t\t// ID preference order\n\t\t\tconst id = (profile as any).sub || (profile as any).userId;\n\t\t\tconst name = (profile as any).name || (profile as any).displayName || \"\";\n\t\t\tconst image =\n\t\t\t\t(profile as any).picture || (profile as any).pictureUrl || undefined;\n\t\t\tconst email = (profile as any).email;\n\t\t\treturn {\n\t\t\t\tuser: {\n\t\t\t\t\tid,\n\t\t\t\t\tname,\n\t\t\t\t\temail,\n\t\t\t\t\timage,\n\t\t\t\t\t// LINE does not expose email verification status in ID token/userinfo\n\t\t\t\t\temailVerified: false,\n\t\t\t\t\t...userMap,\n\t\t\t\t},\n\t\t\t\tdata: profile as any,\n\t\t\t};\n\t\t},\n\t\toptions,\n\t} satisfies OAuthProvider<LineUserInfo | LineIdTokenPayload, LineOptions>;\n};\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"line.mjs","names":[],"sources":["../../src/social-providers/line.ts"],"sourcesContent":["import { betterFetch } from \"@better-fetch/fetch\";\nimport { decodeJwt } from \"jose\";\nimport type { OAuthProvider, ProviderOptions } from \"../oauth2\";\nimport {\n\tcreateAuthorizationURL,\n\trefreshAccessToken,\n\tvalidateAuthorizationCode,\n} from \"../oauth2\";\n\nexport interface LineIdTokenPayload {\n\tiss: string;\n\tsub: string;\n\taud: string;\n\texp: number;\n\tiat: number;\n\tname?: string | undefined;\n\tpicture?: string | undefined;\n\temail?: string | undefined;\n\tamr?: string[] | undefined;\n\tnonce?: string | undefined;\n}\n\nexport interface LineUserInfo {\n\tsub: string;\n\tname?: string | undefined;\n\tpicture?: string | undefined;\n\temail?: string | undefined;\n}\n\nexport interface LineOptions\n\textends ProviderOptions<LineUserInfo | LineIdTokenPayload> {\n\tclientId: string;\n}\n\n/**\n * LINE Login v2.1\n * - Authorization endpoint: https://access.line.me/oauth2/v2.1/authorize\n * - Token endpoint: https://api.line.me/oauth2/v2.1/token\n * - UserInfo endpoint: https://api.line.me/oauth2/v2.1/userinfo\n * - Verify ID token: https://api.line.me/oauth2/v2.1/verify\n *\n * Docs: https://developers.line.biz/en/reference/line-login/#issue-access-token\n */\nexport const line = (options: LineOptions) => {\n\tconst authorizationEndpoint = \"https://access.line.me/oauth2/v2.1/authorize\";\n\tconst tokenEndpoint = \"https://api.line.me/oauth2/v2.1/token\";\n\tconst userInfoEndpoint = \"https://api.line.me/oauth2/v2.1/userinfo\";\n\tconst verifyIdTokenEndpoint = \"https://api.line.me/oauth2/v2.1/verify\";\n\n\treturn {\n\t\tid: \"line\",\n\t\tname: \"LINE\",\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}) {\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 await createAuthorizationURL({\n\t\t\t\tid: \"line\",\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\tcodeVerifier,\n\t\t\t\tredirectURI,\n\t\t\t\tloginHint,\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,\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\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\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 body = new URLSearchParams();\n\t\t\tbody.set(\"id_token\", token);\n\t\t\tbody.set(\"client_id\", options.clientId);\n\t\t\tif (nonce) body.set(\"nonce\", nonce);\n\t\t\tconst { data, error } = await betterFetch<LineIdTokenPayload>(\n\t\t\t\tverifyIdTokenEndpoint,\n\t\t\t\t{\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\theaders: {\n\t\t\t\t\t\t\"content-type\": \"application/x-www-form-urlencoded\",\n\t\t\t\t\t},\n\t\t\t\t\tbody,\n\t\t\t\t},\n\t\t\t);\n\t\t\tif (error || !data) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\t// aud must match clientId; nonce (if provided) must also match nonce\n\t\t\tif (data.aud !== options.clientId) return false;\n\t\t\tif (data.nonce && data.nonce !== nonce) return false;\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\tlet profile: LineUserInfo | LineIdTokenPayload | null = null;\n\t\t\t// Prefer ID token if available\n\t\t\tif (token.idToken) {\n\t\t\t\ttry {\n\t\t\t\t\tprofile = decodeJwt(token.idToken) as LineIdTokenPayload;\n\t\t\t\t} catch {}\n\t\t\t}\n\t\t\t// Fallback to UserInfo endpoint\n\t\t\tif (!profile) {\n\t\t\t\tconst { data } = await betterFetch<LineUserInfo>(userInfoEndpoint, {\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\tprofile = data || null;\n\t\t\t}\n\t\t\tif (!profile) return null;\n\t\t\tconst userMap = await options.mapProfileToUser?.(profile as any);\n\t\t\t// ID preference order\n\t\t\tconst id = (profile as any).sub || (profile as any).userId;\n\t\t\tconst name = (profile as any).name || (profile as any).displayName || \"\";\n\t\t\tconst image =\n\t\t\t\t(profile as any).picture || (profile as any).pictureUrl || undefined;\n\t\t\tconst email = (profile as any).email;\n\t\t\treturn {\n\t\t\t\tuser: {\n\t\t\t\t\tid,\n\t\t\t\t\tname,\n\t\t\t\t\temail,\n\t\t\t\t\timage,\n\t\t\t\t\t// LINE does not expose email verification status in ID token/userinfo\n\t\t\t\t\temailVerified: false,\n\t\t\t\t\t...userMap,\n\t\t\t\t},\n\t\t\t\tdata: profile as any,\n\t\t\t};\n\t\t},\n\t\toptions,\n\t} satisfies OAuthProvider<LineUserInfo | LineIdTokenPayload, LineOptions>;\n};\n"],"mappings":";;;;;;;;;;;;;;;;AA2CA,MAAa,QAAQ,YAAyB;CAC7C,MAAM,wBAAwB;CAC9B,MAAM,gBAAgB;CACtB,MAAM,mBAAmB;CACzB,MAAM,wBAAwB;AAE9B,QAAO;EACN,IAAI;EACJ,MAAM;EACN,MAAM,uBAAuB,EAC5B,OACA,QACA,cACA,aACA,aACE;GACF,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,MAAM,uBAAuB;IACnC,IAAI;IACJ;IACA;IACA,QAAQ;IACR;IACA;IACA;IACA;IACA,CAAC;;EAEH,2BAA2B,OAAO,EAAE,MAAM,cAAc,kBAAkB;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,cAAc,QAAQ;KACtB;IACD;IACA,CAAC;;EAEL,MAAM,cAAc,OAAO,OAAO;AACjC,OAAI,QAAQ,qBACX,QAAO;AAER,OAAI,QAAQ,cACX,QAAO,QAAQ,cAAc,OAAO,MAAM;GAE3C,MAAM,OAAO,IAAI,iBAAiB;AAClC,QAAK,IAAI,YAAY,MAAM;AAC3B,QAAK,IAAI,aAAa,QAAQ,SAAS;AACvC,OAAI,MAAO,MAAK,IAAI,SAAS,MAAM;GACnC,MAAM,EAAE,MAAM,UAAU,MAAM,YAC7B,uBACA;IACC,QAAQ;IACR,SAAS,EACR,gBAAgB,qCAChB;IACD;IACA,CACD;AACD,OAAI,SAAS,CAAC,KACb,QAAO;AAGR,OAAI,KAAK,QAAQ,QAAQ,SAAU,QAAO;AAC1C,OAAI,KAAK,SAAS,KAAK,UAAU,MAAO,QAAO;AAC/C,UAAO;;EAER,MAAM,YAAY,OAAO;AACxB,OAAI,QAAQ,YACX,QAAO,QAAQ,YAAY,MAAM;GAElC,IAAI,UAAoD;AAExD,OAAI,MAAM,QACT,KAAI;AACH,cAAU,UAAU,MAAM,QAAQ;WAC3B;AAGT,OAAI,CAAC,SAAS;IACb,MAAM,EAAE,SAAS,MAAM,YAA0B,kBAAkB,EAClE,SAAS,EACR,eAAe,UAAU,MAAM,eAC/B,EACD,CAAC;AACF,cAAU,QAAQ;;AAEnB,OAAI,CAAC,QAAS,QAAO;GACrB,MAAM,UAAU,MAAM,QAAQ,mBAAmB,QAAe;GAEhE,MAAM,KAAM,QAAgB,OAAQ,QAAgB;GACpD,MAAM,OAAQ,QAAgB,QAAS,QAAgB,eAAe;GACtE,MAAM,QACJ,QAAgB,WAAY,QAAgB,cAAc,KAAA;AAE5D,UAAO;IACN,MAAM;KACL;KACA;KACA,OALa,QAAgB;KAM7B;KAEA,eAAe;KACf,GAAG;KACH;IACD,MAAM;IACN;;EAEF;EACA"}
|
|
@@ -3,7 +3,6 @@ import { refreshAccessToken } from "../oauth2/refresh-access-token.mjs";
|
|
|
3
3
|
import { validateAuthorizationCode } from "../oauth2/validate-authorization-code.mjs";
|
|
4
4
|
import "../oauth2/index.mjs";
|
|
5
5
|
import { betterFetch } from "@better-fetch/fetch";
|
|
6
|
-
|
|
7
6
|
//#region src/social-providers/linear.ts
|
|
8
7
|
const linear = (options) => {
|
|
9
8
|
const tokenEndpoint = "https://api.linear.app/oauth/token";
|
|
@@ -83,7 +82,7 @@ const linear = (options) => {
|
|
|
83
82
|
options
|
|
84
83
|
};
|
|
85
84
|
};
|
|
86
|
-
|
|
87
85
|
//#endregion
|
|
88
86
|
export { linear };
|
|
87
|
+
|
|
89
88
|
//# sourceMappingURL=linear.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"linear.mjs","names":[],"sources":["../../src/social-providers/linear.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 LinearUser {\n\tid: string;\n\tname: string;\n\temail: string;\n\tavatarUrl?: string | undefined;\n\tactive: boolean;\n\tcreatedAt: string;\n\tupdatedAt: string;\n}\n\nexport interface LinearProfile {\n\tdata: {\n\t\tviewer: LinearUser;\n\t};\n}\n\nexport interface LinearOptions extends ProviderOptions<LinearUser> {\n\tclientId: string;\n}\n\nexport const linear = (options: LinearOptions) => {\n\tconst tokenEndpoint = \"https://api.linear.app/oauth/token\";\n\treturn {\n\t\tid: \"linear\",\n\t\tname: \"Linear\",\n\t\tcreateAuthorizationURL({ state, scopes, loginHint, redirectURI }) {\n\t\t\tconst _scopes = options.disableDefaultScope ? [] : [\"read\"];\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: \"linear\",\n\t\t\t\toptions,\n\t\t\t\tauthorizationEndpoint: \"https://linear.app/oauth/authorize\",\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});\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,\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,\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\tconst { data: profile, error } = await betterFetch<LinearProfile>(\n\t\t\t\t\"https://api.linear.app/graphql\",\n\t\t\t\t{\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\theaders: {\n\t\t\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t\t\tAuthorization: `Bearer ${token.accessToken}`,\n\t\t\t\t\t},\n\t\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\t\tquery: `\n\t\t\t\t\t\t\tquery {\n\t\t\t\t\t\t\t\tviewer {\n\t\t\t\t\t\t\t\t\tid\n\t\t\t\t\t\t\t\t\tname\n\t\t\t\t\t\t\t\t\temail\n\t\t\t\t\t\t\t\t\tavatarUrl\n\t\t\t\t\t\t\t\t\tactive\n\t\t\t\t\t\t\t\t\tcreatedAt\n\t\t\t\t\t\t\t\t\tupdatedAt\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t`,\n\t\t\t\t\t}),\n\t\t\t\t},\n\t\t\t);\n\t\t\tif (error || !profile?.data?.viewer) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tconst userData = profile.data.viewer;\n\t\t\tconst userMap = await options.mapProfileToUser?.(userData);\n\t\t\t// Linear does not provide email_verified claim.\n\t\t\t// We default to false for security consistency.\n\t\t\treturn {\n\t\t\t\tuser: {\n\t\t\t\t\tid: profile.data.viewer.id,\n\t\t\t\t\tname: profile.data.viewer.name,\n\t\t\t\t\temail: profile.data.viewer.email,\n\t\t\t\t\timage: profile.data.viewer.avatarUrl,\n\t\t\t\t\temailVerified: false,\n\t\t\t\t\t...userMap,\n\t\t\t\t},\n\t\t\t\tdata: userData,\n\t\t\t};\n\t\t},\n\t\toptions,\n\t} satisfies OAuthProvider<LinearUser>;\n};\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"linear.mjs","names":[],"sources":["../../src/social-providers/linear.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 LinearUser {\n\tid: string;\n\tname: string;\n\temail: string;\n\tavatarUrl?: string | undefined;\n\tactive: boolean;\n\tcreatedAt: string;\n\tupdatedAt: string;\n}\n\nexport interface LinearProfile {\n\tdata: {\n\t\tviewer: LinearUser;\n\t};\n}\n\nexport interface LinearOptions extends ProviderOptions<LinearUser> {\n\tclientId: string;\n}\n\nexport const linear = (options: LinearOptions) => {\n\tconst tokenEndpoint = \"https://api.linear.app/oauth/token\";\n\treturn {\n\t\tid: \"linear\",\n\t\tname: \"Linear\",\n\t\tcreateAuthorizationURL({ state, scopes, loginHint, redirectURI }) {\n\t\t\tconst _scopes = options.disableDefaultScope ? [] : [\"read\"];\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: \"linear\",\n\t\t\t\toptions,\n\t\t\t\tauthorizationEndpoint: \"https://linear.app/oauth/authorize\",\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});\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,\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,\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\tconst { data: profile, error } = await betterFetch<LinearProfile>(\n\t\t\t\t\"https://api.linear.app/graphql\",\n\t\t\t\t{\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\theaders: {\n\t\t\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t\t\tAuthorization: `Bearer ${token.accessToken}`,\n\t\t\t\t\t},\n\t\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\t\tquery: `\n\t\t\t\t\t\t\tquery {\n\t\t\t\t\t\t\t\tviewer {\n\t\t\t\t\t\t\t\t\tid\n\t\t\t\t\t\t\t\t\tname\n\t\t\t\t\t\t\t\t\temail\n\t\t\t\t\t\t\t\t\tavatarUrl\n\t\t\t\t\t\t\t\t\tactive\n\t\t\t\t\t\t\t\t\tcreatedAt\n\t\t\t\t\t\t\t\t\tupdatedAt\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t`,\n\t\t\t\t\t}),\n\t\t\t\t},\n\t\t\t);\n\t\t\tif (error || !profile?.data?.viewer) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tconst userData = profile.data.viewer;\n\t\t\tconst userMap = await options.mapProfileToUser?.(userData);\n\t\t\t// Linear does not provide email_verified claim.\n\t\t\t// We default to false for security consistency.\n\t\t\treturn {\n\t\t\t\tuser: {\n\t\t\t\t\tid: profile.data.viewer.id,\n\t\t\t\t\tname: profile.data.viewer.name,\n\t\t\t\t\temail: profile.data.viewer.email,\n\t\t\t\t\timage: profile.data.viewer.avatarUrl,\n\t\t\t\t\temailVerified: false,\n\t\t\t\t\t...userMap,\n\t\t\t\t},\n\t\t\t\tdata: userData,\n\t\t\t};\n\t\t},\n\t\toptions,\n\t} satisfies OAuthProvider<LinearUser>;\n};\n"],"mappings":";;;;;;AA4BA,MAAa,UAAU,YAA2B;CACjD,MAAM,gBAAgB;AACtB,QAAO;EACN,IAAI;EACJ,MAAM;EACN,uBAAuB,EAAE,OAAO,QAAQ,WAAW,eAAe;GACjE,MAAM,UAAU,QAAQ,sBAAsB,EAAE,GAAG,CAAC,OAAO;AAC3D,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,kBAAkB;AAC3D,UAAO,0BAA0B;IAChC;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;IACA,CAAC;;EAEL,MAAM,YAAY,OAAO;AACxB,OAAI,QAAQ,YACX,QAAO,QAAQ,YAAY,MAAM;GAGlC,MAAM,EAAE,MAAM,SAAS,UAAU,MAAM,YACtC,kCACA;IACC,QAAQ;IACR,SAAS;KACR,gBAAgB;KAChB,eAAe,UAAU,MAAM;KAC/B;IACD,MAAM,KAAK,UAAU,EACpB,OAAO;;;;;;;;;;;;SAaP,CAAC;IACF,CACD;AACD,OAAI,SAAS,CAAC,SAAS,MAAM,OAC5B,QAAO;GAGR,MAAM,WAAW,QAAQ,KAAK;GAC9B,MAAM,UAAU,MAAM,QAAQ,mBAAmB,SAAS;AAG1D,UAAO;IACN,MAAM;KACL,IAAI,QAAQ,KAAK,OAAO;KACxB,MAAM,QAAQ,KAAK,OAAO;KAC1B,OAAO,QAAQ,KAAK,OAAO;KAC3B,OAAO,QAAQ,KAAK,OAAO;KAC3B,eAAe;KACf,GAAG;KACH;IACD,MAAM;IACN;;EAEF;EACA"}
|
|
@@ -3,7 +3,6 @@ import { refreshAccessToken } from "../oauth2/refresh-access-token.mjs";
|
|
|
3
3
|
import { validateAuthorizationCode } from "../oauth2/validate-authorization-code.mjs";
|
|
4
4
|
import "../oauth2/index.mjs";
|
|
5
5
|
import { betterFetch } from "@better-fetch/fetch";
|
|
6
|
-
|
|
7
6
|
//#region src/social-providers/linkedin.ts
|
|
8
7
|
const linkedin = (options) => {
|
|
9
8
|
const authorizationEndpoint = "https://www.linkedin.com/oauth/v2/authorization";
|
|
@@ -71,7 +70,7 @@ const linkedin = (options) => {
|
|
|
71
70
|
options
|
|
72
71
|
};
|
|
73
72
|
};
|
|
74
|
-
|
|
75
73
|
//#endregion
|
|
76
74
|
export { linkedin };
|
|
75
|
+
|
|
77
76
|
//# sourceMappingURL=linkedin.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"linkedin.mjs","names":[],"sources":["../../src/social-providers/linkedin.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 LinkedInProfile {\n\tsub: string;\n\tname: string;\n\tgiven_name: string;\n\tfamily_name: string;\n\tpicture: string;\n\tlocale: {\n\t\tcountry: string;\n\t\tlanguage: string;\n\t};\n\temail: string;\n\temail_verified: boolean;\n}\n\nexport interface LinkedInOptions extends ProviderOptions<LinkedInProfile> {\n\tclientId: string;\n}\n\nexport const linkedin = (options: LinkedInOptions) => {\n\tconst authorizationEndpoint =\n\t\t\"https://www.linkedin.com/oauth/v2/authorization\";\n\tconst tokenEndpoint = \"https://www.linkedin.com/oauth/v2/accessToken\";\n\n\treturn {\n\t\tid: \"linkedin\",\n\t\tname: \"Linkedin\",\n\t\tcreateAuthorizationURL: async ({\n\t\t\tstate,\n\t\t\tscopes,\n\t\t\tredirectURI,\n\t\t\tloginHint,\n\t\t}) => {\n\t\t\tconst _scopes = options.disableDefaultScope\n\t\t\t\t? []\n\t\t\t\t: [\"profile\", \"email\", \"openid\"];\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: \"linkedin\",\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\tloginHint,\n\t\t\t\tredirectURI,\n\t\t\t});\n\t\t},\n\t\tvalidateAuthorizationCode: async ({ code, redirectURI }) => {\n\t\t\treturn await validateAuthorizationCode({\n\t\t\t\tcode,\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,\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<LinkedInProfile>(\n\t\t\t\t\"https://api.linkedin.com/v2/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\n\t\t\tif (error) {\n\t\t\t\treturn null;\n\t\t\t}\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.sub,\n\t\t\t\t\tname: profile.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.picture,\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<LinkedInProfile>;\n};\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"linkedin.mjs","names":[],"sources":["../../src/social-providers/linkedin.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 LinkedInProfile {\n\tsub: string;\n\tname: string;\n\tgiven_name: string;\n\tfamily_name: string;\n\tpicture: string;\n\tlocale: {\n\t\tcountry: string;\n\t\tlanguage: string;\n\t};\n\temail: string;\n\temail_verified: boolean;\n}\n\nexport interface LinkedInOptions extends ProviderOptions<LinkedInProfile> {\n\tclientId: string;\n}\n\nexport const linkedin = (options: LinkedInOptions) => {\n\tconst authorizationEndpoint =\n\t\t\"https://www.linkedin.com/oauth/v2/authorization\";\n\tconst tokenEndpoint = \"https://www.linkedin.com/oauth/v2/accessToken\";\n\n\treturn {\n\t\tid: \"linkedin\",\n\t\tname: \"Linkedin\",\n\t\tcreateAuthorizationURL: async ({\n\t\t\tstate,\n\t\t\tscopes,\n\t\t\tredirectURI,\n\t\t\tloginHint,\n\t\t}) => {\n\t\t\tconst _scopes = options.disableDefaultScope\n\t\t\t\t? []\n\t\t\t\t: [\"profile\", \"email\", \"openid\"];\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: \"linkedin\",\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\tloginHint,\n\t\t\t\tredirectURI,\n\t\t\t});\n\t\t},\n\t\tvalidateAuthorizationCode: async ({ code, redirectURI }) => {\n\t\t\treturn await validateAuthorizationCode({\n\t\t\t\tcode,\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,\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<LinkedInProfile>(\n\t\t\t\t\"https://api.linkedin.com/v2/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\n\t\t\tif (error) {\n\t\t\t\treturn null;\n\t\t\t}\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.sub,\n\t\t\t\t\tname: profile.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.picture,\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<LinkedInProfile>;\n};\n"],"mappings":";;;;;;AA0BA,MAAa,YAAY,YAA6B;CACrD,MAAM,wBACL;CACD,MAAM,gBAAgB;AAEtB,QAAO;EACN,IAAI;EACJ,MAAM;EACN,wBAAwB,OAAO,EAC9B,OACA,QACA,aACA,gBACK;GACL,MAAM,UAAU,QAAQ,sBACrB,EAAE,GACF;IAAC;IAAW;IAAS;IAAS;AACjC,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,CAAC;;EAEH,2BAA2B,OAAO,EAAE,MAAM,kBAAkB;AAC3D,UAAO,MAAM,0BAA0B;IACtC;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;IACA,CAAC;;EAEL,MAAM,YAAY,OAAO;AACxB,OAAI,QAAQ,YACX,QAAO,QAAQ,YAAY,MAAM;GAElC,MAAM,EAAE,MAAM,SAAS,UAAU,MAAM,YACtC,wCACA;IACC,QAAQ;IACR,SAAS,EACR,eAAe,UAAU,MAAM,eAC/B;IACD,CACD;AAED,OAAI,MACH,QAAO;GAGR,MAAM,UAAU,MAAM,QAAQ,mBAAmB,QAAQ;AACzD,UAAO;IACN,MAAM;KACL,IAAI,QAAQ;KACZ,MAAM,QAAQ;KACd,OAAO,QAAQ;KACf,eAAe,QAAQ,kBAAkB;KACzC,OAAO,QAAQ;KACf,GAAG;KACH;IACD,MAAM;IACN;;EAEF;EACA"}
|
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import { OAuth2Tokens, ProviderOptions } from "../oauth2/oauth-provider.mjs";
|
|
2
|
-
import "../oauth2/index.mjs";
|
|
3
|
-
|
|
4
2
|
//#region src/social-providers/microsoft-entra-id.d.ts
|
|
5
3
|
/**
|
|
6
4
|
* @see [Microsoft Identity Platform - Optional claims reference](https://learn.microsoft.com/en-us/entra/identity-platform/optional-claims-reference)
|
|
@@ -8,7 +8,6 @@ import "../oauth2/index.mjs";
|
|
|
8
8
|
import { base64 } from "@better-auth/utils/base64";
|
|
9
9
|
import { betterFetch } from "@better-fetch/fetch";
|
|
10
10
|
import { decodeJwt, decodeProtectedHeader, importJWK, jwtVerify } from "jose";
|
|
11
|
-
|
|
12
11
|
//#region src/social-providers/microsoft-entra-id.ts
|
|
13
12
|
const microsoft = (options) => {
|
|
14
13
|
const tenant = options.tenantId || "common";
|
|
@@ -134,7 +133,7 @@ const getMicrosoftPublicKey = async (kid, tenant, authority) => {
|
|
|
134
133
|
if (!jwk) throw new Error(`JWK with kid ${kid} not found`);
|
|
135
134
|
return await importJWK(jwk, jwk.alg);
|
|
136
135
|
};
|
|
137
|
-
|
|
138
136
|
//#endregion
|
|
139
137
|
export { getMicrosoftPublicKey, microsoft };
|
|
138
|
+
|
|
140
139
|
//# sourceMappingURL=microsoft-entra-id.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"microsoft-entra-id.mjs","names":[],"sources":["../../src/social-providers/microsoft-entra-id.ts"],"sourcesContent":["import { base64 } from \"@better-auth/utils/base64\";\nimport { betterFetch } from \"@better-fetch/fetch\";\nimport { decodeJwt, decodeProtectedHeader, importJWK, jwtVerify } from \"jose\";\nimport { logger } from \"../env\";\nimport { APIError } from \"../error\";\nimport type { OAuthProvider, ProviderOptions } from \"../oauth2\";\nimport {\n\tcreateAuthorizationURL,\n\trefreshAccessToken,\n\tvalidateAuthorizationCode,\n} from \"../oauth2\";\n\n/**\n * @see [Microsoft Identity Platform - Optional claims reference](https://learn.microsoft.com/en-us/entra/identity-platform/optional-claims-reference)\n */\nexport interface MicrosoftEntraIDProfile extends Record<string, any> {\n\t/** Identifies the intended recipient of the token */\n\taud: string;\n\t/** Identifies the issuer, or \"authorization server\" that constructs and returns the token */\n\tiss: string;\n\t/** Indicates when the authentication for the token occurred */\n\tiat: Date;\n\t/** Records the identity provider that authenticated the subject of the token */\n\tidp: string;\n\t/** Identifies the time before which the JWT can't be accepted for processing */\n\tnbf: Date;\n\t/** Identifies the expiration time on or after which the JWT can't be accepted for processing */\n\texp: Date;\n\t/** Code hash included in ID tokens when issued with an OAuth 2.0 authorization code */\n\tc_hash: string;\n\t/** Access token hash included in ID tokens when issued with an OAuth 2.0 access token */\n\tat_hash: string;\n\t/** Internal claim used to record data for token reuse */\n\taio: string;\n\t/** The primary username that represents the user */\n\tpreferred_username: string;\n\t/** User's email address */\n\temail: string;\n\t/** Human-readable value that identifies the subject of the token */\n\tname: string;\n\t/** Matches the parameter included in the original authorize request */\n\tnonce: string;\n\t/** User's profile picture */\n\tpicture: string;\n\t/** Immutable identifier for the user account */\n\toid: string;\n\t/** Set of roles assigned to the user */\n\troles: string[];\n\t/** Internal claim used to revalidate tokens */\n\trh: string;\n\t/** Subject identifier - unique to application ID */\n\tsub: string;\n\t/** Tenant ID the user is signing in to */\n\ttid: string;\n\t/** Unique identifier for a session */\n\tsid: string;\n\t/** Token identifier claim */\n\tuti: string;\n\t/** Indicates if user is in at least one group */\n\thasgroups: boolean;\n\t/** User account status in tenant (0 = member, 1 = guest) */\n\tacct: 0 | 1;\n\t/** Auth Context IDs */\n\tacrs: string;\n\t/** Time when the user last authenticated */\n\tauth_time: Date;\n\t/** User's country/region */\n\tctry: string;\n\t/** IP address of requesting client when inside VNET */\n\tfwd: string;\n\t/** Group claims */\n\tgroups: string;\n\t/** Login hint for SSO */\n\tlogin_hint: string;\n\t/** Resource tenant's country/region */\n\ttenant_ctry: string;\n\t/** Region of the resource tenant */\n\ttenant_region_scope: string;\n\t/** UserPrincipalName */\n\tupn: string;\n\t/** User's verified primary email addresses */\n\tverified_primary_email: string[];\n\t/** User's verified secondary email addresses */\n\tverified_secondary_email: string[];\n\t/** Whether the user's email is verified (optional claim, must be configured in app registration) */\n\temail_verified?: boolean | undefined;\n\t/** VNET specifier information */\n\tvnet: string;\n\t/** Client Capabilities */\n\txms_cc: string;\n\t/** Whether user's email domain is verified */\n\txms_edov: boolean;\n\t/** Preferred data location for Multi-Geo tenants */\n\txms_pdl: string;\n\t/** User preferred language */\n\txms_pl: string;\n\t/** Tenant preferred language */\n\txms_tpl: string;\n\t/** Zero-touch Deployment ID */\n\tztdid: string;\n\t/** IP Address */\n\tipaddr: string;\n\t/** On-premises Security Identifier */\n\tonprem_sid: string;\n\t/** Password Expiration Time */\n\tpwd_exp: number;\n\t/** Change Password URL */\n\tpwd_url: string;\n\t/** Inside Corporate Network flag */\n\tin_corp: string;\n\t/** User's family name/surname */\n\tfamily_name: string;\n\t/** User's given/first name */\n\tgiven_name: string;\n}\n\nexport interface MicrosoftOptions\n\textends ProviderOptions<MicrosoftEntraIDProfile> {\n\tclientId: string;\n\t/**\n\t * The tenant ID of the Microsoft account\n\t * @default \"common\"\n\t */\n\ttenantId?: string | undefined;\n\t/**\n\t * The authentication authority URL. Use the default \"https://login.microsoftonline.com\" for standard Entra ID or \"https://<tenant-id>.ciamlogin.com\" for CIAM scenarios.\n\t * @default \"https://login.microsoftonline.com\"\n\t */\n\tauthority?: string | undefined;\n\t/**\n\t * The size of the profile photo\n\t * @default 48\n\t */\n\tprofilePhotoSize?:\n\t\t| (48 | 64 | 96 | 120 | 240 | 360 | 432 | 504 | 648)\n\t\t| undefined;\n\t/**\n\t * Disable profile photo\n\t */\n\tdisableProfilePhoto?: boolean | undefined;\n}\n\nexport const microsoft = (options: MicrosoftOptions) => {\n\tconst tenant = options.tenantId || \"common\";\n\tconst authority = options.authority || \"https://login.microsoftonline.com\";\n\tconst authorizationEndpoint = `${authority}/${tenant}/oauth2/v2.0/authorize`;\n\tconst tokenEndpoint = `${authority}/${tenant}/oauth2/v2.0/token`;\n\treturn {\n\t\tid: \"microsoft\",\n\t\tname: \"Microsoft EntraID\",\n\t\tcreateAuthorizationURL(data) {\n\t\t\tconst scopes = options.disableDefaultScope\n\t\t\t\t? []\n\t\t\t\t: [\"openid\", \"profile\", \"email\", \"User.Read\", \"offline_access\"];\n\t\t\tif (options.scope) scopes.push(...options.scope);\n\t\t\tif (data.scopes) scopes.push(...data.scopes);\n\t\t\treturn createAuthorizationURL({\n\t\t\t\tid: \"microsoft\",\n\t\t\t\toptions,\n\t\t\t\tauthorizationEndpoint,\n\t\t\t\tstate: data.state,\n\t\t\t\tcodeVerifier: data.codeVerifier,\n\t\t\t\tscopes,\n\t\t\t\tredirectURI: data.redirectURI,\n\t\t\t\tprompt: options.prompt,\n\t\t\t\tloginHint: data.loginHint,\n\t\t\t});\n\t\t},\n\t\tvalidateAuthorizationCode({ 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\n\t\t\ttry {\n\t\t\t\tconst { kid, alg: jwtAlg } = decodeProtectedHeader(token);\n\t\t\t\tif (!kid || !jwtAlg) return false;\n\n\t\t\t\tconst publicKey = await getMicrosoftPublicKey(kid, tenant, authority);\n\t\t\t\tconst verifyOptions: {\n\t\t\t\t\talgorithms: [string];\n\t\t\t\t\taudience: string;\n\t\t\t\t\tmaxTokenAge: string;\n\t\t\t\t\tissuer?: string;\n\t\t\t\t} = {\n\t\t\t\t\talgorithms: [jwtAlg],\n\t\t\t\t\taudience: options.clientId,\n\t\t\t\t\tmaxTokenAge: \"1h\",\n\t\t\t\t};\n\t\t\t\t/**\n\t\t\t\t * Issuer varies per user's tenant for multi-tenant endpoints, so only validate for specific tenants.\n\t\t\t\t * @see https://learn.microsoft.com/en-us/entra/identity-platform/v2-protocols#endpoints\n\t\t\t\t */\n\t\t\t\tif (\n\t\t\t\t\ttenant !== \"common\" &&\n\t\t\t\t\ttenant !== \"organizations\" &&\n\t\t\t\t\ttenant !== \"consumers\"\n\t\t\t\t) {\n\t\t\t\t\tverifyOptions.issuer = `${authority}/${tenant}/v2.0`;\n\t\t\t\t}\n\t\t\t\tconst { payload: jwtClaims } = await jwtVerify(\n\t\t\t\t\ttoken,\n\t\t\t\t\tpublicKey,\n\t\t\t\t\tverifyOptions,\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\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\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 MicrosoftEntraIDProfile;\n\t\t\tconst profilePhotoSize = options.profilePhotoSize || 48;\n\t\t\tawait betterFetch<ArrayBuffer>(\n\t\t\t\t`https://graph.microsoft.com/v1.0/me/photos/${profilePhotoSize}x${profilePhotoSize}/$value`,\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\tasync onResponse(context) {\n\t\t\t\t\t\tif (options.disableProfilePhoto || !context.response.ok) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst response = context.response.clone();\n\t\t\t\t\t\t\tconst pictureBuffer = await response.arrayBuffer();\n\t\t\t\t\t\t\tconst pictureBase64 = base64.encode(pictureBuffer);\n\t\t\t\t\t\t\tuser.picture = `data:image/jpeg;base64, ${pictureBase64}`;\n\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t\tlogger.error(\n\t\t\t\t\t\t\t\te && typeof e === \"object\" && \"name\" in e\n\t\t\t\t\t\t\t\t\t? (e.name as string)\n\t\t\t\t\t\t\t\t\t: \"\",\n\t\t\t\t\t\t\t\te,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\t\t\tconst userMap = await options.mapProfileToUser?.(user);\n\t\t\t// Microsoft Entra ID does NOT include email_verified claim by default.\n\t\t\t// It must be configured as an optional claim in the app registration.\n\t\t\t// We default to false when not provided for security consistency.\n\t\t\t// We can also check verified_primary_email/verified_secondary_email arrays as fallback.\n\t\t\tconst emailVerified =\n\t\t\t\tuser.email_verified !== undefined\n\t\t\t\t\t? user.email_verified\n\t\t\t\t\t: user.email &&\n\t\t\t\t\t\t\t(user.verified_primary_email?.includes(user.email) ||\n\t\t\t\t\t\t\t\tuser.verified_secondary_email?.includes(user.email))\n\t\t\t\t\t\t? true\n\t\t\t\t\t\t: false;\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,\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\trefreshAccessToken: options.refreshAccessToken\n\t\t\t? options.refreshAccessToken\n\t\t\t: async (refreshToken) => {\n\t\t\t\t\tconst scopes = options.disableDefaultScope\n\t\t\t\t\t\t? []\n\t\t\t\t\t\t: [\"openid\", \"profile\", \"email\", \"User.Read\", \"offline_access\"];\n\t\t\t\t\tif (options.scope) scopes.push(...options.scope);\n\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\textraParams: {\n\t\t\t\t\t\t\tscope: scopes.join(\" \"), // Include the scopes in request to microsoft\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\t\toptions,\n\t} satisfies OAuthProvider;\n};\n\nexport const getMicrosoftPublicKey = async (\n\tkid: string,\n\ttenant: string,\n\tauthority: string,\n) => {\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\tx5c?: string[];\n\t\t\tx5t?: string;\n\t\t}>;\n\t}>(`${authority}/${tenant}/discovery/v2.0/keys`);\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":"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"}
|
|
1
|
+
{"version":3,"file":"microsoft-entra-id.mjs","names":[],"sources":["../../src/social-providers/microsoft-entra-id.ts"],"sourcesContent":["import { base64 } from \"@better-auth/utils/base64\";\nimport { betterFetch } from \"@better-fetch/fetch\";\nimport { decodeJwt, decodeProtectedHeader, importJWK, jwtVerify } from \"jose\";\nimport { logger } from \"../env\";\nimport { APIError } from \"../error\";\nimport type { OAuthProvider, ProviderOptions } from \"../oauth2\";\nimport {\n\tcreateAuthorizationURL,\n\trefreshAccessToken,\n\tvalidateAuthorizationCode,\n} from \"../oauth2\";\n\n/**\n * @see [Microsoft Identity Platform - Optional claims reference](https://learn.microsoft.com/en-us/entra/identity-platform/optional-claims-reference)\n */\nexport interface MicrosoftEntraIDProfile extends Record<string, any> {\n\t/** Identifies the intended recipient of the token */\n\taud: string;\n\t/** Identifies the issuer, or \"authorization server\" that constructs and returns the token */\n\tiss: string;\n\t/** Indicates when the authentication for the token occurred */\n\tiat: Date;\n\t/** Records the identity provider that authenticated the subject of the token */\n\tidp: string;\n\t/** Identifies the time before which the JWT can't be accepted for processing */\n\tnbf: Date;\n\t/** Identifies the expiration time on or after which the JWT can't be accepted for processing */\n\texp: Date;\n\t/** Code hash included in ID tokens when issued with an OAuth 2.0 authorization code */\n\tc_hash: string;\n\t/** Access token hash included in ID tokens when issued with an OAuth 2.0 access token */\n\tat_hash: string;\n\t/** Internal claim used to record data for token reuse */\n\taio: string;\n\t/** The primary username that represents the user */\n\tpreferred_username: string;\n\t/** User's email address */\n\temail: string;\n\t/** Human-readable value that identifies the subject of the token */\n\tname: string;\n\t/** Matches the parameter included in the original authorize request */\n\tnonce: string;\n\t/** User's profile picture */\n\tpicture: string;\n\t/** Immutable identifier for the user account */\n\toid: string;\n\t/** Set of roles assigned to the user */\n\troles: string[];\n\t/** Internal claim used to revalidate tokens */\n\trh: string;\n\t/** Subject identifier - unique to application ID */\n\tsub: string;\n\t/** Tenant ID the user is signing in to */\n\ttid: string;\n\t/** Unique identifier for a session */\n\tsid: string;\n\t/** Token identifier claim */\n\tuti: string;\n\t/** Indicates if user is in at least one group */\n\thasgroups: boolean;\n\t/** User account status in tenant (0 = member, 1 = guest) */\n\tacct: 0 | 1;\n\t/** Auth Context IDs */\n\tacrs: string;\n\t/** Time when the user last authenticated */\n\tauth_time: Date;\n\t/** User's country/region */\n\tctry: string;\n\t/** IP address of requesting client when inside VNET */\n\tfwd: string;\n\t/** Group claims */\n\tgroups: string;\n\t/** Login hint for SSO */\n\tlogin_hint: string;\n\t/** Resource tenant's country/region */\n\ttenant_ctry: string;\n\t/** Region of the resource tenant */\n\ttenant_region_scope: string;\n\t/** UserPrincipalName */\n\tupn: string;\n\t/** User's verified primary email addresses */\n\tverified_primary_email: string[];\n\t/** User's verified secondary email addresses */\n\tverified_secondary_email: string[];\n\t/** Whether the user's email is verified (optional claim, must be configured in app registration) */\n\temail_verified?: boolean | undefined;\n\t/** VNET specifier information */\n\tvnet: string;\n\t/** Client Capabilities */\n\txms_cc: string;\n\t/** Whether user's email domain is verified */\n\txms_edov: boolean;\n\t/** Preferred data location for Multi-Geo tenants */\n\txms_pdl: string;\n\t/** User preferred language */\n\txms_pl: string;\n\t/** Tenant preferred language */\n\txms_tpl: string;\n\t/** Zero-touch Deployment ID */\n\tztdid: string;\n\t/** IP Address */\n\tipaddr: string;\n\t/** On-premises Security Identifier */\n\tonprem_sid: string;\n\t/** Password Expiration Time */\n\tpwd_exp: number;\n\t/** Change Password URL */\n\tpwd_url: string;\n\t/** Inside Corporate Network flag */\n\tin_corp: string;\n\t/** User's family name/surname */\n\tfamily_name: string;\n\t/** User's given/first name */\n\tgiven_name: string;\n}\n\nexport interface MicrosoftOptions\n\textends ProviderOptions<MicrosoftEntraIDProfile> {\n\tclientId: string;\n\t/**\n\t * The tenant ID of the Microsoft account\n\t * @default \"common\"\n\t */\n\ttenantId?: string | undefined;\n\t/**\n\t * The authentication authority URL. Use the default \"https://login.microsoftonline.com\" for standard Entra ID or \"https://<tenant-id>.ciamlogin.com\" for CIAM scenarios.\n\t * @default \"https://login.microsoftonline.com\"\n\t */\n\tauthority?: string | undefined;\n\t/**\n\t * The size of the profile photo\n\t * @default 48\n\t */\n\tprofilePhotoSize?:\n\t\t| (48 | 64 | 96 | 120 | 240 | 360 | 432 | 504 | 648)\n\t\t| undefined;\n\t/**\n\t * Disable profile photo\n\t */\n\tdisableProfilePhoto?: boolean | undefined;\n}\n\nexport const microsoft = (options: MicrosoftOptions) => {\n\tconst tenant = options.tenantId || \"common\";\n\tconst authority = options.authority || \"https://login.microsoftonline.com\";\n\tconst authorizationEndpoint = `${authority}/${tenant}/oauth2/v2.0/authorize`;\n\tconst tokenEndpoint = `${authority}/${tenant}/oauth2/v2.0/token`;\n\treturn {\n\t\tid: \"microsoft\",\n\t\tname: \"Microsoft EntraID\",\n\t\tcreateAuthorizationURL(data) {\n\t\t\tconst scopes = options.disableDefaultScope\n\t\t\t\t? []\n\t\t\t\t: [\"openid\", \"profile\", \"email\", \"User.Read\", \"offline_access\"];\n\t\t\tif (options.scope) scopes.push(...options.scope);\n\t\t\tif (data.scopes) scopes.push(...data.scopes);\n\t\t\treturn createAuthorizationURL({\n\t\t\t\tid: \"microsoft\",\n\t\t\t\toptions,\n\t\t\t\tauthorizationEndpoint,\n\t\t\t\tstate: data.state,\n\t\t\t\tcodeVerifier: data.codeVerifier,\n\t\t\t\tscopes,\n\t\t\t\tredirectURI: data.redirectURI,\n\t\t\t\tprompt: options.prompt,\n\t\t\t\tloginHint: data.loginHint,\n\t\t\t});\n\t\t},\n\t\tvalidateAuthorizationCode({ 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\n\t\t\ttry {\n\t\t\t\tconst { kid, alg: jwtAlg } = decodeProtectedHeader(token);\n\t\t\t\tif (!kid || !jwtAlg) return false;\n\n\t\t\t\tconst publicKey = await getMicrosoftPublicKey(kid, tenant, authority);\n\t\t\t\tconst verifyOptions: {\n\t\t\t\t\talgorithms: [string];\n\t\t\t\t\taudience: string;\n\t\t\t\t\tmaxTokenAge: string;\n\t\t\t\t\tissuer?: string;\n\t\t\t\t} = {\n\t\t\t\t\talgorithms: [jwtAlg],\n\t\t\t\t\taudience: options.clientId,\n\t\t\t\t\tmaxTokenAge: \"1h\",\n\t\t\t\t};\n\t\t\t\t/**\n\t\t\t\t * Issuer varies per user's tenant for multi-tenant endpoints, so only validate for specific tenants.\n\t\t\t\t * @see https://learn.microsoft.com/en-us/entra/identity-platform/v2-protocols#endpoints\n\t\t\t\t */\n\t\t\t\tif (\n\t\t\t\t\ttenant !== \"common\" &&\n\t\t\t\t\ttenant !== \"organizations\" &&\n\t\t\t\t\ttenant !== \"consumers\"\n\t\t\t\t) {\n\t\t\t\t\tverifyOptions.issuer = `${authority}/${tenant}/v2.0`;\n\t\t\t\t}\n\t\t\t\tconst { payload: jwtClaims } = await jwtVerify(\n\t\t\t\t\ttoken,\n\t\t\t\t\tpublicKey,\n\t\t\t\t\tverifyOptions,\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\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\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 MicrosoftEntraIDProfile;\n\t\t\tconst profilePhotoSize = options.profilePhotoSize || 48;\n\t\t\tawait betterFetch<ArrayBuffer>(\n\t\t\t\t`https://graph.microsoft.com/v1.0/me/photos/${profilePhotoSize}x${profilePhotoSize}/$value`,\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\tasync onResponse(context) {\n\t\t\t\t\t\tif (options.disableProfilePhoto || !context.response.ok) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst response = context.response.clone();\n\t\t\t\t\t\t\tconst pictureBuffer = await response.arrayBuffer();\n\t\t\t\t\t\t\tconst pictureBase64 = base64.encode(pictureBuffer);\n\t\t\t\t\t\t\tuser.picture = `data:image/jpeg;base64, ${pictureBase64}`;\n\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t\tlogger.error(\n\t\t\t\t\t\t\t\te && typeof e === \"object\" && \"name\" in e\n\t\t\t\t\t\t\t\t\t? (e.name as string)\n\t\t\t\t\t\t\t\t\t: \"\",\n\t\t\t\t\t\t\t\te,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\t\t\tconst userMap = await options.mapProfileToUser?.(user);\n\t\t\t// Microsoft Entra ID does NOT include email_verified claim by default.\n\t\t\t// It must be configured as an optional claim in the app registration.\n\t\t\t// We default to false when not provided for security consistency.\n\t\t\t// We can also check verified_primary_email/verified_secondary_email arrays as fallback.\n\t\t\tconst emailVerified =\n\t\t\t\tuser.email_verified !== undefined\n\t\t\t\t\t? user.email_verified\n\t\t\t\t\t: user.email &&\n\t\t\t\t\t\t\t(user.verified_primary_email?.includes(user.email) ||\n\t\t\t\t\t\t\t\tuser.verified_secondary_email?.includes(user.email))\n\t\t\t\t\t\t? true\n\t\t\t\t\t\t: false;\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,\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\trefreshAccessToken: options.refreshAccessToken\n\t\t\t? options.refreshAccessToken\n\t\t\t: async (refreshToken) => {\n\t\t\t\t\tconst scopes = options.disableDefaultScope\n\t\t\t\t\t\t? []\n\t\t\t\t\t\t: [\"openid\", \"profile\", \"email\", \"User.Read\", \"offline_access\"];\n\t\t\t\t\tif (options.scope) scopes.push(...options.scope);\n\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\textraParams: {\n\t\t\t\t\t\t\tscope: scopes.join(\" \"), // Include the scopes in request to microsoft\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\t\toptions,\n\t} satisfies OAuthProvider;\n};\n\nexport const getMicrosoftPublicKey = async (\n\tkid: string,\n\ttenant: string,\n\tauthority: string,\n) => {\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\tx5c?: string[];\n\t\t\tx5t?: string;\n\t\t}>;\n\t}>(`${authority}/${tenant}/discovery/v2.0/keys`);\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":"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"}
|
|
@@ -3,9 +3,9 @@ import { refreshAccessToken } from "../oauth2/refresh-access-token.mjs";
|
|
|
3
3
|
import { validateAuthorizationCode } from "../oauth2/validate-authorization-code.mjs";
|
|
4
4
|
import "../oauth2/index.mjs";
|
|
5
5
|
import { betterFetch } from "@better-fetch/fetch";
|
|
6
|
-
|
|
7
6
|
//#region src/social-providers/naver.ts
|
|
8
7
|
const naver = (options) => {
|
|
8
|
+
const tokenEndpoint = "https://nid.naver.com/oauth2.0/token";
|
|
9
9
|
return {
|
|
10
10
|
id: "naver",
|
|
11
11
|
name: "Naver",
|
|
@@ -27,7 +27,7 @@ const naver = (options) => {
|
|
|
27
27
|
code,
|
|
28
28
|
redirectURI,
|
|
29
29
|
options,
|
|
30
|
-
tokenEndpoint
|
|
30
|
+
tokenEndpoint
|
|
31
31
|
});
|
|
32
32
|
},
|
|
33
33
|
refreshAccessToken: options.refreshAccessToken ? options.refreshAccessToken : async (refreshToken) => {
|
|
@@ -38,7 +38,7 @@ const naver = (options) => {
|
|
|
38
38
|
clientKey: options.clientKey,
|
|
39
39
|
clientSecret: options.clientSecret
|
|
40
40
|
},
|
|
41
|
-
tokenEndpoint
|
|
41
|
+
tokenEndpoint
|
|
42
42
|
});
|
|
43
43
|
},
|
|
44
44
|
async getUserInfo(token) {
|
|
@@ -62,7 +62,7 @@ const naver = (options) => {
|
|
|
62
62
|
options
|
|
63
63
|
};
|
|
64
64
|
};
|
|
65
|
-
|
|
66
65
|
//#endregion
|
|
67
66
|
export { naver };
|
|
67
|
+
|
|
68
68
|
//# sourceMappingURL=naver.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"naver.mjs","names":[],"sources":["../../src/social-providers/naver.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 NaverProfile {\n\t/** API response result code */\n\tresultcode: string;\n\t/** API response message */\n\tmessage: string;\n\tresponse: {\n\t\t/** Unique Naver user identifier */\n\t\tid: string;\n\t\t/** User nickname */\n\t\tnickname: string;\n\t\t/** User real name */\n\t\tname: string;\n\t\t/** User email address */\n\t\temail: string;\n\t\t/** Gender (F: female, M: male, U: unknown) */\n\t\tgender: string;\n\t\t/** Age range */\n\t\tage: string;\n\t\t/** Birthday (MM-DD format) */\n\t\tbirthday: string;\n\t\t/** Birth year */\n\t\tbirthyear: string;\n\t\t/** Profile image URL */\n\t\tprofile_image: string;\n\t\t/** Mobile phone number */\n\t\tmobile: string;\n\t};\n}\n\nexport interface NaverOptions extends ProviderOptions<NaverProfile> {\n\tclientId: string;\n}\n\nexport const naver = (options: NaverOptions) => {\n\treturn {\n\t\tid: \"naver\",\n\t\tname: \"Naver\",\n\t\tcreateAuthorizationURL({ state, scopes, redirectURI }) {\n\t\t\tconst _scopes = options.disableDefaultScope ? [] : [\"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: \"naver\",\n\t\t\t\toptions,\n\t\t\t\tauthorizationEndpoint: \"https://nid.naver.com/oauth2.0/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
|
|
1
|
+
{"version":3,"file":"naver.mjs","names":[],"sources":["../../src/social-providers/naver.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 NaverProfile {\n\t/** API response result code */\n\tresultcode: string;\n\t/** API response message */\n\tmessage: string;\n\tresponse: {\n\t\t/** Unique Naver user identifier */\n\t\tid: string;\n\t\t/** User nickname */\n\t\tnickname: string;\n\t\t/** User real name */\n\t\tname: string;\n\t\t/** User email address */\n\t\temail: string;\n\t\t/** Gender (F: female, M: male, U: unknown) */\n\t\tgender: string;\n\t\t/** Age range */\n\t\tage: string;\n\t\t/** Birthday (MM-DD format) */\n\t\tbirthday: string;\n\t\t/** Birth year */\n\t\tbirthyear: string;\n\t\t/** Profile image URL */\n\t\tprofile_image: string;\n\t\t/** Mobile phone number */\n\t\tmobile: string;\n\t};\n}\n\nexport interface NaverOptions extends ProviderOptions<NaverProfile> {\n\tclientId: string;\n}\n\nexport const naver = (options: NaverOptions) => {\n\tconst tokenEndpoint = \"https://nid.naver.com/oauth2.0/token\";\n\treturn {\n\t\tid: \"naver\",\n\t\tname: \"Naver\",\n\t\tcreateAuthorizationURL({ state, scopes, redirectURI }) {\n\t\t\tconst _scopes = options.disableDefaultScope ? [] : [\"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: \"naver\",\n\t\t\t\toptions,\n\t\t\t\tauthorizationEndpoint: \"https://nid.naver.com/oauth2.0/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,\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,\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<NaverProfile>(\n\t\t\t\t\"https://openapi.naver.com/v1/nid/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 || profile.resultcode !== \"00\") {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst userMap = await options.mapProfileToUser?.(profile);\n\t\t\tconst res = profile.response || {};\n\t\t\tconst user = {\n\t\t\t\tid: res.id,\n\t\t\t\tname: res.name || res.nickname || \"\",\n\t\t\t\temail: res.email,\n\t\t\t\timage: res.profile_image,\n\t\t\t\temailVerified: false,\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<NaverProfile>;\n};\n"],"mappings":";;;;;;AAyCA,MAAa,SAAS,YAA0B;CAC/C,MAAM,gBAAgB;AACtB,QAAO;EACN,IAAI;EACJ,MAAM;EACN,uBAAuB,EAAE,OAAO,QAAQ,eAAe;GACtD,MAAM,UAAU,QAAQ,sBAAsB,EAAE,GAAG,CAAC,WAAW,QAAQ;AACvE,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;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;IACA,CAAC;;EAEL,MAAM,YAAY,OAAO;AACxB,OAAI,QAAQ,YACX,QAAO,QAAQ,YAAY,MAAM;GAElC,MAAM,EAAE,MAAM,SAAS,UAAU,MAAM,YACtC,uCACA,EACC,SAAS,EACR,eAAe,UAAU,MAAM,eAC/B,EACD,CACD;AACD,OAAI,SAAS,CAAC,WAAW,QAAQ,eAAe,KAC/C,QAAO;GAER,MAAM,UAAU,MAAM,QAAQ,mBAAmB,QAAQ;GACzD,MAAM,MAAM,QAAQ,YAAY,EAAE;AASlC,UAAO;IACN,MATY;KACZ,IAAI,IAAI;KACR,MAAM,IAAI,QAAQ,IAAI,YAAY;KAClC,OAAO,IAAI;KACX,OAAO,IAAI;KACX,eAAe;KACf,GAAG;KACH;IAGA,MAAM;IACN;;EAEF;EACA"}
|