@better-auth/core 1.7.0-beta.7 → 1.7.0-beta.9
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 +3 -3
- package/dist/context/global.mjs +1 -1
- package/dist/db/adapter/factory.mjs +1 -1
- package/dist/db/get-tables.mjs +3 -3
- package/dist/db/schema/account.d.mts +1 -1
- package/dist/db/schema/account.mjs +1 -1
- package/dist/error/codes.d.mts +0 -5
- package/dist/error/codes.mjs +0 -5
- package/dist/instrumentation/tracer.mjs +1 -1
- package/dist/oauth2/create-authorization-url.d.mts +1 -4
- package/dist/oauth2/create-authorization-url.mjs +1 -4
- package/dist/oauth2/index.d.mts +3 -4
- package/dist/oauth2/index.mjs +2 -3
- package/dist/oauth2/oauth-provider.d.mts +12 -50
- package/dist/oauth2/refresh-access-token.mjs +2 -1
- package/dist/oauth2/utils.d.mts +6 -1
- package/dist/oauth2/utils.mjs +24 -2
- package/dist/oauth2/verify-id-token.d.mts +6 -5
- package/dist/oauth2/verify-id-token.mjs +2 -2
- package/dist/social-providers/apple.d.mts +1 -5
- package/dist/social-providers/apple.mjs +5 -5
- package/dist/social-providers/atlassian.d.mts +1 -5
- package/dist/social-providers/atlassian.mjs +4 -4
- package/dist/social-providers/cognito.d.mts +1 -5
- package/dist/social-providers/cognito.mjs +11 -18
- package/dist/social-providers/discord.d.mts +1 -5
- package/dist/social-providers/discord.mjs +6 -7
- package/dist/social-providers/dropbox.d.mts +1 -5
- package/dist/social-providers/dropbox.mjs +5 -5
- package/dist/social-providers/facebook.d.mts +1 -5
- package/dist/social-providers/facebook.mjs +5 -5
- package/dist/social-providers/figma.d.mts +1 -5
- package/dist/social-providers/figma.mjs +5 -5
- package/dist/social-providers/github.d.mts +1 -5
- package/dist/social-providers/github.mjs +4 -4
- package/dist/social-providers/gitlab.d.mts +1 -5
- package/dist/social-providers/gitlab.mjs +6 -6
- package/dist/social-providers/google.d.mts +8 -10
- package/dist/social-providers/google.mjs +12 -13
- package/dist/social-providers/huggingface.d.mts +1 -5
- package/dist/social-providers/huggingface.mjs +8 -8
- package/dist/social-providers/index.d.mts +35 -177
- package/dist/social-providers/kakao.d.mts +1 -5
- package/dist/social-providers/kakao.mjs +8 -8
- package/dist/social-providers/kick.d.mts +1 -5
- package/dist/social-providers/kick.mjs +4 -4
- package/dist/social-providers/line.d.mts +1 -5
- package/dist/social-providers/line.mjs +10 -10
- package/dist/social-providers/linear.d.mts +1 -5
- package/dist/social-providers/linear.mjs +4 -4
- package/dist/social-providers/linkedin.d.mts +1 -5
- package/dist/social-providers/linkedin.mjs +10 -10
- package/dist/social-providers/microsoft-entra-id.d.mts +1 -5
- package/dist/social-providers/microsoft-entra-id.mjs +10 -11
- package/dist/social-providers/naver.d.mts +1 -5
- package/dist/social-providers/naver.mjs +4 -4
- package/dist/social-providers/notion.d.mts +1 -5
- package/dist/social-providers/notion.mjs +4 -4
- package/dist/social-providers/paybin.d.mts +1 -5
- package/dist/social-providers/paybin.mjs +10 -10
- package/dist/social-providers/paypal.d.mts +1 -5
- package/dist/social-providers/paypal.mjs +2 -8
- package/dist/social-providers/polar.d.mts +1 -5
- package/dist/social-providers/polar.mjs +8 -8
- package/dist/social-providers/railway.d.mts +1 -5
- package/dist/social-providers/railway.mjs +9 -9
- package/dist/social-providers/reddit.d.mts +1 -5
- package/dist/social-providers/reddit.mjs +5 -5
- package/dist/social-providers/roblox.d.mts +1 -5
- package/dist/social-providers/roblox.mjs +5 -5
- package/dist/social-providers/salesforce.d.mts +1 -5
- package/dist/social-providers/salesforce.mjs +8 -8
- package/dist/social-providers/slack.d.mts +1 -5
- package/dist/social-providers/slack.mjs +9 -9
- package/dist/social-providers/spotify.d.mts +1 -5
- package/dist/social-providers/spotify.mjs +5 -5
- package/dist/social-providers/tiktok.d.mts +1 -5
- package/dist/social-providers/tiktok.mjs +5 -9
- package/dist/social-providers/twitch.d.mts +1 -5
- package/dist/social-providers/twitch.mjs +4 -4
- package/dist/social-providers/twitter.d.mts +1 -5
- package/dist/social-providers/twitter.mjs +9 -9
- package/dist/social-providers/vercel.d.mts +1 -5
- package/dist/social-providers/vercel.mjs +7 -4
- package/dist/social-providers/vk.d.mts +1 -5
- package/dist/social-providers/vk.mjs +5 -5
- package/dist/social-providers/wechat.d.mts +1 -5
- package/dist/social-providers/wechat.mjs +5 -9
- package/dist/social-providers/zoom.d.mts +1 -6
- package/dist/social-providers/zoom.mjs +9 -15
- package/dist/types/context.d.mts +6 -2
- package/package.json +1 -1
- package/src/db/get-tables.ts +3 -8
- package/src/db/schema/account.ts +5 -14
- package/src/error/codes.ts +0 -5
- package/src/oauth2/create-authorization-url.ts +1 -1
- package/src/oauth2/index.ts +2 -12
- package/src/oauth2/oauth-provider.ts +11 -56
- package/src/oauth2/refresh-access-token.ts +3 -2
- package/src/oauth2/utils.ts +39 -1
- package/src/oauth2/verify-id-token.ts +7 -5
- package/src/social-providers/apple.ts +8 -13
- package/src/social-providers/atlassian.ts +8 -12
- package/src/social-providers/cognito.ts +11 -18
- package/src/social-providers/discord.ts +8 -19
- package/src/social-providers/dropbox.ts +7 -13
- package/src/social-providers/facebook.ts +9 -13
- package/src/social-providers/figma.ts +9 -13
- package/src/social-providers/github.ts +8 -12
- package/src/social-providers/gitlab.ts +8 -14
- package/src/social-providers/google.ts +23 -29
- package/src/social-providers/huggingface.ts +8 -12
- package/src/social-providers/kakao.ts +8 -16
- package/src/social-providers/kick.ts +7 -12
- package/src/social-providers/line.ts +10 -14
- package/src/social-providers/linear.ts +6 -12
- package/src/social-providers/linkedin.ts +10 -14
- package/src/social-providers/microsoft-entra-id.ts +8 -18
- package/src/social-providers/naver.ts +6 -12
- package/src/social-providers/notion.ts +6 -12
- package/src/social-providers/paybin.ts +11 -14
- package/src/social-providers/paypal.ts +8 -6
- package/src/social-providers/polar.ts +8 -12
- package/src/social-providers/railway.ts +9 -13
- package/src/social-providers/reddit.ts +7 -18
- package/src/social-providers/roblox.ts +7 -18
- package/src/social-providers/salesforce.ts +8 -12
- package/src/social-providers/slack.ts +9 -18
- package/src/social-providers/spotify.ts +7 -13
- package/src/social-providers/tiktok.ts +7 -13
- package/src/social-providers/twitch.ts +8 -12
- package/src/social-providers/twitter.ts +8 -17
- package/src/social-providers/vercel.ts +10 -16
- package/src/social-providers/vk.ts +7 -13
- package/src/social-providers/wechat.ts +8 -20
- package/src/social-providers/zoom.ts +6 -19
- package/src/types/context.ts +8 -2
- package/dist/oauth2/scopes.d.mts +0 -76
- package/dist/oauth2/scopes.mjs +0 -96
- package/src/oauth2/scopes.ts +0 -118
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { betterFetch } from "@better-fetch/fetch";
|
|
2
|
-
import type {
|
|
2
|
+
import type { OAuthProvider, ProviderOptions } from "../oauth2";
|
|
3
3
|
import {
|
|
4
4
|
createAuthorizationURL,
|
|
5
5
|
refreshAccessToken,
|
|
6
|
-
resolveRequestedScopes,
|
|
7
6
|
validateAuthorizationCode,
|
|
8
7
|
} from "../oauth2";
|
|
9
8
|
|
|
@@ -42,30 +41,22 @@ export interface SlackOptions extends ProviderOptions<SlackProfile> {
|
|
|
42
41
|
clientId: string;
|
|
43
42
|
}
|
|
44
43
|
|
|
45
|
-
const SLACK_DEFAULT_SCOPES = ["openid", "profile", "email"];
|
|
46
|
-
|
|
47
44
|
export const slack = (options: SlackOptions) => {
|
|
48
45
|
const tokenEndpoint = "https://slack.com/api/openid.connect.token";
|
|
49
46
|
return {
|
|
50
47
|
id: "slack",
|
|
51
48
|
name: "Slack",
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
}) {
|
|
59
|
-
const requestedScopes = resolveRequestedScopes(
|
|
60
|
-
options,
|
|
61
|
-
SLACK_DEFAULT_SCOPES,
|
|
62
|
-
scopes,
|
|
63
|
-
);
|
|
49
|
+
createAuthorizationURL({ state, scopes, redirectURI, additionalParams }) {
|
|
50
|
+
const _scopes = options.disableDefaultScope
|
|
51
|
+
? []
|
|
52
|
+
: ["openid", "profile", "email"];
|
|
53
|
+
if (scopes) _scopes.push(...scopes);
|
|
54
|
+
if (options.scope) _scopes.push(...options.scope);
|
|
64
55
|
return createAuthorizationURL({
|
|
65
56
|
id: "slack",
|
|
66
57
|
options,
|
|
67
58
|
authorizationEndpoint: "https://slack.com/openid/connect/authorize",
|
|
68
|
-
scopes:
|
|
59
|
+
scopes: _scopes,
|
|
69
60
|
state,
|
|
70
61
|
redirectURI,
|
|
71
62
|
additionalParams,
|
|
@@ -123,5 +114,5 @@ export const slack = (options: SlackOptions) => {
|
|
|
123
114
|
};
|
|
124
115
|
},
|
|
125
116
|
options,
|
|
126
|
-
} satisfies
|
|
117
|
+
} satisfies OAuthProvider<SlackProfile>;
|
|
127
118
|
};
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { betterFetch } from "@better-fetch/fetch";
|
|
2
|
-
import type {
|
|
2
|
+
import type { OAuthProvider, ProviderOptions } from "../oauth2";
|
|
3
3
|
import {
|
|
4
4
|
createAuthorizationURL,
|
|
5
5
|
refreshAccessToken,
|
|
6
|
-
resolveRequestedScopes,
|
|
7
6
|
validateAuthorizationCode,
|
|
8
7
|
} from "../oauth2";
|
|
9
8
|
|
|
@@ -20,31 +19,26 @@ export interface SpotifyOptions extends ProviderOptions<SpotifyProfile> {
|
|
|
20
19
|
clientId: string;
|
|
21
20
|
}
|
|
22
21
|
|
|
23
|
-
const SPOTIFY_DEFAULT_SCOPES = ["user-read-email"];
|
|
24
|
-
|
|
25
22
|
export const spotify = (options: SpotifyOptions) => {
|
|
26
23
|
const tokenEndpoint = "https://accounts.spotify.com/api/token";
|
|
27
24
|
return {
|
|
28
25
|
id: "spotify",
|
|
29
26
|
name: "Spotify",
|
|
30
|
-
|
|
31
|
-
async createAuthorizationURL({
|
|
27
|
+
createAuthorizationURL({
|
|
32
28
|
state,
|
|
33
29
|
scopes,
|
|
34
30
|
codeVerifier,
|
|
35
31
|
redirectURI,
|
|
36
32
|
additionalParams,
|
|
37
33
|
}) {
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
scopes,
|
|
42
|
-
);
|
|
34
|
+
const _scopes = options.disableDefaultScope ? [] : ["user-read-email"];
|
|
35
|
+
if (options.scope) _scopes.push(...options.scope);
|
|
36
|
+
if (scopes) _scopes.push(...scopes);
|
|
43
37
|
return createAuthorizationURL({
|
|
44
38
|
id: "spotify",
|
|
45
39
|
options,
|
|
46
40
|
authorizationEndpoint: "https://accounts.spotify.com/authorize",
|
|
47
|
-
scopes:
|
|
41
|
+
scopes: _scopes,
|
|
48
42
|
state,
|
|
49
43
|
codeVerifier,
|
|
50
44
|
redirectURI,
|
|
@@ -103,5 +97,5 @@ export const spotify = (options: SpotifyOptions) => {
|
|
|
103
97
|
};
|
|
104
98
|
},
|
|
105
99
|
options,
|
|
106
|
-
} satisfies
|
|
100
|
+
} satisfies OAuthProvider<SpotifyProfile>;
|
|
107
101
|
};
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { betterFetch } from "@better-fetch/fetch";
|
|
2
|
-
import type {
|
|
2
|
+
import type { OAuthProvider, ProviderOptions } from "../oauth2";
|
|
3
3
|
import {
|
|
4
4
|
RESERVED_AUTHORIZATION_PARAMS_SET,
|
|
5
5
|
refreshAccessToken,
|
|
6
|
-
resolveRequestedScopes,
|
|
7
6
|
validateAuthorizationCode,
|
|
8
7
|
} from "../oauth2";
|
|
9
8
|
|
|
@@ -131,24 +130,19 @@ export interface TiktokOptions extends ProviderOptions {
|
|
|
131
130
|
clientKey: string;
|
|
132
131
|
}
|
|
133
132
|
|
|
134
|
-
const TIKTOK_DEFAULT_SCOPES = ["user.info.profile"];
|
|
135
|
-
|
|
136
133
|
export const tiktok = (options: TiktokOptions) => {
|
|
137
134
|
const tokenEndpoint = "https://open.tiktokapis.com/v2/oauth/token/";
|
|
138
135
|
return {
|
|
139
136
|
id: "tiktok",
|
|
140
137
|
name: "TikTok",
|
|
141
|
-
callbackPath: "/callback/tiktok",
|
|
142
138
|
createAuthorizationURL({ state, scopes, redirectURI, additionalParams }) {
|
|
143
|
-
const
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
scopes,
|
|
147
|
-
);
|
|
139
|
+
const _scopes = options.disableDefaultScope ? [] : ["user.info.profile"];
|
|
140
|
+
if (options.scope) _scopes.push(...options.scope);
|
|
141
|
+
if (scopes) _scopes.push(...scopes);
|
|
148
142
|
// TikTok uses `client_key` instead of the standard `client_id`, so the
|
|
149
143
|
// shared createAuthorizationURL helper cannot be used directly.
|
|
150
144
|
const url = new URL("https://www.tiktok.com/v2/auth/authorize");
|
|
151
|
-
url.searchParams.set("scope",
|
|
145
|
+
url.searchParams.set("scope", _scopes.join(","));
|
|
152
146
|
url.searchParams.set("response_type", "code");
|
|
153
147
|
url.searchParams.set("client_key", options.clientKey);
|
|
154
148
|
url.searchParams.set("redirect_uri", options.redirectURI || redirectURI);
|
|
@@ -160,7 +154,7 @@ export const tiktok = (options: TiktokOptions) => {
|
|
|
160
154
|
url.searchParams.set(key, value);
|
|
161
155
|
}
|
|
162
156
|
}
|
|
163
|
-
return
|
|
157
|
+
return url;
|
|
164
158
|
},
|
|
165
159
|
|
|
166
160
|
validateAuthorizationCode: async ({ code, redirectURI }) => {
|
|
@@ -226,5 +220,5 @@ export const tiktok = (options: TiktokOptions) => {
|
|
|
226
220
|
};
|
|
227
221
|
},
|
|
228
222
|
options,
|
|
229
|
-
} satisfies
|
|
223
|
+
} satisfies OAuthProvider<TiktokProfile, TiktokOptions>;
|
|
230
224
|
};
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { decodeJwt } from "jose";
|
|
2
2
|
import { logger } from "../env";
|
|
3
|
-
import type {
|
|
3
|
+
import type { OAuthProvider, ProviderOptions } from "../oauth2";
|
|
4
4
|
import {
|
|
5
5
|
createAuthorizationURL,
|
|
6
6
|
refreshAccessToken,
|
|
7
|
-
resolveRequestedScopes,
|
|
8
7
|
validateAuthorizationCode,
|
|
9
8
|
} from "../oauth2";
|
|
10
9
|
|
|
@@ -38,26 +37,23 @@ export interface TwitchOptions extends ProviderOptions<TwitchProfile> {
|
|
|
38
37
|
clientId: string;
|
|
39
38
|
claims?: string[] | undefined;
|
|
40
39
|
}
|
|
41
|
-
const TWITCH_DEFAULT_SCOPES = ["user:read:email", "openid"];
|
|
42
|
-
|
|
43
40
|
export const twitch = (options: TwitchOptions) => {
|
|
44
41
|
const tokenEndpoint = "https://id.twitch.tv/oauth2/token";
|
|
45
42
|
return {
|
|
46
43
|
id: "twitch",
|
|
47
44
|
name: "Twitch",
|
|
48
|
-
callbackPath: "/callback/twitch",
|
|
49
45
|
createAuthorizationURL({ state, scopes, redirectURI, additionalParams }) {
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
);
|
|
46
|
+
const _scopes = options.disableDefaultScope
|
|
47
|
+
? []
|
|
48
|
+
: ["user:read:email", "openid"];
|
|
49
|
+
if (options.scope) _scopes.push(...options.scope);
|
|
50
|
+
if (scopes) _scopes.push(...scopes);
|
|
55
51
|
return createAuthorizationURL({
|
|
56
52
|
id: "twitch",
|
|
57
53
|
redirectURI,
|
|
58
54
|
options,
|
|
59
55
|
authorizationEndpoint: "https://id.twitch.tv/oauth2/authorize",
|
|
60
|
-
scopes:
|
|
56
|
+
scopes: _scopes,
|
|
61
57
|
state,
|
|
62
58
|
claims: options.claims || [
|
|
63
59
|
"email",
|
|
@@ -113,5 +109,5 @@ export const twitch = (options: TwitchOptions) => {
|
|
|
113
109
|
};
|
|
114
110
|
},
|
|
115
111
|
options,
|
|
116
|
-
} satisfies
|
|
112
|
+
} satisfies OAuthProvider<TwitchProfile>;
|
|
117
113
|
};
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { betterFetch } from "@better-fetch/fetch";
|
|
2
|
-
import type {
|
|
2
|
+
import type { OAuthProvider, ProviderOptions } from "../oauth2";
|
|
3
3
|
import {
|
|
4
4
|
createAuthorizationURL,
|
|
5
5
|
refreshAccessToken,
|
|
6
|
-
resolveRequestedScopes,
|
|
7
6
|
validateAuthorizationCode,
|
|
8
7
|
} from "../oauth2";
|
|
9
8
|
|
|
@@ -104,30 +103,22 @@ export interface TwitterOption extends ProviderOptions<TwitterProfile> {
|
|
|
104
103
|
clientId: string;
|
|
105
104
|
}
|
|
106
105
|
|
|
107
|
-
const TWITTER_DEFAULT_SCOPES = [
|
|
108
|
-
"users.read",
|
|
109
|
-
"tweet.read",
|
|
110
|
-
"offline.access",
|
|
111
|
-
"users.email",
|
|
112
|
-
];
|
|
113
|
-
|
|
114
106
|
export const twitter = (options: TwitterOption) => {
|
|
115
107
|
const tokenEndpoint = "https://api.x.com/2/oauth2/token";
|
|
116
108
|
return {
|
|
117
109
|
id: "twitter",
|
|
118
110
|
name: "Twitter",
|
|
119
|
-
callbackPath: "/callback/twitter",
|
|
120
111
|
createAuthorizationURL(data) {
|
|
121
|
-
const
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
);
|
|
112
|
+
const _scopes = options.disableDefaultScope
|
|
113
|
+
? []
|
|
114
|
+
: ["users.read", "tweet.read", "offline.access", "users.email"];
|
|
115
|
+
if (options.scope) _scopes.push(...options.scope);
|
|
116
|
+
if (data.scopes) _scopes.push(...data.scopes);
|
|
126
117
|
return createAuthorizationURL({
|
|
127
118
|
id: "twitter",
|
|
128
119
|
options,
|
|
129
120
|
authorizationEndpoint: "https://x.com/i/oauth2/authorize",
|
|
130
|
-
scopes:
|
|
121
|
+
scopes: _scopes,
|
|
131
122
|
state: data.state,
|
|
132
123
|
codeVerifier: data.codeVerifier,
|
|
133
124
|
redirectURI: data.redirectURI,
|
|
@@ -205,5 +196,5 @@ export const twitter = (options: TwitterOption) => {
|
|
|
205
196
|
};
|
|
206
197
|
},
|
|
207
198
|
options,
|
|
208
|
-
} satisfies
|
|
199
|
+
} satisfies OAuthProvider<TwitterProfile>;
|
|
209
200
|
};
|
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
import { betterFetch } from "@better-fetch/fetch";
|
|
2
2
|
import { BetterAuthError } from "../error";
|
|
3
|
-
import type {
|
|
4
|
-
import {
|
|
5
|
-
createAuthorizationURL,
|
|
6
|
-
resolveRequestedScopes,
|
|
7
|
-
validateAuthorizationCode,
|
|
8
|
-
} from "../oauth2";
|
|
3
|
+
import type { OAuthProvider, ProviderOptions } from "../oauth2";
|
|
4
|
+
import { createAuthorizationURL, validateAuthorizationCode } from "../oauth2";
|
|
9
5
|
|
|
10
6
|
export interface VercelProfile {
|
|
11
7
|
sub: string;
|
|
@@ -20,13 +16,10 @@ export interface VercelOptions extends ProviderOptions<VercelProfile> {
|
|
|
20
16
|
clientId: string;
|
|
21
17
|
}
|
|
22
18
|
|
|
23
|
-
const VERCEL_DEFAULT_SCOPES: string[] = [];
|
|
24
|
-
|
|
25
19
|
export const vercel = (options: VercelOptions) => {
|
|
26
20
|
return {
|
|
27
21
|
id: "vercel",
|
|
28
22
|
name: "Vercel",
|
|
29
|
-
callbackPath: "/callback/vercel",
|
|
30
23
|
createAuthorizationURL({
|
|
31
24
|
state,
|
|
32
25
|
scopes,
|
|
@@ -38,17 +31,18 @@ export const vercel = (options: VercelOptions) => {
|
|
|
38
31
|
throw new BetterAuthError("codeVerifier is required for Vercel");
|
|
39
32
|
}
|
|
40
33
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
34
|
+
let _scopes: string[] | undefined = undefined;
|
|
35
|
+
if (options.scope !== undefined || scopes !== undefined) {
|
|
36
|
+
_scopes = [];
|
|
37
|
+
if (options.scope) _scopes.push(...options.scope);
|
|
38
|
+
if (scopes) _scopes.push(...scopes);
|
|
39
|
+
}
|
|
46
40
|
|
|
47
41
|
return createAuthorizationURL({
|
|
48
42
|
id: "vercel",
|
|
49
43
|
options,
|
|
50
44
|
authorizationEndpoint: "https://vercel.com/oauth/authorize",
|
|
51
|
-
scopes:
|
|
45
|
+
scopes: _scopes,
|
|
52
46
|
state,
|
|
53
47
|
codeVerifier,
|
|
54
48
|
redirectURI,
|
|
@@ -96,5 +90,5 @@ export const vercel = (options: VercelOptions) => {
|
|
|
96
90
|
};
|
|
97
91
|
},
|
|
98
92
|
options,
|
|
99
|
-
} satisfies
|
|
93
|
+
} satisfies OAuthProvider<VercelProfile>;
|
|
100
94
|
};
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { betterFetch } from "@better-fetch/fetch";
|
|
2
|
-
import type {
|
|
2
|
+
import type { OAuthProvider, ProviderOptions } from "../oauth2";
|
|
3
3
|
import {
|
|
4
4
|
createAuthorizationURL,
|
|
5
5
|
refreshAccessToken,
|
|
6
|
-
resolveRequestedScopes,
|
|
7
6
|
validateAuthorizationCode,
|
|
8
7
|
} from "../oauth2";
|
|
9
8
|
|
|
@@ -26,33 +25,28 @@ export interface VkOption extends ProviderOptions {
|
|
|
26
25
|
scheme?: ("light" | "dark") | undefined;
|
|
27
26
|
}
|
|
28
27
|
|
|
29
|
-
const VK_DEFAULT_SCOPES = ["email", "phone"];
|
|
30
|
-
|
|
31
28
|
export const vk = (options: VkOption) => {
|
|
32
29
|
const tokenEndpoint = "https://id.vk.com/oauth2/auth";
|
|
33
30
|
return {
|
|
34
31
|
id: "vk",
|
|
35
32
|
name: "VK",
|
|
36
|
-
|
|
37
|
-
createAuthorizationURL({
|
|
33
|
+
async createAuthorizationURL({
|
|
38
34
|
state,
|
|
39
35
|
scopes,
|
|
40
36
|
codeVerifier,
|
|
41
37
|
redirectURI,
|
|
42
38
|
additionalParams,
|
|
43
39
|
}) {
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
scopes,
|
|
48
|
-
);
|
|
40
|
+
const _scopes = options.disableDefaultScope ? [] : ["email", "phone"];
|
|
41
|
+
if (options.scope) _scopes.push(...options.scope);
|
|
42
|
+
if (scopes) _scopes.push(...scopes);
|
|
49
43
|
const authorizationEndpoint = "https://id.vk.com/authorize";
|
|
50
44
|
|
|
51
45
|
return createAuthorizationURL({
|
|
52
46
|
id: "vk",
|
|
53
47
|
options,
|
|
54
48
|
authorizationEndpoint,
|
|
55
|
-
scopes:
|
|
49
|
+
scopes: _scopes,
|
|
56
50
|
state,
|
|
57
51
|
redirectURI,
|
|
58
52
|
codeVerifier,
|
|
@@ -134,5 +128,5 @@ export const vk = (options: VkOption) => {
|
|
|
134
128
|
};
|
|
135
129
|
},
|
|
136
130
|
options,
|
|
137
|
-
} satisfies
|
|
131
|
+
} satisfies OAuthProvider<VkProfile>;
|
|
138
132
|
};
|
|
@@ -1,13 +1,6 @@
|
|
|
1
1
|
import { betterFetch } from "@better-fetch/fetch";
|
|
2
|
-
import type {
|
|
3
|
-
|
|
4
|
-
ProviderOptions,
|
|
5
|
-
UpstreamProvider,
|
|
6
|
-
} from "../oauth2";
|
|
7
|
-
import {
|
|
8
|
-
RESERVED_AUTHORIZATION_PARAMS_SET,
|
|
9
|
-
resolveRequestedScopes,
|
|
10
|
-
} from "../oauth2";
|
|
2
|
+
import type { OAuth2Tokens, OAuthProvider, ProviderOptions } from "../oauth2";
|
|
3
|
+
import { RESERVED_AUTHORIZATION_PARAMS_SET } from "../oauth2";
|
|
11
4
|
|
|
12
5
|
/**
|
|
13
6
|
* WeChat user profile information
|
|
@@ -62,24 +55,19 @@ export interface WeChatOptions extends ProviderOptions<WeChatProfile> {
|
|
|
62
55
|
lang?: "cn" | "en";
|
|
63
56
|
}
|
|
64
57
|
|
|
65
|
-
const WECHAT_DEFAULT_SCOPES = ["snsapi_login"];
|
|
66
|
-
|
|
67
58
|
export const wechat = (options: WeChatOptions) => {
|
|
68
59
|
return {
|
|
69
60
|
id: "wechat",
|
|
70
61
|
name: "WeChat",
|
|
71
|
-
callbackPath: "/callback/wechat",
|
|
72
62
|
createAuthorizationURL({ state, scopes, redirectURI, additionalParams }) {
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
scopes,
|
|
77
|
-
);
|
|
63
|
+
const _scopes = options.disableDefaultScope ? [] : ["snsapi_login"];
|
|
64
|
+
options.scope && _scopes.push(...options.scope);
|
|
65
|
+
scopes && _scopes.push(...scopes);
|
|
78
66
|
|
|
79
67
|
// WeChat uses non-standard OAuth2 parameters (appid instead of client_id)
|
|
80
68
|
// and requires a fragment (#wechat_redirect), so we construct the URL manually.
|
|
81
69
|
const url = new URL("https://open.weixin.qq.com/connect/qrconnect");
|
|
82
|
-
url.searchParams.set("scope",
|
|
70
|
+
url.searchParams.set("scope", _scopes.join(","));
|
|
83
71
|
url.searchParams.set("response_type", "code");
|
|
84
72
|
url.searchParams.set("appid", options.clientId);
|
|
85
73
|
url.searchParams.set("redirect_uri", options.redirectURI || redirectURI);
|
|
@@ -94,7 +82,7 @@ export const wechat = (options: WeChatOptions) => {
|
|
|
94
82
|
}
|
|
95
83
|
url.hash = "wechat_redirect";
|
|
96
84
|
|
|
97
|
-
return
|
|
85
|
+
return url;
|
|
98
86
|
},
|
|
99
87
|
|
|
100
88
|
// WeChat uses non-standard token exchange (appid/secret instead of
|
|
@@ -236,5 +224,5 @@ export const wechat = (options: WeChatOptions) => {
|
|
|
236
224
|
};
|
|
237
225
|
},
|
|
238
226
|
options,
|
|
239
|
-
} satisfies
|
|
227
|
+
} satisfies OAuthProvider<WeChatProfile, WeChatOptions>;
|
|
240
228
|
};
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { betterFetch } from "@better-fetch/fetch";
|
|
2
|
-
import type {
|
|
2
|
+
import type { OAuthProvider, ProviderOptions } from "../oauth2";
|
|
3
3
|
import {
|
|
4
4
|
createAuthorizationURL,
|
|
5
5
|
refreshAccessToken,
|
|
6
|
-
resolveRequestedScopes,
|
|
7
6
|
validateAuthorizationCode,
|
|
8
7
|
} from "../oauth2";
|
|
9
8
|
|
|
@@ -144,8 +143,6 @@ export interface ZoomOptions extends ProviderOptions<ZoomProfile> {
|
|
|
144
143
|
pkce?: boolean | undefined;
|
|
145
144
|
}
|
|
146
145
|
|
|
147
|
-
const ZOOM_DEFAULT_SCOPES: string[] = [];
|
|
148
|
-
|
|
149
146
|
export const zoom = (userOptions: ZoomOptions) => {
|
|
150
147
|
const options = {
|
|
151
148
|
pkce: true,
|
|
@@ -155,31 +152,21 @@ export const zoom = (userOptions: ZoomOptions) => {
|
|
|
155
152
|
return {
|
|
156
153
|
id: "zoom",
|
|
157
154
|
name: "Zoom",
|
|
158
|
-
|
|
159
|
-
createAuthorizationURL: ({
|
|
155
|
+
createAuthorizationURL: async ({
|
|
160
156
|
state,
|
|
161
|
-
scopes,
|
|
162
157
|
redirectURI,
|
|
163
158
|
codeVerifier,
|
|
164
159
|
additionalParams,
|
|
165
|
-
}) =>
|
|
166
|
-
|
|
167
|
-
options,
|
|
168
|
-
ZOOM_DEFAULT_SCOPES,
|
|
169
|
-
scopes,
|
|
170
|
-
);
|
|
171
|
-
|
|
172
|
-
return createAuthorizationURL({
|
|
160
|
+
}) =>
|
|
161
|
+
createAuthorizationURL({
|
|
173
162
|
id: "zoom",
|
|
174
163
|
options,
|
|
175
164
|
authorizationEndpoint: "https://zoom.us/oauth/authorize",
|
|
176
|
-
scopes: requestedScopes,
|
|
177
165
|
state,
|
|
178
166
|
redirectURI,
|
|
179
167
|
codeVerifier: options.pkce ? codeVerifier : undefined,
|
|
180
168
|
additionalParams,
|
|
181
|
-
})
|
|
182
|
-
},
|
|
169
|
+
}),
|
|
183
170
|
validateAuthorizationCode: async ({ code, redirectURI, codeVerifier }) => {
|
|
184
171
|
return validateAuthorizationCode({
|
|
185
172
|
code,
|
|
@@ -235,5 +222,5 @@ export const zoom = (userOptions: ZoomOptions) => {
|
|
|
235
222
|
},
|
|
236
223
|
};
|
|
237
224
|
},
|
|
238
|
-
} satisfies
|
|
225
|
+
} satisfies OAuthProvider<ZoomProfile>;
|
|
239
226
|
};
|
package/src/types/context.ts
CHANGED
|
@@ -10,7 +10,7 @@ import type {
|
|
|
10
10
|
} from "../db";
|
|
11
11
|
import type { DBAdapter, Where } from "../db/adapter";
|
|
12
12
|
import type { createLogger } from "../env";
|
|
13
|
-
import type {
|
|
13
|
+
import type { OAuthProvider } from "../oauth2";
|
|
14
14
|
import type { BetterAuthCookie, BetterAuthCookies } from "./cookie";
|
|
15
15
|
import type { Awaitable, LiteralString } from "./helper";
|
|
16
16
|
import type {
|
|
@@ -88,6 +88,12 @@ export type GenericEndpointContext<
|
|
|
88
88
|
export interface InternalAdapter<
|
|
89
89
|
_Options extends BetterAuthOptions = BetterAuthOptions,
|
|
90
90
|
> {
|
|
91
|
+
createOAuthUser(
|
|
92
|
+
user: Omit<User, "id" | "createdAt" | "updatedAt">,
|
|
93
|
+
account: Omit<Account, "userId" | "id" | "createdAt" | "updatedAt"> &
|
|
94
|
+
Partial<Account>,
|
|
95
|
+
): Promise<{ user: User; account: Account }>;
|
|
96
|
+
|
|
91
97
|
createUser<T extends Record<string, any>>(
|
|
92
98
|
user: Omit<User, "id" | "createdAt" | "updatedAt" | "emailVerified"> &
|
|
93
99
|
Partial<User> &
|
|
@@ -369,7 +375,7 @@ export type AuthContext<Options extends BetterAuthOptions = BetterAuthOptions> =
|
|
|
369
375
|
user: User & Record<string, any>;
|
|
370
376
|
} | null,
|
|
371
377
|
) => void;
|
|
372
|
-
socialProviders:
|
|
378
|
+
socialProviders: OAuthProvider[];
|
|
373
379
|
authCookies: BetterAuthCookies;
|
|
374
380
|
logger: ReturnType<typeof createLogger>;
|
|
375
381
|
rateLimit: {
|
package/dist/oauth2/scopes.d.mts
DELETED
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import { ProviderOptions } from "./oauth-provider.mjs";
|
|
2
|
-
|
|
3
|
-
//#region src/oauth2/scopes.d.ts
|
|
4
|
-
/**
|
|
5
|
-
* Parse a provider's `scope` token-response field into a string array.
|
|
6
|
-
*
|
|
7
|
-
* RFC 6749 §3.3 defines `scope` as a space-delimited string, but providers
|
|
8
|
-
* vary: some (e.g. Twitch) return an already-split array. Accept both, plus the
|
|
9
|
-
* omitted/empty case, without ever calling `.split` on a non-string. Returns
|
|
10
|
-
* `[]` when no scope is present.
|
|
11
|
-
*
|
|
12
|
-
* @see https://github.com/better-auth/better-auth/issues/9076
|
|
13
|
-
*/
|
|
14
|
-
declare function parseScopeField(scope: unknown): string[];
|
|
15
|
-
/**
|
|
16
|
-
* Normalize a scope set into a single deduped, sorted array.
|
|
17
|
-
*
|
|
18
|
-
* Scope order is insignificant per RFC 6749 §3.3, so normalize for idempotent
|
|
19
|
-
* writes and trivial comparisons: trim each token, drop empties, dedupe, and
|
|
20
|
-
* sort ascending. Returns `[]` when the union is empty.
|
|
21
|
-
*
|
|
22
|
-
* @see https://www.rfc-editor.org/rfc/rfc6749#section-3.3
|
|
23
|
-
*/
|
|
24
|
-
declare function normalizeScopes(stored: string[] | null | undefined, incoming?: string[] | undefined): string[];
|
|
25
|
-
/**
|
|
26
|
-
* Union the stored granted-scope set with the scopes observed on an
|
|
27
|
-
* authorization or token exchange.
|
|
28
|
-
*
|
|
29
|
-
* The provider's echoed `scope` is authoritative when present. RFC 6749 §3.3
|
|
30
|
-
* and §5.1 say an omitted or empty echo means the grant equals what was
|
|
31
|
-
* requested, so fall back to `requested` in that case. The result unions onto
|
|
32
|
-
* the stored grant (never narrows on a normal write) and is normalized per
|
|
33
|
-
* {@link normalizeScopes}.
|
|
34
|
-
*
|
|
35
|
-
* @see https://www.rfc-editor.org/rfc/rfc6749#section-3.3
|
|
36
|
-
* @see https://www.rfc-editor.org/rfc/rfc6749#section-5.1
|
|
37
|
-
*/
|
|
38
|
-
declare function unionGrantedScopes(stored: string[] | null | undefined, echoed: string[] | undefined, requested: string[] | undefined): string[];
|
|
39
|
-
/**
|
|
40
|
-
* Coerce a stored granted-scope value into a usable array.
|
|
41
|
-
*
|
|
42
|
-
* `account.grantedScopes` is nullable (legacy rows and non-OAuth accounts read
|
|
43
|
-
* as unset), and on dialects that store the array as a JSON string a malformed
|
|
44
|
-
* operator backfill could deserialize to a non-array. Both collapse to `[]`
|
|
45
|
-
* here so every reader works against a real `string[]` without re-deriving the
|
|
46
|
-
* guard.
|
|
47
|
-
*/
|
|
48
|
-
declare function readGrantedScopes(stored: string[] | null | undefined): string[];
|
|
49
|
-
/**
|
|
50
|
-
* Test whether a normalized granted-scope set contains a specific scope.
|
|
51
|
-
*
|
|
52
|
-
* Matching is exact and case-sensitive per RFC 6749 §3.3. The argument is the
|
|
53
|
-
* normalized `account.grantedScopes` array; a raw provider `scope` string must
|
|
54
|
-
* be run through {@link parseScopeField} first.
|
|
55
|
-
*
|
|
56
|
-
* @see https://www.rfc-editor.org/rfc/rfc6749#section-3.3
|
|
57
|
-
*/
|
|
58
|
-
declare function includesGrantedScope(granted: string[] | null | undefined, scope: string): boolean;
|
|
59
|
-
/**
|
|
60
|
-
* Compose the effective scope set to encode in a single authorization URL.
|
|
61
|
-
*
|
|
62
|
-
* Precedence: the provider's built-in defaults (unless `disableDefaultScope`),
|
|
63
|
-
* then the integrator's configured `options.scope`, then the per-request
|
|
64
|
-
* `scopes`. The result is the value persisted into OAuth state as the RFC 6749
|
|
65
|
-
* §5.1 fallback, so it is preserved verbatim (not normalized) to match what is
|
|
66
|
-
* sent to the provider.
|
|
67
|
-
*
|
|
68
|
-
* `defaultScopes` is a parameter rather than a provider-contract field so the
|
|
69
|
-
* runtime-synthesized generic OAuth provider, which has no static default set,
|
|
70
|
-
* can pass its configured scopes here.
|
|
71
|
-
*
|
|
72
|
-
* @see https://www.rfc-editor.org/rfc/rfc6749#section-5.1
|
|
73
|
-
*/
|
|
74
|
-
declare function resolveRequestedScopes(options: Pick<ProviderOptions, "scope" | "disableDefaultScope"> | undefined, defaultScopes: string[], perRequestScopes: string[] | undefined): string[];
|
|
75
|
-
//#endregion
|
|
76
|
-
export { includesGrantedScope, normalizeScopes, parseScopeField, readGrantedScopes, resolveRequestedScopes, unionGrantedScopes };
|