@better-auth/core 1.7.0-beta.4 → 1.7.0-beta.5
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 +2 -2
- 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/env/env-impl.mjs +1 -1
- package/dist/error/codes.d.mts +5 -0
- package/dist/error/codes.mjs +5 -0
- package/dist/index.d.mts +2 -2
- package/dist/instrumentation/tracer.mjs +1 -1
- package/dist/oauth2/create-authorization-url.d.mts +4 -1
- package/dist/oauth2/create-authorization-url.mjs +5 -2
- package/dist/oauth2/index.d.mts +4 -2
- package/dist/oauth2/index.mjs +3 -1
- package/dist/oauth2/oauth-provider.d.mts +128 -9
- package/dist/oauth2/refresh-access-token.mjs +1 -1
- package/dist/oauth2/scopes.d.mts +76 -0
- package/dist/oauth2/scopes.mjs +96 -0
- package/dist/oauth2/utils.mjs +2 -1
- package/dist/oauth2/verify-id-token.d.mts +26 -0
- package/dist/oauth2/verify-id-token.mjs +62 -0
- package/dist/oauth2/verify.d.mts +14 -0
- package/dist/oauth2/verify.mjs +23 -7
- package/dist/social-providers/apple.d.mts +14 -2
- package/dist/social-providers/apple.mjs +12 -36
- package/dist/social-providers/atlassian.d.mts +5 -1
- package/dist/social-providers/atlassian.mjs +4 -4
- package/dist/social-providers/cognito.d.mts +13 -2
- package/dist/social-providers/cognito.mjs +24 -32
- package/dist/social-providers/discord.d.mts +5 -1
- package/dist/social-providers/discord.mjs +7 -6
- package/dist/social-providers/dropbox.d.mts +5 -1
- package/dist/social-providers/dropbox.mjs +5 -5
- package/dist/social-providers/facebook.d.mts +21 -2
- package/dist/social-providers/facebook.mjs +46 -22
- package/dist/social-providers/figma.d.mts +5 -1
- package/dist/social-providers/figma.mjs +5 -5
- package/dist/social-providers/github.d.mts +5 -1
- package/dist/social-providers/github.mjs +4 -4
- package/dist/social-providers/gitlab.d.mts +5 -1
- package/dist/social-providers/gitlab.mjs +6 -6
- package/dist/social-providers/google.d.mts +29 -3
- package/dist/social-providers/google.mjs +24 -30
- package/dist/social-providers/huggingface.d.mts +5 -1
- package/dist/social-providers/huggingface.mjs +8 -8
- package/dist/social-providers/index.d.mts +221 -42
- package/dist/social-providers/kakao.d.mts +5 -1
- package/dist/social-providers/kakao.mjs +8 -8
- package/dist/social-providers/kick.d.mts +5 -1
- package/dist/social-providers/kick.mjs +4 -4
- package/dist/social-providers/line.d.mts +8 -2
- package/dist/social-providers/line.mjs +12 -14
- package/dist/social-providers/linear.d.mts +5 -1
- package/dist/social-providers/linear.mjs +4 -4
- package/dist/social-providers/linkedin.d.mts +5 -1
- package/dist/social-providers/linkedin.mjs +10 -10
- package/dist/social-providers/microsoft-entra-id.d.mts +31 -6
- package/dist/social-providers/microsoft-entra-id.mjs +26 -37
- package/dist/social-providers/naver.d.mts +5 -1
- package/dist/social-providers/naver.mjs +4 -4
- package/dist/social-providers/notion.d.mts +5 -1
- package/dist/social-providers/notion.mjs +4 -4
- package/dist/social-providers/paybin.d.mts +5 -1
- package/dist/social-providers/paybin.mjs +10 -10
- package/dist/social-providers/paypal.d.mts +5 -2
- package/dist/social-providers/paypal.mjs +8 -13
- package/dist/social-providers/polar.d.mts +5 -1
- package/dist/social-providers/polar.mjs +8 -8
- package/dist/social-providers/railway.d.mts +5 -1
- package/dist/social-providers/railway.mjs +9 -9
- package/dist/social-providers/reddit.d.mts +5 -1
- package/dist/social-providers/reddit.mjs +9 -8
- package/dist/social-providers/roblox.d.mts +5 -1
- package/dist/social-providers/roblox.mjs +5 -5
- package/dist/social-providers/salesforce.d.mts +5 -1
- package/dist/social-providers/salesforce.mjs +8 -8
- package/dist/social-providers/slack.d.mts +5 -1
- package/dist/social-providers/slack.mjs +9 -9
- package/dist/social-providers/spotify.d.mts +5 -1
- package/dist/social-providers/spotify.mjs +5 -5
- package/dist/social-providers/tiktok.d.mts +5 -1
- package/dist/social-providers/tiktok.mjs +9 -5
- package/dist/social-providers/twitch.d.mts +5 -1
- package/dist/social-providers/twitch.mjs +4 -4
- package/dist/social-providers/twitter.d.mts +6 -4
- package/dist/social-providers/twitter.mjs +9 -9
- package/dist/social-providers/vercel.d.mts +5 -1
- package/dist/social-providers/vercel.mjs +4 -7
- package/dist/social-providers/vk.d.mts +5 -1
- package/dist/social-providers/vk.mjs +5 -5
- package/dist/social-providers/wechat.d.mts +5 -1
- package/dist/social-providers/wechat.mjs +9 -5
- package/dist/social-providers/zoom.d.mts +6 -1
- package/dist/social-providers/zoom.mjs +15 -9
- package/dist/types/context.d.mts +10 -8
- package/dist/types/index.d.mts +1 -1
- package/dist/types/init-options.d.mts +92 -1
- package/package.json +5 -5
- package/src/db/adapter/factory.ts +10 -2
- package/src/db/get-tables.ts +8 -3
- package/src/db/schema/account.ts +14 -2
- package/src/env/env-impl.ts +1 -2
- package/src/error/codes.ts +5 -0
- package/src/oauth2/create-authorization-url.ts +2 -2
- package/src/oauth2/index.ts +17 -1
- package/src/oauth2/oauth-provider.ts +140 -10
- package/src/oauth2/refresh-access-token.ts +2 -2
- package/src/oauth2/scopes.ts +118 -0
- package/src/oauth2/utils.ts +2 -5
- package/src/oauth2/verify-id-token.ts +111 -0
- package/src/oauth2/verify.ts +62 -11
- package/src/social-providers/apple.ts +24 -61
- package/src/social-providers/atlassian.ts +12 -8
- package/src/social-providers/cognito.ts +25 -47
- package/src/social-providers/discord.ts +19 -8
- package/src/social-providers/dropbox.ts +13 -7
- package/src/social-providers/facebook.ts +97 -51
- package/src/social-providers/figma.ts +13 -9
- package/src/social-providers/github.ts +12 -8
- package/src/social-providers/gitlab.ts +14 -8
- package/src/social-providers/google.ts +66 -47
- package/src/social-providers/huggingface.ts +12 -8
- package/src/social-providers/kakao.ts +16 -8
- package/src/social-providers/kick.ts +12 -7
- package/src/social-providers/line.ts +37 -37
- package/src/social-providers/linear.ts +12 -6
- package/src/social-providers/linkedin.ts +14 -10
- package/src/social-providers/microsoft-entra-id.ts +65 -64
- package/src/social-providers/naver.ts +12 -6
- package/src/social-providers/notion.ts +12 -6
- package/src/social-providers/paybin.ts +14 -11
- package/src/social-providers/paypal.ts +6 -25
- package/src/social-providers/polar.ts +12 -8
- package/src/social-providers/railway.ts +13 -9
- package/src/social-providers/reddit.ts +21 -10
- package/src/social-providers/roblox.ts +18 -7
- package/src/social-providers/salesforce.ts +12 -8
- package/src/social-providers/slack.ts +18 -9
- package/src/social-providers/spotify.ts +13 -7
- package/src/social-providers/tiktok.ts +13 -7
- package/src/social-providers/twitch.ts +12 -8
- package/src/social-providers/twitter.ts +17 -8
- package/src/social-providers/vercel.ts +16 -10
- package/src/social-providers/vk.ts +13 -7
- package/src/social-providers/wechat.ts +20 -8
- package/src/social-providers/zoom.ts +19 -6
- package/src/types/context.ts +8 -8
- package/src/types/index.ts +7 -0
- package/src/types/init-options.ts +119 -0
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { betterFetch } from "@better-fetch/fetch";
|
|
2
|
-
import type {
|
|
2
|
+
import type { ProviderOptions, UpstreamProvider } from "../oauth2";
|
|
3
3
|
import {
|
|
4
4
|
createAuthorizationURL,
|
|
5
5
|
refreshAccessToken,
|
|
6
|
+
resolveRequestedScopes,
|
|
6
7
|
validateAuthorizationCode,
|
|
7
8
|
} from "../oauth2";
|
|
8
9
|
|
|
@@ -26,11 +27,14 @@ export interface LinearOptions extends ProviderOptions<LinearUser> {
|
|
|
26
27
|
clientId: string;
|
|
27
28
|
}
|
|
28
29
|
|
|
30
|
+
const LINEAR_DEFAULT_SCOPES = ["read"];
|
|
31
|
+
|
|
29
32
|
export const linear = (options: LinearOptions) => {
|
|
30
33
|
const tokenEndpoint = "https://api.linear.app/oauth/token";
|
|
31
34
|
return {
|
|
32
35
|
id: "linear",
|
|
33
36
|
name: "Linear",
|
|
37
|
+
callbackPath: "/callback/linear",
|
|
34
38
|
createAuthorizationURL({
|
|
35
39
|
state,
|
|
36
40
|
scopes,
|
|
@@ -38,14 +42,16 @@ export const linear = (options: LinearOptions) => {
|
|
|
38
42
|
redirectURI,
|
|
39
43
|
additionalParams,
|
|
40
44
|
}) {
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
45
|
+
const requestedScopes = resolveRequestedScopes(
|
|
46
|
+
options,
|
|
47
|
+
LINEAR_DEFAULT_SCOPES,
|
|
48
|
+
scopes,
|
|
49
|
+
);
|
|
44
50
|
return createAuthorizationURL({
|
|
45
51
|
id: "linear",
|
|
46
52
|
options,
|
|
47
53
|
authorizationEndpoint: "https://linear.app/oauth/authorize",
|
|
48
|
-
scopes:
|
|
54
|
+
scopes: requestedScopes,
|
|
49
55
|
state,
|
|
50
56
|
redirectURI,
|
|
51
57
|
loginHint,
|
|
@@ -124,5 +130,5 @@ export const linear = (options: LinearOptions) => {
|
|
|
124
130
|
};
|
|
125
131
|
},
|
|
126
132
|
options,
|
|
127
|
-
} satisfies
|
|
133
|
+
} satisfies UpstreamProvider<LinearUser>;
|
|
128
134
|
};
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { betterFetch } from "@better-fetch/fetch";
|
|
2
|
-
import type {
|
|
2
|
+
import type { ProviderOptions, UpstreamProvider } from "../oauth2";
|
|
3
3
|
import {
|
|
4
4
|
createAuthorizationURL,
|
|
5
5
|
refreshAccessToken,
|
|
6
|
+
resolveRequestedScopes,
|
|
6
7
|
validateAuthorizationCode,
|
|
7
8
|
} from "../oauth2";
|
|
8
9
|
|
|
@@ -24,6 +25,8 @@ export interface LinkedInOptions extends ProviderOptions<LinkedInProfile> {
|
|
|
24
25
|
clientId: string;
|
|
25
26
|
}
|
|
26
27
|
|
|
28
|
+
const LINKEDIN_DEFAULT_SCOPES = ["profile", "email", "openid"];
|
|
29
|
+
|
|
27
30
|
export const linkedin = (options: LinkedInOptions) => {
|
|
28
31
|
const authorizationEndpoint =
|
|
29
32
|
"https://www.linkedin.com/oauth/v2/authorization";
|
|
@@ -32,23 +35,24 @@ export const linkedin = (options: LinkedInOptions) => {
|
|
|
32
35
|
return {
|
|
33
36
|
id: "linkedin",
|
|
34
37
|
name: "Linkedin",
|
|
35
|
-
|
|
38
|
+
callbackPath: "/callback/linkedin",
|
|
39
|
+
createAuthorizationURL: ({
|
|
36
40
|
state,
|
|
37
41
|
scopes,
|
|
38
42
|
redirectURI,
|
|
39
43
|
loginHint,
|
|
40
44
|
additionalParams,
|
|
41
45
|
}) => {
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
return
|
|
46
|
+
const requestedScopes = resolveRequestedScopes(
|
|
47
|
+
options,
|
|
48
|
+
LINKEDIN_DEFAULT_SCOPES,
|
|
49
|
+
scopes,
|
|
50
|
+
);
|
|
51
|
+
return createAuthorizationURL({
|
|
48
52
|
id: "linkedin",
|
|
49
53
|
options,
|
|
50
54
|
authorizationEndpoint,
|
|
51
|
-
scopes:
|
|
55
|
+
scopes: requestedScopes,
|
|
52
56
|
state,
|
|
53
57
|
loginHint,
|
|
54
58
|
redirectURI,
|
|
@@ -108,5 +112,5 @@ export const linkedin = (options: LinkedInOptions) => {
|
|
|
108
112
|
};
|
|
109
113
|
},
|
|
110
114
|
options,
|
|
111
|
-
} satisfies
|
|
115
|
+
} satisfies UpstreamProvider<LinkedInProfile>;
|
|
112
116
|
};
|
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
import { base64 } from "@better-auth/utils/base64";
|
|
2
2
|
import { betterFetch } from "@better-fetch/fetch";
|
|
3
|
-
import { decodeJwt,
|
|
3
|
+
import { decodeJwt, importJWK } from "jose";
|
|
4
4
|
import { logger } from "../env";
|
|
5
5
|
import { APIError, BetterAuthError } from "../error";
|
|
6
|
-
import type {
|
|
6
|
+
import type {
|
|
7
|
+
ClientAssertionGetter,
|
|
8
|
+
ProviderOptions,
|
|
9
|
+
TokenEndpointAuth,
|
|
10
|
+
UpstreamProvider,
|
|
11
|
+
} from "../oauth2";
|
|
7
12
|
import {
|
|
8
13
|
createAuthorizationURL,
|
|
9
14
|
getPrimaryClientId,
|
|
10
15
|
refreshAccessToken,
|
|
16
|
+
resolveRequestedScopes,
|
|
11
17
|
validateAuthorizationCode,
|
|
12
18
|
} from "../oauth2";
|
|
13
19
|
|
|
@@ -122,33 +128,60 @@ export interface MicrosoftOptions
|
|
|
122
128
|
* The tenant ID of the Microsoft account
|
|
123
129
|
* @default "common"
|
|
124
130
|
*/
|
|
125
|
-
tenantId?: string
|
|
131
|
+
tenantId?: string;
|
|
126
132
|
/**
|
|
127
133
|
* The authentication authority URL. Use the default "https://login.microsoftonline.com" for standard Entra ID or "https://<tenant-id>.ciamlogin.com" for CIAM scenarios.
|
|
128
134
|
* @default "https://login.microsoftonline.com"
|
|
129
135
|
*/
|
|
130
|
-
authority?: string
|
|
136
|
+
authority?: string;
|
|
137
|
+
/**
|
|
138
|
+
* Function that returns a JWT client assertion for token endpoint authentication.
|
|
139
|
+
*
|
|
140
|
+
* Use this instead of `clientSecret` when your Microsoft Entra ID app is
|
|
141
|
+
* configured for client authentication with assertions (private_key_jwt or
|
|
142
|
+
* workload identity federation).
|
|
143
|
+
*/
|
|
144
|
+
clientAssertion?: ClientAssertionGetter;
|
|
131
145
|
/**
|
|
132
146
|
* The size of the profile photo
|
|
133
147
|
* @default 48
|
|
134
148
|
*/
|
|
135
|
-
profilePhotoSize?:
|
|
136
|
-
| (48 | 64 | 96 | 120 | 240 | 360 | 432 | 504 | 648)
|
|
137
|
-
| undefined;
|
|
149
|
+
profilePhotoSize?: 48 | 64 | 96 | 120 | 240 | 360 | 432 | 504 | 648;
|
|
138
150
|
/**
|
|
139
151
|
* Disable profile photo
|
|
140
152
|
*/
|
|
141
|
-
disableProfilePhoto?: boolean
|
|
153
|
+
disableProfilePhoto?: boolean;
|
|
142
154
|
}
|
|
143
155
|
|
|
156
|
+
const MICROSOFT_ENTRA_ID_DEFAULT_SCOPES = [
|
|
157
|
+
"openid",
|
|
158
|
+
"profile",
|
|
159
|
+
"email",
|
|
160
|
+
"User.Read",
|
|
161
|
+
"offline_access",
|
|
162
|
+
];
|
|
163
|
+
|
|
144
164
|
export const microsoft = (options: MicrosoftOptions) => {
|
|
145
165
|
const tenant = options.tenantId || "common";
|
|
146
166
|
const authority = options.authority || "https://login.microsoftonline.com";
|
|
147
167
|
const authorizationEndpoint = `${authority}/${tenant}/oauth2/v2.0/authorize`;
|
|
148
168
|
const tokenEndpoint = `${authority}/${tenant}/oauth2/v2.0/token`;
|
|
169
|
+
if (options.clientSecret && options.clientAssertion) {
|
|
170
|
+
throw new BetterAuthError(
|
|
171
|
+
"Microsoft Entra ID clientAssertion cannot be combined with clientSecret",
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
const tokenEndpointAuth: TokenEndpointAuth | undefined =
|
|
175
|
+
options.clientAssertion
|
|
176
|
+
? {
|
|
177
|
+
method: "private_key_jwt",
|
|
178
|
+
getClientAssertion: options.clientAssertion,
|
|
179
|
+
}
|
|
180
|
+
: undefined;
|
|
149
181
|
return {
|
|
150
182
|
id: "microsoft",
|
|
151
183
|
name: "Microsoft EntraID",
|
|
184
|
+
callbackPath: "/callback/microsoft",
|
|
152
185
|
createAuthorizationURL(data) {
|
|
153
186
|
// Microsoft Entra supports public clients (SPA / native apps with
|
|
154
187
|
// PKCE only), so clientSecret is intentionally not required here.
|
|
@@ -159,18 +192,18 @@ export const microsoft = (options: MicrosoftOptions) => {
|
|
|
159
192
|
);
|
|
160
193
|
throw new BetterAuthError("CLIENT_ID_AND_SECRET_REQUIRED");
|
|
161
194
|
}
|
|
162
|
-
const
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
195
|
+
const requestedScopes = resolveRequestedScopes(
|
|
196
|
+
options,
|
|
197
|
+
MICROSOFT_ENTRA_ID_DEFAULT_SCOPES,
|
|
198
|
+
data.scopes,
|
|
199
|
+
);
|
|
167
200
|
return createAuthorizationURL({
|
|
168
201
|
id: "microsoft",
|
|
169
202
|
options,
|
|
170
203
|
authorizationEndpoint,
|
|
171
204
|
state: data.state,
|
|
172
205
|
codeVerifier: data.codeVerifier,
|
|
173
|
-
scopes,
|
|
206
|
+
scopes: requestedScopes,
|
|
174
207
|
redirectURI: data.redirectURI,
|
|
175
208
|
prompt: options.prompt,
|
|
176
209
|
loginHint: data.loginHint,
|
|
@@ -184,57 +217,24 @@ export const microsoft = (options: MicrosoftOptions) => {
|
|
|
184
217
|
redirectURI,
|
|
185
218
|
options,
|
|
186
219
|
tokenEndpoint,
|
|
220
|
+
tokenEndpointAuth,
|
|
187
221
|
});
|
|
188
222
|
},
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
audience: string | string[];
|
|
205
|
-
maxTokenAge: string;
|
|
206
|
-
issuer?: string;
|
|
207
|
-
} = {
|
|
208
|
-
algorithms: [jwtAlg],
|
|
209
|
-
audience: options.clientId,
|
|
210
|
-
maxTokenAge: "1h",
|
|
211
|
-
};
|
|
212
|
-
/**
|
|
213
|
-
* Issuer varies per user's tenant for multi-tenant endpoints, so only validate for specific tenants.
|
|
214
|
-
* @see https://learn.microsoft.com/en-us/entra/identity-platform/v2-protocols#endpoints
|
|
215
|
-
*/
|
|
216
|
-
if (
|
|
217
|
-
tenant !== "common" &&
|
|
218
|
-
tenant !== "organizations" &&
|
|
219
|
-
tenant !== "consumers"
|
|
220
|
-
) {
|
|
221
|
-
verifyOptions.issuer = `${authority}/${tenant}/v2.0`;
|
|
222
|
-
}
|
|
223
|
-
const { payload: jwtClaims } = await jwtVerify(
|
|
224
|
-
token,
|
|
225
|
-
publicKey,
|
|
226
|
-
verifyOptions,
|
|
227
|
-
);
|
|
228
|
-
|
|
229
|
-
if (nonce && jwtClaims.nonce !== nonce) {
|
|
230
|
-
return false;
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
return true;
|
|
234
|
-
} catch (error) {
|
|
235
|
-
logger.error("Failed to verify ID token:", error);
|
|
236
|
-
return false;
|
|
237
|
-
}
|
|
223
|
+
idToken: {
|
|
224
|
+
jwks: (header) => getMicrosoftPublicKey(header.kid!, tenant, authority),
|
|
225
|
+
audience: options.clientId,
|
|
226
|
+
maxTokenAge: "1h",
|
|
227
|
+
/**
|
|
228
|
+
* Issuer varies per tenant for multi-tenant endpoints, so only validate it for
|
|
229
|
+
* specific tenants.
|
|
230
|
+
* @see https://learn.microsoft.com/en-us/entra/identity-platform/v2-protocols#endpoints
|
|
231
|
+
*/
|
|
232
|
+
issuer:
|
|
233
|
+
tenant !== "common" &&
|
|
234
|
+
tenant !== "organizations" &&
|
|
235
|
+
tenant !== "consumers"
|
|
236
|
+
? `${authority}/${tenant}/v2.0`
|
|
237
|
+
: undefined,
|
|
238
238
|
},
|
|
239
239
|
async getUserInfo(token) {
|
|
240
240
|
if (options.getUserInfo) {
|
|
@@ -314,10 +314,11 @@ export const microsoft = (options: MicrosoftOptions) => {
|
|
|
314
314
|
scope: scopes.join(" "), // Include the scopes in request to microsoft
|
|
315
315
|
},
|
|
316
316
|
tokenEndpoint,
|
|
317
|
+
tokenEndpointAuth,
|
|
317
318
|
});
|
|
318
319
|
},
|
|
319
320
|
options,
|
|
320
|
-
} satisfies
|
|
321
|
+
} satisfies UpstreamProvider;
|
|
321
322
|
};
|
|
322
323
|
|
|
323
324
|
export const getMicrosoftPublicKey = async (
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { betterFetch } from "@better-fetch/fetch";
|
|
2
|
-
import type {
|
|
2
|
+
import type { ProviderOptions, UpstreamProvider } from "../oauth2";
|
|
3
3
|
import {
|
|
4
4
|
createAuthorizationURL,
|
|
5
5
|
refreshAccessToken,
|
|
6
|
+
resolveRequestedScopes,
|
|
6
7
|
validateAuthorizationCode,
|
|
7
8
|
} from "../oauth2";
|
|
8
9
|
|
|
@@ -39,20 +40,25 @@ export interface NaverOptions extends ProviderOptions<NaverProfile> {
|
|
|
39
40
|
clientId: string;
|
|
40
41
|
}
|
|
41
42
|
|
|
43
|
+
const NAVER_DEFAULT_SCOPES = ["profile", "email"];
|
|
44
|
+
|
|
42
45
|
export const naver = (options: NaverOptions) => {
|
|
43
46
|
const tokenEndpoint = "https://nid.naver.com/oauth2.0/token";
|
|
44
47
|
return {
|
|
45
48
|
id: "naver",
|
|
46
49
|
name: "Naver",
|
|
50
|
+
callbackPath: "/callback/naver",
|
|
47
51
|
createAuthorizationURL({ state, scopes, redirectURI, additionalParams }) {
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
|
|
52
|
+
const requestedScopes = resolveRequestedScopes(
|
|
53
|
+
options,
|
|
54
|
+
NAVER_DEFAULT_SCOPES,
|
|
55
|
+
scopes,
|
|
56
|
+
);
|
|
51
57
|
return createAuthorizationURL({
|
|
52
58
|
id: "naver",
|
|
53
59
|
options,
|
|
54
60
|
authorizationEndpoint: "https://nid.naver.com/oauth2.0/authorize",
|
|
55
|
-
scopes:
|
|
61
|
+
scopes: requestedScopes,
|
|
56
62
|
state,
|
|
57
63
|
redirectURI,
|
|
58
64
|
additionalParams,
|
|
@@ -110,5 +116,5 @@ export const naver = (options: NaverOptions) => {
|
|
|
110
116
|
};
|
|
111
117
|
},
|
|
112
118
|
options,
|
|
113
|
-
} satisfies
|
|
119
|
+
} satisfies UpstreamProvider<NaverProfile>;
|
|
114
120
|
};
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { betterFetch } from "@better-fetch/fetch";
|
|
2
|
-
import type {
|
|
2
|
+
import type { ProviderOptions, UpstreamProvider } from "../oauth2";
|
|
3
3
|
import {
|
|
4
4
|
createAuthorizationURL,
|
|
5
5
|
refreshAccessToken,
|
|
6
|
+
resolveRequestedScopes,
|
|
6
7
|
validateAuthorizationCode,
|
|
7
8
|
} from "../oauth2";
|
|
8
9
|
|
|
@@ -23,11 +24,14 @@ export interface NotionOptions extends ProviderOptions<NotionProfile> {
|
|
|
23
24
|
clientId: string;
|
|
24
25
|
}
|
|
25
26
|
|
|
27
|
+
const NOTION_DEFAULT_SCOPES: string[] = [];
|
|
28
|
+
|
|
26
29
|
export const notion = (options: NotionOptions) => {
|
|
27
30
|
const tokenEndpoint = "https://api.notion.com/v1/oauth/token";
|
|
28
31
|
return {
|
|
29
32
|
id: "notion",
|
|
30
33
|
name: "Notion",
|
|
34
|
+
callbackPath: "/callback/notion",
|
|
31
35
|
createAuthorizationURL({
|
|
32
36
|
state,
|
|
33
37
|
scopes,
|
|
@@ -35,14 +39,16 @@ export const notion = (options: NotionOptions) => {
|
|
|
35
39
|
redirectURI,
|
|
36
40
|
additionalParams,
|
|
37
41
|
}) {
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
42
|
+
const requestedScopes = resolveRequestedScopes(
|
|
43
|
+
options,
|
|
44
|
+
NOTION_DEFAULT_SCOPES,
|
|
45
|
+
scopes,
|
|
46
|
+
);
|
|
41
47
|
return createAuthorizationURL({
|
|
42
48
|
id: "notion",
|
|
43
49
|
options,
|
|
44
50
|
authorizationEndpoint: "https://api.notion.com/v1/oauth/authorize",
|
|
45
|
-
scopes:
|
|
51
|
+
scopes: requestedScopes,
|
|
46
52
|
state,
|
|
47
53
|
redirectURI,
|
|
48
54
|
loginHint,
|
|
@@ -111,5 +117,5 @@ export const notion = (options: NotionOptions) => {
|
|
|
111
117
|
};
|
|
112
118
|
},
|
|
113
119
|
options,
|
|
114
|
-
} satisfies
|
|
120
|
+
} satisfies UpstreamProvider<NotionProfile>;
|
|
115
121
|
};
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { decodeJwt } from "jose";
|
|
2
2
|
import { logger } from "../env";
|
|
3
3
|
import { BetterAuthError } from "../error";
|
|
4
|
-
import type {
|
|
4
|
+
import type { ProviderOptions, UpstreamProvider } from "../oauth2";
|
|
5
5
|
import {
|
|
6
6
|
createAuthorizationURL,
|
|
7
7
|
refreshAccessToken,
|
|
8
|
+
resolveRequestedScopes,
|
|
8
9
|
validateAuthorizationCode,
|
|
9
10
|
} from "../oauth2";
|
|
10
11
|
|
|
@@ -28,6 +29,8 @@ export interface PaybinOptions extends ProviderOptions<PaybinProfile> {
|
|
|
28
29
|
issuer?: string | undefined;
|
|
29
30
|
}
|
|
30
31
|
|
|
32
|
+
const PAYBIN_DEFAULT_SCOPES = ["openid", "email", "profile"];
|
|
33
|
+
|
|
31
34
|
export const paybin = (options: PaybinOptions) => {
|
|
32
35
|
const issuer = options.issuer || "https://idp.paybin.io";
|
|
33
36
|
const authorizationEndpoint = `${issuer}/oauth2/authorize`;
|
|
@@ -36,7 +39,8 @@ export const paybin = (options: PaybinOptions) => {
|
|
|
36
39
|
return {
|
|
37
40
|
id: "paybin",
|
|
38
41
|
name: "Paybin",
|
|
39
|
-
|
|
42
|
+
callbackPath: "/callback/paybin",
|
|
43
|
+
createAuthorizationURL({
|
|
40
44
|
state,
|
|
41
45
|
scopes,
|
|
42
46
|
codeVerifier,
|
|
@@ -53,16 +57,16 @@ export const paybin = (options: PaybinOptions) => {
|
|
|
53
57
|
if (!codeVerifier) {
|
|
54
58
|
throw new BetterAuthError("codeVerifier is required for Paybin");
|
|
55
59
|
}
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
60
|
+
const requestedScopes = resolveRequestedScopes(
|
|
61
|
+
options,
|
|
62
|
+
PAYBIN_DEFAULT_SCOPES,
|
|
63
|
+
scopes,
|
|
64
|
+
);
|
|
65
|
+
return createAuthorizationURL({
|
|
62
66
|
id: "paybin",
|
|
63
67
|
options,
|
|
64
68
|
authorizationEndpoint,
|
|
65
|
-
scopes:
|
|
69
|
+
scopes: requestedScopes,
|
|
66
70
|
state,
|
|
67
71
|
codeVerifier,
|
|
68
72
|
redirectURI,
|
|
@@ -70,7 +74,6 @@ export const paybin = (options: PaybinOptions) => {
|
|
|
70
74
|
loginHint,
|
|
71
75
|
additionalParams,
|
|
72
76
|
});
|
|
73
|
-
return url;
|
|
74
77
|
},
|
|
75
78
|
validateAuthorizationCode: async ({ code, codeVerifier, redirectURI }) => {
|
|
76
79
|
return validateAuthorizationCode({
|
|
@@ -116,5 +119,5 @@ export const paybin = (options: PaybinOptions) => {
|
|
|
116
119
|
};
|
|
117
120
|
},
|
|
118
121
|
options,
|
|
119
|
-
} satisfies
|
|
122
|
+
} satisfies UpstreamProvider<PaybinProfile>;
|
|
120
123
|
};
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { base64 } from "@better-auth/utils/base64";
|
|
2
2
|
import { betterFetch } from "@better-fetch/fetch";
|
|
3
|
-
import { decodeJwt } from "jose";
|
|
4
3
|
import { logger } from "../env";
|
|
5
4
|
import { BetterAuthError } from "../error";
|
|
6
|
-
import type {
|
|
5
|
+
import type { ProviderOptions, UpstreamProvider } from "../oauth2";
|
|
7
6
|
import { createAuthorizationURL } from "../oauth2";
|
|
8
7
|
|
|
9
8
|
export interface PayPalProfile {
|
|
@@ -78,7 +77,8 @@ export const paypal = (options: PayPalOptions) => {
|
|
|
78
77
|
return {
|
|
79
78
|
id: "paypal",
|
|
80
79
|
name: "PayPal",
|
|
81
|
-
|
|
80
|
+
callbackPath: "/callback/paypal",
|
|
81
|
+
createAuthorizationURL({
|
|
82
82
|
state,
|
|
83
83
|
codeVerifier,
|
|
84
84
|
redirectURI,
|
|
@@ -97,20 +97,17 @@ export const paypal = (options: PayPalOptions) => {
|
|
|
97
97
|
* We don't pass any scopes to avoid "invalid scope" errors
|
|
98
98
|
**/
|
|
99
99
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
const url = await createAuthorizationURL({
|
|
100
|
+
return createAuthorizationURL({
|
|
103
101
|
id: "paypal",
|
|
104
102
|
options,
|
|
105
103
|
authorizationEndpoint,
|
|
106
|
-
scopes:
|
|
104
|
+
scopes: [],
|
|
107
105
|
state,
|
|
108
106
|
codeVerifier,
|
|
109
107
|
redirectURI,
|
|
110
108
|
prompt: options.prompt,
|
|
111
109
|
additionalParams,
|
|
112
110
|
});
|
|
113
|
-
return url;
|
|
114
111
|
},
|
|
115
112
|
|
|
116
113
|
validateAuthorizationCode: async ({ code, redirectURI }) => {
|
|
@@ -200,22 +197,6 @@ export const paypal = (options: PayPalOptions) => {
|
|
|
200
197
|
}
|
|
201
198
|
},
|
|
202
199
|
|
|
203
|
-
async verifyIdToken(token, nonce) {
|
|
204
|
-
if (options.disableIdTokenSignIn) {
|
|
205
|
-
return false;
|
|
206
|
-
}
|
|
207
|
-
if (options.verifyIdToken) {
|
|
208
|
-
return options.verifyIdToken(token, nonce);
|
|
209
|
-
}
|
|
210
|
-
try {
|
|
211
|
-
const payload = decodeJwt(token);
|
|
212
|
-
return !!payload.sub;
|
|
213
|
-
} catch (error) {
|
|
214
|
-
logger.error("Failed to verify PayPal ID token:", error);
|
|
215
|
-
return false;
|
|
216
|
-
}
|
|
217
|
-
},
|
|
218
|
-
|
|
219
200
|
async getUserInfo(token) {
|
|
220
201
|
if (options.getUserInfo) {
|
|
221
202
|
return options.getUserInfo(token);
|
|
@@ -265,5 +246,5 @@ export const paypal = (options: PayPalOptions) => {
|
|
|
265
246
|
},
|
|
266
247
|
|
|
267
248
|
options,
|
|
268
|
-
} satisfies
|
|
249
|
+
} satisfies UpstreamProvider<PayPalProfile>;
|
|
269
250
|
};
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { betterFetch } from "@better-fetch/fetch";
|
|
2
|
-
import type {
|
|
2
|
+
import type { ProviderOptions, UpstreamProvider } from "../oauth2";
|
|
3
3
|
import {
|
|
4
4
|
createAuthorizationURL,
|
|
5
5
|
refreshAccessToken,
|
|
6
|
+
resolveRequestedScopes,
|
|
6
7
|
validateAuthorizationCode,
|
|
7
8
|
} from "../oauth2";
|
|
8
9
|
|
|
@@ -32,11 +33,14 @@ export interface PolarProfile {
|
|
|
32
33
|
|
|
33
34
|
export interface PolarOptions extends ProviderOptions<PolarProfile> {}
|
|
34
35
|
|
|
36
|
+
const POLAR_DEFAULT_SCOPES = ["openid", "profile", "email"];
|
|
37
|
+
|
|
35
38
|
export const polar = (options: PolarOptions) => {
|
|
36
39
|
const tokenEndpoint = "https://api.polar.sh/v1/oauth2/token";
|
|
37
40
|
return {
|
|
38
41
|
id: "polar",
|
|
39
42
|
name: "Polar",
|
|
43
|
+
callbackPath: "/callback/polar",
|
|
40
44
|
createAuthorizationURL({
|
|
41
45
|
state,
|
|
42
46
|
scopes,
|
|
@@ -44,16 +48,16 @@ export const polar = (options: PolarOptions) => {
|
|
|
44
48
|
redirectURI,
|
|
45
49
|
additionalParams,
|
|
46
50
|
}) {
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
51
|
+
const requestedScopes = resolveRequestedScopes(
|
|
52
|
+
options,
|
|
53
|
+
POLAR_DEFAULT_SCOPES,
|
|
54
|
+
scopes,
|
|
55
|
+
);
|
|
52
56
|
return createAuthorizationURL({
|
|
53
57
|
id: "polar",
|
|
54
58
|
options,
|
|
55
59
|
authorizationEndpoint: "https://polar.sh/oauth2/authorize",
|
|
56
|
-
scopes:
|
|
60
|
+
scopes: requestedScopes,
|
|
57
61
|
state,
|
|
58
62
|
codeVerifier,
|
|
59
63
|
redirectURI,
|
|
@@ -114,5 +118,5 @@ export const polar = (options: PolarOptions) => {
|
|
|
114
118
|
};
|
|
115
119
|
},
|
|
116
120
|
options,
|
|
117
|
-
} satisfies
|
|
121
|
+
} satisfies UpstreamProvider<PolarProfile>;
|
|
118
122
|
};
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { betterFetch } from "@better-fetch/fetch";
|
|
2
|
-
import type {
|
|
2
|
+
import type { ProviderOptions, UpstreamProvider } from "../oauth2";
|
|
3
3
|
import {
|
|
4
4
|
createAuthorizationURL,
|
|
5
5
|
refreshAccessToken,
|
|
6
|
+
resolveRequestedScopes,
|
|
6
7
|
validateAuthorizationCode,
|
|
7
8
|
} from "../oauth2";
|
|
8
9
|
|
|
@@ -25,27 +26,30 @@ export interface RailwayOptions extends ProviderOptions<RailwayProfile> {
|
|
|
25
26
|
clientId: string;
|
|
26
27
|
}
|
|
27
28
|
|
|
29
|
+
const RAILWAY_DEFAULT_SCOPES = ["openid", "email", "profile"];
|
|
30
|
+
|
|
28
31
|
export const railway = (options: RailwayOptions) => {
|
|
29
32
|
return {
|
|
30
33
|
id: "railway",
|
|
31
34
|
name: "Railway",
|
|
32
|
-
|
|
35
|
+
callbackPath: "/callback/railway",
|
|
36
|
+
async createAuthorizationURL({
|
|
33
37
|
state,
|
|
34
38
|
scopes,
|
|
35
39
|
codeVerifier,
|
|
36
40
|
redirectURI,
|
|
37
41
|
additionalParams,
|
|
38
42
|
}) {
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
43
|
+
const requestedScopes = resolveRequestedScopes(
|
|
44
|
+
options,
|
|
45
|
+
RAILWAY_DEFAULT_SCOPES,
|
|
46
|
+
scopes,
|
|
47
|
+
);
|
|
44
48
|
return createAuthorizationURL({
|
|
45
49
|
id: "railway",
|
|
46
50
|
options,
|
|
47
51
|
authorizationEndpoint,
|
|
48
|
-
scopes:
|
|
52
|
+
scopes: requestedScopes,
|
|
49
53
|
state,
|
|
50
54
|
codeVerifier,
|
|
51
55
|
redirectURI,
|
|
@@ -103,5 +107,5 @@ export const railway = (options: RailwayOptions) => {
|
|
|
103
107
|
};
|
|
104
108
|
},
|
|
105
109
|
options,
|
|
106
|
-
} satisfies
|
|
110
|
+
} satisfies UpstreamProvider<RailwayProfile>;
|
|
107
111
|
};
|