@better-auth/core 1.7.0-rc.1 → 1.7.0-rc.3
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 +28 -28
- package/dist/async_hooks/index.d.mts +0 -1
- package/dist/async_hooks/pure.index.d.mts +0 -1
- package/dist/context/endpoint-context.d.mts +1 -1
- package/dist/context/global.d.mts +0 -1
- package/dist/context/global.mjs +1 -1
- package/dist/context/request-state.d.mts +0 -1
- package/dist/context/request-state.mjs +8 -5
- package/dist/context/transaction.d.mts +8 -3
- package/dist/context/transaction.mjs +27 -10
- package/dist/db/adapter/factory.d.mts +3 -5
- package/dist/db/adapter/factory.mjs +7 -5
- package/dist/db/adapter/get-default-field-name.d.mts +2 -9
- package/dist/db/adapter/get-default-model-name.d.mts +1 -5
- package/dist/db/adapter/get-default-model-name.mjs +6 -5
- package/dist/db/adapter/get-field-attributes.d.mts +4 -11
- package/dist/db/adapter/get-field-name.d.mts +2 -9
- package/dist/db/adapter/get-id-field.d.mts +4 -12
- package/dist/db/adapter/get-model-name.d.mts +1 -5
- package/dist/db/adapter/index.d.mts +7 -32
- package/dist/db/adapter/types.d.mts +5 -17
- package/dist/db/adapter/utils.d.mts +0 -1
- package/dist/db/database-index.d.mts +44 -0
- package/dist/db/database-index.mjs +168 -0
- package/dist/db/get-tables.d.mts +7 -1
- package/dist/db/get-tables.mjs +47 -6
- package/dist/db/index.d.mts +3 -3
- package/dist/db/index.mjs +2 -2
- package/dist/db/internal.d.mts +3 -0
- package/dist/db/internal.mjs +3 -0
- package/dist/db/plugin.d.mts +4 -3
- package/dist/db/schema/account.d.mts +16 -3
- package/dist/db/schema/account.mjs +35 -2
- package/dist/db/schema/rate-limit.d.mts +1 -1
- package/dist/db/schema/rate-limit.mjs +9 -0
- package/dist/db/schema/session.d.mts +1 -1
- package/dist/db/schema/shared.d.mts +0 -1
- package/dist/db/schema/user.d.mts +1 -1
- package/dist/db/schema/verification.d.mts +1 -1
- package/dist/db/type.d.mts +17 -9
- package/dist/env/logger.d.mts +25 -25
- package/dist/error/codes.d.mts +0 -1
- package/dist/error/index.d.mts +0 -1
- package/dist/index.d.mts +1 -1
- package/dist/instrumentation/attributes.d.mts +0 -1
- package/dist/instrumentation/pure.index.d.mts +0 -1
- package/dist/instrumentation/tracer.mjs +1 -1
- package/dist/oauth2/authorization-params.d.mts +0 -1
- package/dist/oauth2/client-assertion.d.mts +3 -13
- package/dist/oauth2/client-credentials-token.d.mts +3 -17
- package/dist/oauth2/client-credentials-token.mjs +1 -4
- package/dist/oauth2/create-authorization-url.d.mts +3 -21
- package/dist/oauth2/dpop.d.mts +2 -23
- package/dist/oauth2/dpop.mjs +1 -1
- package/dist/oauth2/index.d.mts +3 -3
- package/dist/oauth2/index.mjs +2 -2
- package/dist/oauth2/oauth-provider.d.mts +94 -36
- package/dist/oauth2/refresh-access-token.d.mts +3 -19
- package/dist/oauth2/refresh-access-token.mjs +3 -9
- package/dist/oauth2/reject-redirects.mjs +1 -1
- package/dist/oauth2/token-endpoint-auth.d.mts +0 -1
- package/dist/oauth2/utils.d.mts +0 -1
- package/dist/oauth2/utils.mjs +2 -3
- package/dist/oauth2/validate-authorization-code.d.mts +5 -29
- package/dist/oauth2/verify-id-token.d.mts +3 -2
- package/dist/oauth2/verify-id-token.mjs +3 -3
- package/dist/oauth2/verify.d.mts +18 -9
- package/dist/oauth2/verify.mjs +68 -5
- package/dist/social-providers/apple.d.mts +9 -24
- package/dist/social-providers/apple.mjs +2 -1
- package/dist/social-providers/atlassian.d.mts +18 -19
- package/dist/social-providers/atlassian.mjs +1 -1
- package/dist/social-providers/cognito.d.mts +33 -22
- package/dist/social-providers/cognito.mjs +2 -2
- package/dist/social-providers/discord.d.mts +7 -20
- package/dist/social-providers/discord.mjs +1 -1
- package/dist/social-providers/dropbox.d.mts +7 -22
- package/dist/social-providers/dropbox.mjs +1 -1
- package/dist/social-providers/facebook.d.mts +19 -27
- package/dist/social-providers/facebook.mjs +6 -17
- package/dist/social-providers/figma.d.mts +7 -22
- package/dist/social-providers/figma.mjs +1 -1
- package/dist/social-providers/github.d.mts +7 -23
- package/dist/social-providers/github.mjs +1 -1
- package/dist/social-providers/gitlab.d.mts +6 -43
- package/dist/social-providers/gitlab.mjs +1 -1
- package/dist/social-providers/google.d.mts +10 -32
- package/dist/social-providers/google.mjs +2 -1
- package/dist/social-providers/huggingface.d.mts +7 -22
- package/dist/social-providers/huggingface.mjs +1 -1
- package/dist/social-providers/index.d.mts +229 -787
- package/dist/social-providers/kakao.d.mts +8 -33
- package/dist/social-providers/kakao.mjs +1 -1
- package/dist/social-providers/kick.d.mts +7 -22
- package/dist/social-providers/kick.mjs +1 -1
- package/dist/social-providers/line.d.mts +8 -44
- package/dist/social-providers/line.mjs +4 -6
- package/dist/social-providers/linear.d.mts +7 -21
- package/dist/social-providers/linear.mjs +1 -1
- package/dist/social-providers/linkedin.d.mts +7 -21
- package/dist/social-providers/linkedin.mjs +1 -1
- package/dist/social-providers/microsoft-entra-id.d.mts +8 -18
- package/dist/social-providers/microsoft-entra-id.mjs +24 -4
- package/dist/social-providers/naver.d.mts +27 -42
- package/dist/social-providers/naver.mjs +1 -1
- package/dist/social-providers/notion.d.mts +7 -21
- package/dist/social-providers/notion.mjs +1 -1
- package/dist/social-providers/paybin.d.mts +8 -23
- package/dist/social-providers/paybin.mjs +2 -1
- package/dist/social-providers/paypal.d.mts +8 -33
- package/dist/social-providers/paypal.mjs +1 -1
- package/dist/social-providers/polar.d.mts +7 -22
- package/dist/social-providers/polar.mjs +1 -1
- package/dist/social-providers/railway.d.mts +7 -22
- package/dist/social-providers/railway.mjs +1 -1
- package/dist/social-providers/reddit.d.mts +7 -20
- package/dist/social-providers/reddit.mjs +1 -1
- package/dist/social-providers/roblox.d.mts +7 -20
- package/dist/social-providers/roblox.mjs +1 -1
- package/dist/social-providers/salesforce.d.mts +7 -22
- package/dist/social-providers/salesforce.mjs +1 -1
- package/dist/social-providers/slack.d.mts +7 -20
- package/dist/social-providers/slack.mjs +1 -1
- package/dist/social-providers/spotify.d.mts +7 -22
- package/dist/social-providers/spotify.mjs +1 -1
- package/dist/social-providers/tiktok.d.mts +10 -22
- package/dist/social-providers/tiktok.mjs +1 -1
- package/dist/social-providers/twitch.d.mts +7 -20
- package/dist/social-providers/twitch.mjs +1 -1
- package/dist/social-providers/twitter.d.mts +29 -26
- package/dist/social-providers/twitter.mjs +1 -1
- package/dist/social-providers/vercel.d.mts +7 -22
- package/dist/social-providers/vercel.mjs +1 -1
- package/dist/social-providers/vk.d.mts +8 -24
- package/dist/social-providers/vk.mjs +5 -6
- package/dist/social-providers/wechat.d.mts +7 -19
- package/dist/social-providers/wechat.mjs +1 -1
- package/dist/social-providers/zoom.d.mts +9 -25
- package/dist/social-providers/zoom.mjs +1 -1
- package/dist/types/context.d.mts +16 -9
- package/dist/types/cookie.d.mts +0 -1
- package/dist/types/helper.d.mts +1 -1
- package/dist/types/index.d.mts +1 -1
- package/dist/types/init-options.d.mts +37 -26
- package/dist/types/plugin-client.d.mts +1 -3
- package/dist/types/plugin.d.mts +2 -2
- package/dist/utils/async.d.mts +0 -1
- package/dist/utils/db.d.mts +1 -0
- package/dist/utils/deprecate.d.mts +0 -1
- package/dist/utils/error-codes.d.mts +2 -2
- package/dist/utils/host.d.mts +27 -1
- package/dist/utils/host.mjs +1 -1
- package/dist/utils/ip.d.mts +1 -0
- package/dist/utils/ip.mjs +1 -1
- package/dist/utils/is-api-error.d.mts +0 -1
- package/dist/utils/redirect-uri.d.mts +6 -2
- package/dist/utils/redirect-uri.mjs +11 -1
- package/package.json +10 -2
- package/src/context/request-state.ts +26 -6
- package/src/context/transaction.ts +37 -18
- package/src/db/adapter/factory.ts +34 -28
- package/src/db/adapter/get-default-model-name.ts +23 -14
- package/src/db/database-index.ts +351 -0
- package/src/db/get-tables.ts +89 -9
- package/src/db/index.ts +4 -0
- package/src/db/internal.ts +12 -0
- package/src/db/plugin.ts +3 -1
- package/src/db/schema/account.ts +27 -1
- package/src/db/schema/user.ts +1 -1
- package/src/db/type.ts +12 -0
- package/src/error/codes.ts +1 -0
- package/src/oauth2/index.ts +5 -0
- package/src/oauth2/oauth-provider.ts +105 -36
- package/src/oauth2/verify-id-token.ts +4 -2
- package/src/oauth2/verify.ts +121 -12
- package/src/social-providers/apple.ts +2 -1
- package/src/social-providers/atlassian.ts +1 -1
- package/src/social-providers/cognito.ts +2 -2
- package/src/social-providers/discord.ts +1 -1
- package/src/social-providers/dropbox.ts +1 -1
- package/src/social-providers/facebook.ts +21 -28
- package/src/social-providers/figma.ts +1 -1
- package/src/social-providers/github.ts +1 -1
- package/src/social-providers/gitlab.ts +1 -1
- package/src/social-providers/google.ts +2 -1
- package/src/social-providers/huggingface.ts +1 -1
- package/src/social-providers/kakao.ts +1 -1
- package/src/social-providers/kick.ts +1 -1
- package/src/social-providers/line.ts +7 -12
- package/src/social-providers/linear.ts +1 -1
- package/src/social-providers/linkedin.ts +1 -1
- package/src/social-providers/microsoft-entra-id.ts +36 -27
- package/src/social-providers/naver.ts +1 -1
- package/src/social-providers/notion.ts +1 -1
- package/src/social-providers/paybin.ts +2 -1
- package/src/social-providers/paypal.ts +1 -1
- package/src/social-providers/polar.ts +1 -1
- package/src/social-providers/railway.ts +1 -1
- package/src/social-providers/reddit.ts +1 -1
- package/src/social-providers/roblox.ts +1 -1
- package/src/social-providers/salesforce.ts +1 -1
- package/src/social-providers/slack.ts +1 -1
- package/src/social-providers/spotify.ts +1 -1
- package/src/social-providers/tiktok.ts +2 -2
- package/src/social-providers/twitch.ts +1 -1
- package/src/social-providers/twitter.ts +1 -1
- package/src/social-providers/vercel.ts +1 -1
- package/src/social-providers/vk.ts +2 -2
- package/src/social-providers/wechat.ts +1 -1
- package/src/social-providers/zoom.ts +1 -1
- package/src/types/context.ts +21 -14
- package/src/types/init-options.ts +15 -14
- package/src/utils/redirect-uri.ts +20 -0
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
refreshAccessToken,
|
|
10
10
|
validateAuthorizationCode,
|
|
11
11
|
} from "../oauth2";
|
|
12
|
-
export interface
|
|
12
|
+
export interface FacebookGraphProfile {
|
|
13
13
|
id: string;
|
|
14
14
|
name: string;
|
|
15
15
|
email?: string;
|
|
@@ -24,6 +24,17 @@ export interface FacebookProfile {
|
|
|
24
24
|
};
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
+
export interface FacebookLimitedLoginProfile {
|
|
28
|
+
sub: string;
|
|
29
|
+
email: string;
|
|
30
|
+
name: string;
|
|
31
|
+
picture: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export type FacebookProfile =
|
|
35
|
+
| FacebookGraphProfile
|
|
36
|
+
| FacebookLimitedLoginProfile;
|
|
37
|
+
|
|
27
38
|
interface FacebookDebugTokenData {
|
|
28
39
|
app_id?: string;
|
|
29
40
|
is_valid?: boolean;
|
|
@@ -95,6 +106,9 @@ export const facebook = (options: FacebookOptions) => {
|
|
|
95
106
|
return {
|
|
96
107
|
id: "facebook",
|
|
97
108
|
name: "Facebook",
|
|
109
|
+
accountSubject: ({ profile }) =>
|
|
110
|
+
"sub" in profile ? profile.sub : profile.id,
|
|
111
|
+
accountIssuer: "https://www.facebook.com",
|
|
98
112
|
async createAuthorizationURL({
|
|
99
113
|
state,
|
|
100
114
|
scopes,
|
|
@@ -167,38 +181,18 @@ export const facebook = (options: FacebookOptions) => {
|
|
|
167
181
|
}
|
|
168
182
|
|
|
169
183
|
if (token.idToken && token.idToken.split(".").length === 3) {
|
|
170
|
-
const profile = decodeJwt(token.idToken) as
|
|
171
|
-
sub: string;
|
|
172
|
-
email: string;
|
|
173
|
-
name: string;
|
|
174
|
-
picture: string;
|
|
175
|
-
};
|
|
176
|
-
|
|
177
|
-
const user = {
|
|
178
|
-
id: profile.sub,
|
|
179
|
-
name: profile.name,
|
|
180
|
-
email: profile.email,
|
|
181
|
-
picture: {
|
|
182
|
-
data: {
|
|
183
|
-
url: profile.picture,
|
|
184
|
-
height: 100,
|
|
185
|
-
width: 100,
|
|
186
|
-
is_silhouette: false,
|
|
187
|
-
},
|
|
188
|
-
},
|
|
189
|
-
};
|
|
184
|
+
const profile = decodeJwt(token.idToken) as FacebookLimitedLoginProfile;
|
|
190
185
|
|
|
191
186
|
// https://developers.facebook.com/docs/facebook-login/limited-login/permissions
|
|
192
187
|
// Facebook ID token does not include email_verified claim.
|
|
193
188
|
// We default to false for security consistency.
|
|
194
|
-
const userMap = await options.mapProfileToUser?.(
|
|
195
|
-
...user,
|
|
196
|
-
email_verified: false,
|
|
197
|
-
});
|
|
189
|
+
const userMap = await options.mapProfileToUser?.(profile);
|
|
198
190
|
|
|
199
191
|
return {
|
|
200
192
|
user: {
|
|
201
|
-
|
|
193
|
+
name: profile.name,
|
|
194
|
+
email: profile.email,
|
|
195
|
+
image: profile.picture,
|
|
202
196
|
emailVerified: false,
|
|
203
197
|
...userMap,
|
|
204
198
|
},
|
|
@@ -228,7 +222,7 @@ export const facebook = (options: FacebookOptions) => {
|
|
|
228
222
|
"picture",
|
|
229
223
|
...(options?.fields || []),
|
|
230
224
|
];
|
|
231
|
-
const { data: profile, error } = await betterFetch<
|
|
225
|
+
const { data: profile, error } = await betterFetch<FacebookGraphProfile>(
|
|
232
226
|
"https://graph.facebook.com/me?fields=" + fields.join(","),
|
|
233
227
|
{
|
|
234
228
|
auth: {
|
|
@@ -247,7 +241,6 @@ export const facebook = (options: FacebookOptions) => {
|
|
|
247
241
|
const userMap = await options.mapProfileToUser?.(profile);
|
|
248
242
|
return {
|
|
249
243
|
user: {
|
|
250
|
-
id: profile.id,
|
|
251
244
|
name: profile.name,
|
|
252
245
|
email: profile.email,
|
|
253
246
|
image: profile.picture.data.url,
|
|
@@ -24,6 +24,7 @@ export const figma = (options: FigmaOptions) => {
|
|
|
24
24
|
return {
|
|
25
25
|
id: "figma",
|
|
26
26
|
name: "Figma",
|
|
27
|
+
accountSubject: ({ profile }) => profile.id,
|
|
27
28
|
async createAuthorizationURL({
|
|
28
29
|
state,
|
|
29
30
|
scopes,
|
|
@@ -106,7 +107,6 @@ export const figma = (options: FigmaOptions) => {
|
|
|
106
107
|
|
|
107
108
|
return {
|
|
108
109
|
user: {
|
|
109
|
-
id: profile.id,
|
|
110
110
|
name: profile.handle,
|
|
111
111
|
email: profile.email,
|
|
112
112
|
image: profile.img_url,
|
|
@@ -63,6 +63,7 @@ export const github = (options: GithubOptions) => {
|
|
|
63
63
|
return {
|
|
64
64
|
id: "github",
|
|
65
65
|
name: "GitHub",
|
|
66
|
+
accountSubject: ({ profile }) => profile.id,
|
|
66
67
|
createAuthorizationURL({
|
|
67
68
|
state,
|
|
68
69
|
scopes,
|
|
@@ -171,7 +172,6 @@ export const github = (options: GithubOptions) => {
|
|
|
171
172
|
const userMap = await options.mapProfileToUser?.(profile);
|
|
172
173
|
return {
|
|
173
174
|
user: {
|
|
174
|
-
id: profile.id,
|
|
175
175
|
name: profile.name || profile.login || "",
|
|
176
176
|
email: profile.email,
|
|
177
177
|
image: profile.avatar_url,
|
|
@@ -81,6 +81,7 @@ export const gitlab = (options: GitlabOptions) => {
|
|
|
81
81
|
return {
|
|
82
82
|
id: issuerId,
|
|
83
83
|
name: issuerName,
|
|
84
|
+
accountSubject: ({ profile }) => profile.id,
|
|
84
85
|
createAuthorizationURL: async ({
|
|
85
86
|
state,
|
|
86
87
|
scopes,
|
|
@@ -142,7 +143,6 @@ export const gitlab = (options: GitlabOptions) => {
|
|
|
142
143
|
// We check for it first, then default to false for security consistency.
|
|
143
144
|
return {
|
|
144
145
|
user: {
|
|
145
|
-
id: profile.id,
|
|
146
146
|
name: profile.name ?? profile.username ?? "",
|
|
147
147
|
email: profile.email,
|
|
148
148
|
image: profile.avatar_url,
|
|
@@ -150,6 +150,8 @@ export const google = (options: GoogleOptions) => {
|
|
|
150
150
|
return {
|
|
151
151
|
id: "google",
|
|
152
152
|
name: "Google",
|
|
153
|
+
accountSubject: ({ profile }) => profile.sub,
|
|
154
|
+
accountIssuer: "https://accounts.google.com",
|
|
153
155
|
async createAuthorizationURL({
|
|
154
156
|
state,
|
|
155
157
|
scopes,
|
|
@@ -254,7 +256,6 @@ export const google = (options: GoogleOptions) => {
|
|
|
254
256
|
const userMap = await options.mapProfileToUser?.(user);
|
|
255
257
|
return {
|
|
256
258
|
user: {
|
|
257
|
-
id: user.sub,
|
|
258
259
|
name: user.name,
|
|
259
260
|
email: user.email,
|
|
260
261
|
image: user.picture,
|
|
@@ -47,6 +47,7 @@ export const huggingface = (options: HuggingFaceOptions) => {
|
|
|
47
47
|
return {
|
|
48
48
|
id: "huggingface",
|
|
49
49
|
name: "Hugging Face",
|
|
50
|
+
accountSubject: ({ profile }) => profile.sub,
|
|
50
51
|
createAuthorizationURL({
|
|
51
52
|
state,
|
|
52
53
|
scopes,
|
|
@@ -111,7 +112,6 @@ export const huggingface = (options: HuggingFaceOptions) => {
|
|
|
111
112
|
const userMap = await options.mapProfileToUser?.(profile);
|
|
112
113
|
return {
|
|
113
114
|
user: {
|
|
114
|
-
id: profile.sub,
|
|
115
115
|
name: profile.name || profile.preferred_username || "",
|
|
116
116
|
email: profile.email,
|
|
117
117
|
image: profile.picture,
|
|
@@ -106,6 +106,7 @@ export const kakao = (options: KakaoOptions) => {
|
|
|
106
106
|
return {
|
|
107
107
|
id: "kakao",
|
|
108
108
|
name: "Kakao",
|
|
109
|
+
accountSubject: ({ profile }) => profile.id,
|
|
109
110
|
createAuthorizationURL({ state, scopes, redirectURI, additionalParams }) {
|
|
110
111
|
const _scopes = options.disableDefaultScope
|
|
111
112
|
? []
|
|
@@ -162,7 +163,6 @@ export const kakao = (options: KakaoOptions) => {
|
|
|
162
163
|
const account = profile.kakao_account || {};
|
|
163
164
|
const kakaoProfile = account.profile || {};
|
|
164
165
|
const user = {
|
|
165
|
-
id: String(profile.id),
|
|
166
166
|
name: kakaoProfile.nickname || account.name || "",
|
|
167
167
|
email: account.email,
|
|
168
168
|
image:
|
|
@@ -33,6 +33,7 @@ export const kick = (options: KickOptions) => {
|
|
|
33
33
|
return {
|
|
34
34
|
id: "kick",
|
|
35
35
|
name: "Kick",
|
|
36
|
+
accountSubject: ({ profile }) => profile.user_id,
|
|
36
37
|
createAuthorizationURL({
|
|
37
38
|
state,
|
|
38
39
|
scopes,
|
|
@@ -101,7 +102,6 @@ export const kick = (options: KickOptions) => {
|
|
|
101
102
|
// We default to false for security consistency.
|
|
102
103
|
return {
|
|
103
104
|
user: {
|
|
104
|
-
id: profile.user_id,
|
|
105
105
|
name: profile.name,
|
|
106
106
|
email: profile.email,
|
|
107
107
|
image: profile.profile_picture,
|
|
@@ -50,6 +50,8 @@ export const line = (options: LineOptions) => {
|
|
|
50
50
|
return {
|
|
51
51
|
id: "line",
|
|
52
52
|
name: "LINE",
|
|
53
|
+
accountSubject: ({ profile }) => profile.sub,
|
|
54
|
+
accountIssuer: "https://access.line.me",
|
|
53
55
|
async createAuthorizationURL({
|
|
54
56
|
state,
|
|
55
57
|
scopes,
|
|
@@ -142,24 +144,17 @@ export const line = (options: LineOptions) => {
|
|
|
142
144
|
profile = data || null;
|
|
143
145
|
}
|
|
144
146
|
if (!profile) return null;
|
|
145
|
-
const userMap = await options.mapProfileToUser?.(profile
|
|
146
|
-
// ID preference order
|
|
147
|
-
const id = (profile as any).sub || (profile as any).userId;
|
|
148
|
-
const name = (profile as any).name || (profile as any).displayName || "";
|
|
149
|
-
const image =
|
|
150
|
-
(profile as any).picture || (profile as any).pictureUrl || undefined;
|
|
151
|
-
const email = (profile as any).email;
|
|
147
|
+
const userMap = await options.mapProfileToUser?.(profile);
|
|
152
148
|
return {
|
|
153
149
|
user: {
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
image,
|
|
150
|
+
name: profile.name || "",
|
|
151
|
+
email: profile.email,
|
|
152
|
+
image: profile.picture,
|
|
158
153
|
// LINE does not expose email verification status in ID token/userinfo
|
|
159
154
|
emailVerified: false,
|
|
160
155
|
...userMap,
|
|
161
156
|
},
|
|
162
|
-
data: profile
|
|
157
|
+
data: profile,
|
|
163
158
|
};
|
|
164
159
|
},
|
|
165
160
|
options,
|
|
@@ -31,6 +31,7 @@ export const linear = (options: LinearOptions) => {
|
|
|
31
31
|
return {
|
|
32
32
|
id: "linear",
|
|
33
33
|
name: "Linear",
|
|
34
|
+
accountSubject: ({ profile }) => profile.id,
|
|
34
35
|
createAuthorizationURL({
|
|
35
36
|
state,
|
|
36
37
|
scopes,
|
|
@@ -113,7 +114,6 @@ export const linear = (options: LinearOptions) => {
|
|
|
113
114
|
// We default to false for security consistency.
|
|
114
115
|
return {
|
|
115
116
|
user: {
|
|
116
|
-
id: profile.data.viewer.id,
|
|
117
117
|
name: profile.data.viewer.name,
|
|
118
118
|
email: profile.data.viewer.email,
|
|
119
119
|
image: profile.data.viewer.avatarUrl,
|
|
@@ -32,6 +32,7 @@ export const linkedin = (options: LinkedInOptions) => {
|
|
|
32
32
|
return {
|
|
33
33
|
id: "linkedin",
|
|
34
34
|
name: "Linkedin",
|
|
35
|
+
accountSubject: ({ profile }) => profile.sub,
|
|
35
36
|
createAuthorizationURL: async ({
|
|
36
37
|
state,
|
|
37
38
|
scopes,
|
|
@@ -97,7 +98,6 @@ export const linkedin = (options: LinkedInOptions) => {
|
|
|
97
98
|
const userMap = await options.mapProfileToUser?.(profile);
|
|
98
99
|
return {
|
|
99
100
|
user: {
|
|
100
|
-
id: profile.sub,
|
|
101
101
|
name: profile.name,
|
|
102
102
|
email: profile.email,
|
|
103
103
|
emailVerified: profile.email_verified ?? false,
|
|
@@ -187,6 +187,8 @@ export const microsoft = (options: MicrosoftOptions) => {
|
|
|
187
187
|
return {
|
|
188
188
|
id: "microsoft",
|
|
189
189
|
name: "Microsoft EntraID",
|
|
190
|
+
accountSubject: ({ profile }) => profile.oid,
|
|
191
|
+
accountIssuer: ({ profile }) => profile.iss,
|
|
190
192
|
createAuthorizationURL(data) {
|
|
191
193
|
// Microsoft Entra supports public clients (SPA / native apps with
|
|
192
194
|
// PKCE only), so clientSecret is intentionally not required here.
|
|
@@ -277,33 +279,41 @@ export const microsoft = (options: MicrosoftOptions) => {
|
|
|
277
279
|
return null;
|
|
278
280
|
}
|
|
279
281
|
const user = decodeJwt(token.idToken) as MicrosoftEntraIDProfile;
|
|
282
|
+
if (typeof user.oid !== "string" || user.oid.trim().length === 0) {
|
|
283
|
+
logger.error(
|
|
284
|
+
"Microsoft Entra ID token did not include a valid oid claim; unable to resolve a stable account identifier.",
|
|
285
|
+
);
|
|
286
|
+
return null;
|
|
287
|
+
}
|
|
280
288
|
const profilePhotoSize = options.profilePhotoSize || 48;
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
289
|
+
if (!options.disableProfilePhoto && token.accessToken) {
|
|
290
|
+
await betterFetch<ArrayBuffer>(
|
|
291
|
+
`https://graph.microsoft.com/v1.0/me/photos/${profilePhotoSize}x${profilePhotoSize}/$value`,
|
|
292
|
+
{
|
|
293
|
+
headers: {
|
|
294
|
+
Authorization: `Bearer ${token.accessToken}`,
|
|
295
|
+
},
|
|
296
|
+
async onResponse(context) {
|
|
297
|
+
if (!context.response.ok) {
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
try {
|
|
301
|
+
const response = context.response.clone();
|
|
302
|
+
const pictureBuffer = await response.arrayBuffer();
|
|
303
|
+
const pictureBase64 = base64.encode(pictureBuffer);
|
|
304
|
+
user.picture = `data:image/jpeg;base64, ${pictureBase64}`;
|
|
305
|
+
} catch (e) {
|
|
306
|
+
logger.error(
|
|
307
|
+
e && typeof e === "object" && "name" in e
|
|
308
|
+
? (e.name as string)
|
|
309
|
+
: "",
|
|
310
|
+
e,
|
|
311
|
+
);
|
|
312
|
+
}
|
|
313
|
+
},
|
|
304
314
|
},
|
|
305
|
-
|
|
306
|
-
|
|
315
|
+
);
|
|
316
|
+
}
|
|
307
317
|
const userMap = await options.mapProfileToUser?.(user);
|
|
308
318
|
// Microsoft Entra ID does NOT include email_verified claim by default.
|
|
309
319
|
// It must be configured as an optional claim in the app registration.
|
|
@@ -319,7 +329,6 @@ export const microsoft = (options: MicrosoftOptions) => {
|
|
|
319
329
|
: false;
|
|
320
330
|
return {
|
|
321
331
|
user: {
|
|
322
|
-
id: user.sub,
|
|
323
332
|
name: user.name,
|
|
324
333
|
email: user.email,
|
|
325
334
|
image: user.picture,
|
|
@@ -351,7 +360,7 @@ export const microsoft = (options: MicrosoftOptions) => {
|
|
|
351
360
|
});
|
|
352
361
|
},
|
|
353
362
|
options,
|
|
354
|
-
} satisfies OAuthProvider
|
|
363
|
+
} satisfies OAuthProvider<MicrosoftEntraIDProfile>;
|
|
355
364
|
};
|
|
356
365
|
|
|
357
366
|
export const getMicrosoftPublicKey = async (
|
|
@@ -44,6 +44,7 @@ export const naver = (options: NaverOptions) => {
|
|
|
44
44
|
return {
|
|
45
45
|
id: "naver",
|
|
46
46
|
name: "Naver",
|
|
47
|
+
accountSubject: ({ profile }) => profile.response.id,
|
|
47
48
|
createAuthorizationURL({ state, scopes, redirectURI, additionalParams }) {
|
|
48
49
|
const _scopes = options.disableDefaultScope ? [] : ["profile", "email"];
|
|
49
50
|
if (options.scope) _scopes.push(...options.scope);
|
|
@@ -97,7 +98,6 @@ export const naver = (options: NaverOptions) => {
|
|
|
97
98
|
const userMap = await options.mapProfileToUser?.(profile);
|
|
98
99
|
const res = profile.response || {};
|
|
99
100
|
const user = {
|
|
100
|
-
id: res.id,
|
|
101
101
|
name: res.name || res.nickname || "",
|
|
102
102
|
email: res.email,
|
|
103
103
|
image: res.profile_image,
|
|
@@ -28,6 +28,7 @@ export const notion = (options: NotionOptions) => {
|
|
|
28
28
|
return {
|
|
29
29
|
id: "notion",
|
|
30
30
|
name: "Notion",
|
|
31
|
+
accountSubject: ({ profile }) => profile.id,
|
|
31
32
|
createAuthorizationURL({
|
|
32
33
|
state,
|
|
33
34
|
scopes,
|
|
@@ -100,7 +101,6 @@ export const notion = (options: NotionOptions) => {
|
|
|
100
101
|
const userMap = await options.mapProfileToUser?.(userProfile);
|
|
101
102
|
return {
|
|
102
103
|
user: {
|
|
103
|
-
id: userProfile.id,
|
|
104
104
|
name: userProfile.name || "",
|
|
105
105
|
email: userProfile.person?.email || null,
|
|
106
106
|
image: userProfile.avatar_url,
|
|
@@ -36,6 +36,8 @@ export const paybin = (options: PaybinOptions) => {
|
|
|
36
36
|
return {
|
|
37
37
|
id: "paybin",
|
|
38
38
|
name: "Paybin",
|
|
39
|
+
accountSubject: ({ profile }) => profile.sub,
|
|
40
|
+
accountIssuer: issuer,
|
|
39
41
|
async createAuthorizationURL({
|
|
40
42
|
state,
|
|
41
43
|
scopes,
|
|
@@ -105,7 +107,6 @@ export const paybin = (options: PaybinOptions) => {
|
|
|
105
107
|
const userMap = await options.mapProfileToUser?.(user);
|
|
106
108
|
return {
|
|
107
109
|
user: {
|
|
108
|
-
id: user.sub,
|
|
109
110
|
name: user.name || user.preferred_username || "",
|
|
110
111
|
email: user.email,
|
|
111
112
|
image: user.picture,
|
|
@@ -79,6 +79,7 @@ export const paypal = (options: PayPalOptions) => {
|
|
|
79
79
|
return {
|
|
80
80
|
id: "paypal",
|
|
81
81
|
name: "PayPal",
|
|
82
|
+
accountSubject: ({ profile }) => profile.user_id,
|
|
82
83
|
async createAuthorizationURL({
|
|
83
84
|
state,
|
|
84
85
|
codeVerifier,
|
|
@@ -252,7 +253,6 @@ export const paypal = (options: PayPalOptions) => {
|
|
|
252
253
|
|
|
253
254
|
const result = {
|
|
254
255
|
user: {
|
|
255
|
-
id: userInfo.user_id,
|
|
256
256
|
name: userInfo.name,
|
|
257
257
|
email: userInfo.email,
|
|
258
258
|
image: userInfo.picture,
|
|
@@ -37,6 +37,7 @@ export const polar = (options: PolarOptions) => {
|
|
|
37
37
|
return {
|
|
38
38
|
id: "polar",
|
|
39
39
|
name: "Polar",
|
|
40
|
+
accountSubject: ({ profile }) => profile.id,
|
|
40
41
|
createAuthorizationURL({
|
|
41
42
|
state,
|
|
42
43
|
scopes,
|
|
@@ -103,7 +104,6 @@ export const polar = (options: PolarOptions) => {
|
|
|
103
104
|
// We check for it first, then default to false for security consistency.
|
|
104
105
|
return {
|
|
105
106
|
user: {
|
|
106
|
-
id: profile.id,
|
|
107
107
|
name: profile.public_name || profile.username || "",
|
|
108
108
|
email: profile.email,
|
|
109
109
|
image: profile.avatar_url,
|
|
@@ -29,6 +29,7 @@ export const railway = (options: RailwayOptions) => {
|
|
|
29
29
|
return {
|
|
30
30
|
id: "railway",
|
|
31
31
|
name: "Railway",
|
|
32
|
+
accountSubject: ({ profile }) => profile.sub,
|
|
32
33
|
createAuthorizationURL({
|
|
33
34
|
state,
|
|
34
35
|
scopes,
|
|
@@ -92,7 +93,6 @@ export const railway = (options: RailwayOptions) => {
|
|
|
92
93
|
// We default to false for security consistency.
|
|
93
94
|
return {
|
|
94
95
|
user: {
|
|
95
|
-
id: profile.sub,
|
|
96
96
|
name: profile.name,
|
|
97
97
|
email: profile.email,
|
|
98
98
|
image: profile.picture,
|
|
@@ -25,6 +25,7 @@ export const reddit = (options: RedditOptions) => {
|
|
|
25
25
|
return {
|
|
26
26
|
id: "reddit",
|
|
27
27
|
name: "Reddit",
|
|
28
|
+
accountSubject: ({ profile }) => profile.id,
|
|
28
29
|
createAuthorizationURL({ state, scopes, redirectURI, additionalParams }) {
|
|
29
30
|
const _scopes = options.disableDefaultScope ? [] : ["identity"];
|
|
30
31
|
if (options.scope) _scopes.push(...options.scope);
|
|
@@ -112,7 +113,6 @@ export const reddit = (options: RedditOptions) => {
|
|
|
112
113
|
const email = userMap?.email || `${profile.id}@reddit.invalid`;
|
|
113
114
|
return {
|
|
114
115
|
user: {
|
|
115
|
-
id: profile.id,
|
|
116
116
|
name: profile.name,
|
|
117
117
|
image: profile.icon_img?.split("?")[0]!,
|
|
118
118
|
...userMap,
|
|
@@ -41,6 +41,7 @@ export const roblox = (options: RobloxOptions) => {
|
|
|
41
41
|
return {
|
|
42
42
|
id: "roblox",
|
|
43
43
|
name: "Roblox",
|
|
44
|
+
accountSubject: ({ profile }) => profile.sub,
|
|
44
45
|
createAuthorizationURL({ state, scopes, redirectURI, additionalParams }) {
|
|
45
46
|
const _scopes = options.disableDefaultScope ? [] : ["openid", "profile"];
|
|
46
47
|
if (options.scope) _scopes.push(...options.scope);
|
|
@@ -100,7 +101,6 @@ export const roblox = (options: RobloxOptions) => {
|
|
|
100
101
|
// We default to false for security consistency.
|
|
101
102
|
return {
|
|
102
103
|
user: {
|
|
103
|
-
id: profile.sub,
|
|
104
104
|
name: profile.nickname || profile.preferred_username || "",
|
|
105
105
|
image: profile.picture,
|
|
106
106
|
email: profile.preferred_username || null, // Roblox does not provide email
|
|
@@ -63,6 +63,7 @@ export const salesforce = (options: SalesforceOptions) => {
|
|
|
63
63
|
return {
|
|
64
64
|
id: "salesforce",
|
|
65
65
|
name: "Salesforce",
|
|
66
|
+
accountSubject: ({ profile }) => profile.user_id,
|
|
66
67
|
|
|
67
68
|
async createAuthorizationURL({
|
|
68
69
|
state,
|
|
@@ -146,7 +147,6 @@ export const salesforce = (options: SalesforceOptions) => {
|
|
|
146
147
|
|
|
147
148
|
return {
|
|
148
149
|
user: {
|
|
149
|
-
id: user.user_id,
|
|
150
150
|
name: user.name,
|
|
151
151
|
email: user.email,
|
|
152
152
|
image: user.photos?.picture || user.photos?.thumbnail,
|
|
@@ -46,6 +46,7 @@ export const slack = (options: SlackOptions) => {
|
|
|
46
46
|
return {
|
|
47
47
|
id: "slack",
|
|
48
48
|
name: "Slack",
|
|
49
|
+
accountSubject: ({ profile }) => profile["https://slack.com/user_id"],
|
|
49
50
|
createAuthorizationURL({ state, scopes, redirectURI, additionalParams }) {
|
|
50
51
|
const _scopes = options.disableDefaultScope
|
|
51
52
|
? []
|
|
@@ -103,7 +104,6 @@ export const slack = (options: SlackOptions) => {
|
|
|
103
104
|
const userMap = await options.mapProfileToUser?.(profile);
|
|
104
105
|
return {
|
|
105
106
|
user: {
|
|
106
|
-
id: profile["https://slack.com/user_id"],
|
|
107
107
|
name: profile.name || "",
|
|
108
108
|
email: profile.email,
|
|
109
109
|
emailVerified: profile.email_verified,
|
|
@@ -24,6 +24,7 @@ export const spotify = (options: SpotifyOptions) => {
|
|
|
24
24
|
return {
|
|
25
25
|
id: "spotify",
|
|
26
26
|
name: "Spotify",
|
|
27
|
+
accountSubject: ({ profile }) => profile.id,
|
|
27
28
|
createAuthorizationURL({
|
|
28
29
|
state,
|
|
29
30
|
scopes,
|
|
@@ -86,7 +87,6 @@ export const spotify = (options: SpotifyOptions) => {
|
|
|
86
87
|
const userMap = await options.mapProfileToUser?.(profile);
|
|
87
88
|
return {
|
|
88
89
|
user: {
|
|
89
|
-
id: profile.id,
|
|
90
90
|
name: profile.display_name,
|
|
91
91
|
email: profile.email,
|
|
92
92
|
image: profile.images[0]?.url,
|
|
@@ -123,7 +123,7 @@ export interface TiktokProfile extends Record<string, any> {
|
|
|
123
123
|
| undefined;
|
|
124
124
|
}
|
|
125
125
|
|
|
126
|
-
export interface TiktokOptions extends ProviderOptions {
|
|
126
|
+
export interface TiktokOptions extends ProviderOptions<TiktokProfile> {
|
|
127
127
|
// Client ID is not used in TikTok, we delete it from the options
|
|
128
128
|
clientId?: never | undefined;
|
|
129
129
|
clientSecret: string;
|
|
@@ -135,6 +135,7 @@ export const tiktok = (options: TiktokOptions) => {
|
|
|
135
135
|
return {
|
|
136
136
|
id: "tiktok",
|
|
137
137
|
name: "TikTok",
|
|
138
|
+
accountSubject: ({ profile }) => profile.data.user.open_id,
|
|
138
139
|
createAuthorizationURL({ state, scopes, redirectURI, additionalParams }) {
|
|
139
140
|
const _scopes = options.disableDefaultScope ? [] : ["user.info.profile"];
|
|
140
141
|
if (options.scope) _scopes.push(...options.scope);
|
|
@@ -210,7 +211,6 @@ export const tiktok = (options: TiktokOptions) => {
|
|
|
210
211
|
return {
|
|
211
212
|
user: {
|
|
212
213
|
email: profile.data.user.email || profile.data.user.username,
|
|
213
|
-
id: profile.data.user.open_id,
|
|
214
214
|
name:
|
|
215
215
|
profile.data.user.display_name || profile.data.user.username || "",
|
|
216
216
|
image: profile.data.user.avatar_large_url,
|
|
@@ -42,6 +42,7 @@ export const twitch = (options: TwitchOptions) => {
|
|
|
42
42
|
return {
|
|
43
43
|
id: "twitch",
|
|
44
44
|
name: "Twitch",
|
|
45
|
+
accountSubject: ({ profile }) => profile.sub,
|
|
45
46
|
createAuthorizationURL({ state, scopes, redirectURI, additionalParams }) {
|
|
46
47
|
const _scopes = options.disableDefaultScope
|
|
47
48
|
? []
|
|
@@ -98,7 +99,6 @@ export const twitch = (options: TwitchOptions) => {
|
|
|
98
99
|
const userMap = await options.mapProfileToUser?.(profile);
|
|
99
100
|
return {
|
|
100
101
|
user: {
|
|
101
|
-
id: profile.sub,
|
|
102
102
|
name: profile.preferred_username,
|
|
103
103
|
email: profile.email,
|
|
104
104
|
image: profile.picture,
|
|
@@ -108,6 +108,7 @@ export const twitter = (options: TwitterOption) => {
|
|
|
108
108
|
return {
|
|
109
109
|
id: "twitter",
|
|
110
110
|
name: "Twitter",
|
|
111
|
+
accountSubject: ({ profile }) => profile.data.id,
|
|
111
112
|
createAuthorizationURL(data) {
|
|
112
113
|
const _scopes = options.disableDefaultScope
|
|
113
114
|
? []
|
|
@@ -185,7 +186,6 @@ export const twitter = (options: TwitterOption) => {
|
|
|
185
186
|
const userMap = await options.mapProfileToUser?.(profile);
|
|
186
187
|
return {
|
|
187
188
|
user: {
|
|
188
|
-
id: profile.data.id,
|
|
189
189
|
name: profile.data.name,
|
|
190
190
|
email: profile.data.email || profile.data.username || null,
|
|
191
191
|
image: profile.data.profile_image_url,
|
|
@@ -20,6 +20,7 @@ export const vercel = (options: VercelOptions) => {
|
|
|
20
20
|
return {
|
|
21
21
|
id: "vercel",
|
|
22
22
|
name: "Vercel",
|
|
23
|
+
accountSubject: ({ profile }) => profile.sub,
|
|
23
24
|
createAuthorizationURL({
|
|
24
25
|
state,
|
|
25
26
|
scopes,
|
|
@@ -79,7 +80,6 @@ export const vercel = (options: VercelOptions) => {
|
|
|
79
80
|
const userMap = await options.mapProfileToUser?.(profile);
|
|
80
81
|
return {
|
|
81
82
|
user: {
|
|
82
|
-
id: profile.sub,
|
|
83
83
|
name: profile.name ?? profile.preferred_username ?? "",
|
|
84
84
|
email: profile.email,
|
|
85
85
|
image: profile.picture,
|
|
@@ -20,7 +20,7 @@ export interface VkProfile {
|
|
|
20
20
|
};
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
export interface VkOption extends ProviderOptions {
|
|
23
|
+
export interface VkOption extends ProviderOptions<VkProfile> {
|
|
24
24
|
clientId: string;
|
|
25
25
|
scheme?: ("light" | "dark") | undefined;
|
|
26
26
|
}
|
|
@@ -30,6 +30,7 @@ export const vk = (options: VkOption) => {
|
|
|
30
30
|
return {
|
|
31
31
|
id: "vk",
|
|
32
32
|
name: "VK",
|
|
33
|
+
accountSubject: ({ profile }) => profile.user.user_id,
|
|
33
34
|
async createAuthorizationURL({
|
|
34
35
|
state,
|
|
35
36
|
scopes,
|
|
@@ -113,7 +114,6 @@ export const vk = (options: VkOption) => {
|
|
|
113
114
|
|
|
114
115
|
return {
|
|
115
116
|
user: {
|
|
116
|
-
id: profile.user.user_id,
|
|
117
117
|
first_name: profile.user.first_name,
|
|
118
118
|
last_name: profile.user.last_name,
|
|
119
119
|
email: profile.user.email,
|