@better-auth/core 1.5.0-beta.9 → 1.5.0
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/README.md +17 -0
- package/dist/api/index.d.mts +144 -41
- package/dist/api/index.mjs +2 -1
- package/dist/api/index.mjs.map +1 -0
- package/dist/async_hooks/index.d.mts +2 -1
- package/dist/async_hooks/index.mjs +2 -1
- package/dist/async_hooks/index.mjs.map +1 -0
- package/dist/async_hooks/pure.index.d.mts +2 -1
- package/dist/async_hooks/pure.index.mjs +2 -1
- package/dist/async_hooks/pure.index.mjs.map +1 -0
- package/dist/context/endpoint-context.d.mts +2 -1
- package/dist/context/endpoint-context.mjs +4 -3
- package/dist/context/endpoint-context.mjs.map +1 -0
- package/dist/context/global.d.mts +2 -2
- package/dist/context/global.mjs +3 -2
- package/dist/context/global.mjs.map +1 -0
- package/dist/context/request-state.d.mts +2 -1
- package/dist/context/request-state.mjs +4 -3
- package/dist/context/request-state.mjs.map +1 -0
- package/dist/context/transaction.d.mts +2 -1
- package/dist/context/transaction.mjs +4 -3
- package/dist/context/transaction.mjs.map +1 -0
- package/dist/db/adapter/factory.d.mts +6 -13
- package/dist/db/adapter/factory.mjs +44 -57
- package/dist/db/adapter/factory.mjs.map +1 -0
- package/dist/db/adapter/get-default-field-name.d.mts +2 -1
- package/dist/db/adapter/get-default-field-name.mjs +3 -2
- package/dist/db/adapter/get-default-field-name.mjs.map +1 -0
- package/dist/db/adapter/get-default-model-name.d.mts +2 -1
- package/dist/db/adapter/get-default-model-name.mjs +5 -4
- package/dist/db/adapter/get-default-model-name.mjs.map +1 -0
- package/dist/db/adapter/get-field-attributes.d.mts +3 -2
- package/dist/db/adapter/get-field-attributes.mjs +2 -1
- package/dist/db/adapter/get-field-attributes.mjs.map +1 -0
- package/dist/db/adapter/get-field-name.d.mts +2 -1
- package/dist/db/adapter/get-field-name.mjs +2 -1
- package/dist/db/adapter/get-field-name.mjs.map +1 -0
- package/dist/db/adapter/get-id-field.d.mts +3 -2
- package/dist/db/adapter/get-id-field.mjs +3 -2
- package/dist/db/adapter/get-id-field.mjs.map +1 -0
- package/dist/db/adapter/get-model-name.d.mts +2 -1
- package/dist/db/adapter/get-model-name.mjs +2 -1
- package/dist/db/adapter/get-model-name.mjs.map +1 -0
- package/dist/db/adapter/index.d.mts +10 -4
- package/dist/db/adapter/index.mjs +19 -2
- package/dist/db/adapter/index.mjs.map +1 -0
- package/dist/db/adapter/types.d.mts +3 -34
- package/dist/db/adapter/utils.d.mts +2 -1
- package/dist/db/adapter/utils.mjs +2 -1
- package/dist/db/adapter/utils.mjs.map +1 -0
- package/dist/db/get-tables.d.mts +2 -1
- package/dist/db/get-tables.mjs +46 -39
- package/dist/db/get-tables.mjs.map +1 -0
- package/dist/db/index.d.mts +7 -7
- package/dist/db/plugin.d.mts +2 -1
- package/dist/db/schema/account.d.mts +8 -4
- package/dist/db/schema/account.mjs +2 -1
- package/dist/db/schema/account.mjs.map +1 -0
- package/dist/db/schema/rate-limit.d.mts +8 -2
- package/dist/db/schema/rate-limit.mjs +2 -1
- package/dist/db/schema/rate-limit.mjs.map +1 -0
- package/dist/db/schema/session.d.mts +8 -4
- package/dist/db/schema/session.mjs +2 -1
- package/dist/db/schema/session.mjs.map +1 -0
- package/dist/db/schema/shared.d.mts +2 -1
- package/dist/db/schema/shared.mjs +2 -1
- package/dist/db/schema/shared.mjs.map +1 -0
- package/dist/db/schema/user.d.mts +8 -4
- package/dist/db/schema/user.mjs +2 -1
- package/dist/db/schema/user.mjs.map +1 -0
- package/dist/db/schema/verification.d.mts +8 -4
- package/dist/db/schema/verification.mjs +2 -1
- package/dist/db/schema/verification.mjs.map +1 -0
- package/dist/db/type.d.mts +28 -2
- package/dist/env/color-depth.d.mts +2 -1
- package/dist/env/color-depth.mjs +2 -1
- package/dist/env/color-depth.mjs.map +1 -0
- package/dist/env/env-impl.d.mts +3 -2
- package/dist/env/env-impl.mjs +9 -8
- package/dist/env/env-impl.mjs.map +1 -0
- package/dist/env/logger.d.mts +2 -1
- package/dist/env/logger.mjs +3 -2
- package/dist/env/logger.mjs.map +1 -0
- package/dist/error/codes.d.mts +64 -181
- package/dist/error/codes.mjs +6 -2
- package/dist/error/codes.mjs.map +1 -0
- package/dist/error/index.d.mts +2 -1
- package/dist/error/index.mjs +2 -1
- package/dist/error/index.mjs.map +1 -0
- package/dist/index.d.mts +5 -4
- package/dist/oauth2/client-credentials-token.d.mts +25 -3
- package/dist/oauth2/client-credentials-token.mjs +15 -2
- package/dist/oauth2/client-credentials-token.mjs.map +1 -0
- package/dist/oauth2/create-authorization-url.d.mts +5 -2
- package/dist/oauth2/create-authorization-url.mjs +3 -1
- package/dist/oauth2/create-authorization-url.mjs.map +1 -0
- package/dist/oauth2/index.d.mts +4 -4
- package/dist/oauth2/index.mjs +4 -4
- package/dist/oauth2/oauth-provider.d.mts +3 -2
- package/dist/oauth2/refresh-access-token.d.mts +24 -4
- package/dist/oauth2/refresh-access-token.mjs +20 -2
- package/dist/oauth2/refresh-access-token.mjs.map +1 -0
- package/dist/oauth2/utils.d.mts +2 -1
- package/dist/oauth2/utils.mjs +2 -1
- package/dist/oauth2/utils.mjs.map +1 -0
- package/dist/oauth2/validate-authorization-code.d.mts +37 -4
- package/dist/oauth2/validate-authorization-code.mjs +25 -13
- package/dist/oauth2/validate-authorization-code.mjs.map +1 -0
- package/dist/oauth2/verify.d.mts +7 -13
- package/dist/oauth2/verify.mjs +2 -1
- package/dist/oauth2/verify.mjs.map +1 -0
- package/dist/social-providers/apple.d.mts +2 -1
- package/dist/social-providers/apple.mjs +22 -21
- package/dist/social-providers/apple.mjs.map +1 -0
- package/dist/social-providers/atlassian.d.mts +2 -1
- package/dist/social-providers/atlassian.mjs +2 -1
- package/dist/social-providers/atlassian.mjs.map +1 -0
- package/dist/social-providers/cognito.d.mts +2 -1
- package/dist/social-providers/cognito.mjs +4 -3
- package/dist/social-providers/cognito.mjs.map +1 -0
- package/dist/social-providers/discord.d.mts +2 -1
- package/dist/social-providers/discord.mjs +2 -1
- package/dist/social-providers/discord.mjs.map +1 -0
- package/dist/social-providers/dropbox.d.mts +2 -1
- package/dist/social-providers/dropbox.mjs +2 -1
- package/dist/social-providers/dropbox.mjs.map +1 -0
- package/dist/social-providers/facebook.d.mts +2 -1
- package/dist/social-providers/facebook.mjs +13 -12
- package/dist/social-providers/facebook.mjs.map +1 -0
- package/dist/social-providers/figma.d.mts +2 -1
- package/dist/social-providers/figma.mjs +2 -1
- package/dist/social-providers/figma.mjs.map +1 -0
- package/dist/social-providers/github.d.mts +3 -2
- package/dist/social-providers/github.mjs +23 -6
- package/dist/social-providers/github.mjs.map +1 -0
- package/dist/social-providers/gitlab.d.mts +2 -1
- package/dist/social-providers/gitlab.mjs +3 -2
- package/dist/social-providers/gitlab.mjs.map +1 -0
- package/dist/social-providers/google.d.mts +2 -1
- package/dist/social-providers/google.mjs +18 -13
- package/dist/social-providers/google.mjs.map +1 -0
- package/dist/social-providers/huggingface.d.mts +2 -1
- package/dist/social-providers/huggingface.mjs +3 -2
- package/dist/social-providers/huggingface.mjs.map +1 -0
- package/dist/social-providers/index.d.mts +61 -8
- package/dist/social-providers/index.mjs +5 -2
- package/dist/social-providers/index.mjs.map +1 -0
- package/dist/social-providers/kakao.d.mts +3 -2
- package/dist/social-providers/kakao.mjs +3 -2
- package/dist/social-providers/kakao.mjs.map +1 -0
- package/dist/social-providers/kick.d.mts +2 -1
- package/dist/social-providers/kick.mjs +2 -1
- package/dist/social-providers/kick.mjs.map +1 -0
- package/dist/social-providers/line.d.mts +2 -1
- package/dist/social-providers/line.mjs +3 -2
- package/dist/social-providers/line.mjs.map +1 -0
- package/dist/social-providers/linear.d.mts +2 -1
- package/dist/social-providers/linear.mjs +2 -1
- package/dist/social-providers/linear.mjs.map +1 -0
- package/dist/social-providers/linkedin.d.mts +2 -1
- package/dist/social-providers/linkedin.mjs +2 -1
- package/dist/social-providers/linkedin.mjs.map +1 -0
- package/dist/social-providers/microsoft-entra-id.d.mts +4 -1
- package/dist/social-providers/microsoft-entra-id.mjs +36 -2
- package/dist/social-providers/microsoft-entra-id.mjs.map +1 -0
- package/dist/social-providers/naver.d.mts +11 -20
- package/dist/social-providers/naver.mjs +3 -2
- package/dist/social-providers/naver.mjs.map +1 -0
- package/dist/social-providers/notion.d.mts +2 -1
- package/dist/social-providers/notion.mjs +3 -2
- package/dist/social-providers/notion.mjs.map +1 -0
- package/dist/social-providers/paybin.d.mts +2 -1
- package/dist/social-providers/paybin.mjs +3 -2
- package/dist/social-providers/paybin.mjs.map +1 -0
- package/dist/social-providers/paypal.d.mts +2 -1
- package/dist/social-providers/paypal.mjs +2 -1
- package/dist/social-providers/paypal.mjs.map +1 -0
- package/dist/social-providers/polar.d.mts +2 -1
- package/dist/social-providers/polar.mjs +3 -2
- package/dist/social-providers/polar.mjs.map +1 -0
- package/dist/social-providers/railway.d.mts +68 -0
- package/dist/social-providers/railway.mjs +78 -0
- package/dist/social-providers/railway.mjs.map +1 -0
- package/dist/social-providers/reddit.d.mts +2 -1
- package/dist/social-providers/reddit.mjs +2 -1
- package/dist/social-providers/reddit.mjs.map +1 -0
- package/dist/social-providers/roblox.d.mts +2 -1
- package/dist/social-providers/roblox.mjs +2 -1
- package/dist/social-providers/roblox.mjs.map +1 -0
- package/dist/social-providers/salesforce.d.mts +2 -1
- package/dist/social-providers/salesforce.mjs +2 -1
- package/dist/social-providers/salesforce.mjs.map +1 -0
- package/dist/social-providers/slack.d.mts +2 -1
- package/dist/social-providers/slack.mjs +2 -1
- package/dist/social-providers/slack.mjs.map +1 -0
- package/dist/social-providers/spotify.d.mts +2 -1
- package/dist/social-providers/spotify.mjs +2 -1
- package/dist/social-providers/spotify.mjs.map +1 -0
- package/dist/social-providers/tiktok.d.mts +3 -3
- package/dist/social-providers/tiktok.mjs +3 -2
- package/dist/social-providers/tiktok.mjs.map +1 -0
- package/dist/social-providers/twitch.d.mts +2 -1
- package/dist/social-providers/twitch.mjs +2 -1
- package/dist/social-providers/twitch.mjs.map +1 -0
- package/dist/social-providers/twitter.d.mts +14 -25
- package/dist/social-providers/twitter.mjs +2 -1
- package/dist/social-providers/twitter.mjs.map +1 -0
- package/dist/social-providers/vercel.d.mts +2 -1
- package/dist/social-providers/vercel.mjs +3 -2
- package/dist/social-providers/vercel.mjs.map +1 -0
- package/dist/social-providers/vk.d.mts +2 -1
- package/dist/social-providers/vk.mjs +2 -1
- package/dist/social-providers/vk.mjs.map +1 -0
- package/dist/social-providers/zoom.d.mts +3 -10
- package/dist/social-providers/zoom.mjs +2 -1
- package/dist/social-providers/zoom.mjs.map +1 -0
- package/dist/types/context.d.mts +53 -21
- package/dist/types/cookie.d.mts +2 -1
- package/dist/types/helper.d.mts +4 -1
- package/dist/types/index.d.mts +4 -3
- package/dist/types/init-options.d.mts +231 -159
- package/dist/types/plugin-client.d.mts +4 -1
- package/dist/types/plugin.d.mts +12 -11
- package/dist/types/secret.d.mts +12 -0
- package/dist/utils/db.d.mts +12 -0
- package/dist/utils/db.mjs +17 -0
- package/dist/utils/db.mjs.map +1 -0
- package/dist/utils/deprecate.d.mts +2 -2
- package/dist/utils/deprecate.mjs +2 -1
- package/dist/utils/deprecate.mjs.map +1 -0
- package/dist/utils/error-codes.d.mts +8 -6
- package/dist/utils/error-codes.mjs +3 -2
- package/dist/utils/error-codes.mjs.map +1 -0
- package/dist/utils/id.d.mts +2 -1
- package/dist/utils/id.mjs +2 -1
- package/dist/utils/id.mjs.map +1 -0
- package/dist/utils/ip.d.mts +2 -1
- package/dist/utils/ip.mjs +2 -1
- package/dist/utils/ip.mjs.map +1 -0
- package/dist/utils/json.d.mts +2 -1
- package/dist/utils/json.mjs +2 -1
- package/dist/utils/json.mjs.map +1 -0
- package/dist/utils/string.d.mts +2 -1
- package/dist/utils/string.mjs +2 -1
- package/dist/utils/string.mjs.map +1 -0
- package/dist/utils/url.d.mts +2 -1
- package/dist/utils/url.mjs +2 -1
- package/dist/utils/url.mjs.map +1 -0
- package/package.json +35 -13
- package/src/db/adapter/factory.ts +41 -73
- package/src/db/adapter/get-id-field.ts +1 -3
- package/src/db/adapter/index.ts +20 -15
- package/src/db/adapter/types.ts +2 -41
- package/src/db/get-tables.ts +48 -37
- package/src/db/index.ts +30 -5
- package/src/db/schema/account.ts +16 -3
- package/src/db/schema/rate-limit.ts +16 -1
- package/src/db/schema/session.ts +15 -3
- package/src/db/schema/user.ts +15 -3
- package/src/db/schema/verification.ts +16 -3
- package/src/db/test/get-tables.test.ts +33 -0
- package/src/db/type.ts +154 -1
- package/src/env/env-impl.ts +2 -2
- package/src/env/logger.ts +1 -1
- package/src/error/codes.ts +17 -0
- package/src/oauth2/client-credentials-token.ts +26 -2
- package/src/oauth2/create-authorization-url.ts +3 -1
- package/src/oauth2/index.ts +3 -0
- package/src/oauth2/oauth-provider.ts +1 -1
- package/src/oauth2/refresh-access-token.test.ts +90 -0
- package/src/oauth2/refresh-access-token.ts +37 -4
- package/src/oauth2/validate-authorization-code.ts +55 -24
- package/src/oauth2/validate-token.test.ts +107 -52
- package/src/social-providers/apple.ts +29 -29
- package/src/social-providers/cognito.ts +6 -5
- package/src/social-providers/facebook.ts +3 -3
- package/src/social-providers/github.ts +26 -4
- package/src/social-providers/gitlab.ts +1 -1
- package/src/social-providers/google.ts +18 -14
- package/src/social-providers/huggingface.ts +1 -1
- package/src/social-providers/index.ts +9 -5
- package/src/social-providers/kakao.ts +1 -1
- package/src/social-providers/line.ts +1 -1
- package/src/social-providers/microsoft-entra-id.ts +84 -1
- package/src/social-providers/naver.ts +1 -1
- package/src/social-providers/notion.ts +1 -1
- package/src/social-providers/paybin.ts +1 -5
- package/src/social-providers/polar.ts +1 -1
- package/src/social-providers/railway.ts +100 -0
- package/src/social-providers/tiktok.ts +2 -1
- package/src/social-providers/vercel.ts +1 -1
- package/src/social-providers/zoom.ts +0 -8
- package/src/types/context.ts +74 -14
- package/src/types/helper.ts +9 -0
- package/src/types/index.ts +14 -2
- package/src/types/init-options.ts +294 -186
- package/src/types/plugin-client.ts +1 -0
- package/src/types/plugin.ts +11 -6
- package/src/types/secret.ts +8 -0
- package/src/utils/db.ts +20 -0
- package/src/utils/deprecate.test.ts +0 -1
- package/src/utils/error-codes.ts +12 -9
- package/.turbo/turbo-build.log +0 -182
- package/tsconfig.json +0 -7
- package/tsdown.config.ts +0 -32
- package/vitest.config.ts +0 -3
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { betterFetch } from "@better-fetch/fetch";
|
|
2
|
+
import { logger } from "../env";
|
|
2
3
|
import type { OAuthProvider, ProviderOptions } from "../oauth2";
|
|
3
4
|
import {
|
|
4
5
|
createAuthorizationURL,
|
|
6
|
+
getOAuth2Tokens,
|
|
5
7
|
refreshAccessToken,
|
|
6
|
-
validateAuthorizationCode,
|
|
7
8
|
} from "../oauth2";
|
|
9
|
+
import { createAuthorizationCodeRequest } from "../oauth2/validate-authorization-code";
|
|
8
10
|
|
|
9
11
|
export interface GithubProfile {
|
|
10
12
|
login: string;
|
|
@@ -86,13 +88,33 @@ export const github = (options: GithubOptions) => {
|
|
|
86
88
|
});
|
|
87
89
|
},
|
|
88
90
|
validateAuthorizationCode: async ({ code, codeVerifier, redirectURI }) => {
|
|
89
|
-
|
|
91
|
+
const { body, headers: requestHeaders } = createAuthorizationCodeRequest({
|
|
90
92
|
code,
|
|
91
93
|
codeVerifier,
|
|
92
94
|
redirectURI,
|
|
93
95
|
options,
|
|
94
|
-
tokenEndpoint,
|
|
95
96
|
});
|
|
97
|
+
|
|
98
|
+
const { data, error } = await betterFetch<
|
|
99
|
+
| { access_token: string; token_type: string; scope: string }
|
|
100
|
+
| { error: string; error_description?: string; error_uri?: string }
|
|
101
|
+
>(tokenEndpoint, {
|
|
102
|
+
method: "POST",
|
|
103
|
+
body: body,
|
|
104
|
+
headers: requestHeaders,
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
if (error) {
|
|
108
|
+
logger.error("GitHub OAuth token exchange failed:", error);
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if ("error" in data) {
|
|
113
|
+
logger.error("GitHub OAuth token exchange failed:", data);
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return getOAuth2Tokens(data);
|
|
96
118
|
},
|
|
97
119
|
refreshAccessToken: options.refreshAccessToken
|
|
98
120
|
? options.refreshAccessToken
|
|
@@ -148,7 +170,7 @@ export const github = (options: GithubOptions) => {
|
|
|
148
170
|
return {
|
|
149
171
|
user: {
|
|
150
172
|
id: profile.id,
|
|
151
|
-
name: profile.name || profile.login,
|
|
173
|
+
name: profile.name || profile.login || "",
|
|
152
174
|
email: profile.email,
|
|
153
175
|
image: profile.avatar_url,
|
|
154
176
|
emailVerified,
|
|
@@ -141,7 +141,7 @@ export const gitlab = (options: GitlabOptions) => {
|
|
|
141
141
|
return {
|
|
142
142
|
user: {
|
|
143
143
|
id: profile.id,
|
|
144
|
-
name: profile.name ?? profile.username,
|
|
144
|
+
name: profile.name ?? profile.username ?? "",
|
|
145
145
|
email: profile.email,
|
|
146
146
|
image: profile.avatar_url,
|
|
147
147
|
emailVerified: profile.email_verified ?? false,
|
|
@@ -81,7 +81,7 @@ export const google = (options: GoogleOptions) => {
|
|
|
81
81
|
const url = await createAuthorizationURL({
|
|
82
82
|
id: "google",
|
|
83
83
|
options,
|
|
84
|
-
authorizationEndpoint: "https://accounts.google.com/o/oauth2/auth",
|
|
84
|
+
authorizationEndpoint: "https://accounts.google.com/o/oauth2/v2/auth",
|
|
85
85
|
scopes: _scopes,
|
|
86
86
|
state,
|
|
87
87
|
codeVerifier,
|
|
@@ -116,7 +116,7 @@ export const google = (options: GoogleOptions) => {
|
|
|
116
116
|
clientKey: options.clientKey,
|
|
117
117
|
clientSecret: options.clientSecret,
|
|
118
118
|
},
|
|
119
|
-
tokenEndpoint: "https://
|
|
119
|
+
tokenEndpoint: "https://oauth2.googleapis.com/token",
|
|
120
120
|
});
|
|
121
121
|
},
|
|
122
122
|
async verifyIdToken(token, nonce) {
|
|
@@ -130,22 +130,26 @@ export const google = (options: GoogleOptions) => {
|
|
|
130
130
|
// Verify JWT integrity
|
|
131
131
|
// See https://developers.google.com/identity/sign-in/web/backend-auth#verify-the-integrity-of-the-id-token
|
|
132
132
|
|
|
133
|
-
|
|
134
|
-
|
|
133
|
+
try {
|
|
134
|
+
const { kid, alg: jwtAlg } = decodeProtectedHeader(token);
|
|
135
|
+
if (!kid || !jwtAlg) return false;
|
|
135
136
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
137
|
+
const publicKey = await getGooglePublicKey(kid);
|
|
138
|
+
const { payload: jwtClaims } = await jwtVerify(token, publicKey, {
|
|
139
|
+
algorithms: [jwtAlg],
|
|
140
|
+
issuer: ["https://accounts.google.com", "accounts.google.com"],
|
|
141
|
+
audience: options.clientId,
|
|
142
|
+
maxTokenAge: "1h",
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
if (nonce && jwtClaims.nonce !== nonce) {
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
143
148
|
|
|
144
|
-
|
|
149
|
+
return true;
|
|
150
|
+
} catch {
|
|
145
151
|
return false;
|
|
146
152
|
}
|
|
147
|
-
|
|
148
|
-
return true;
|
|
149
153
|
},
|
|
150
154
|
async getUserInfo(token) {
|
|
151
155
|
if (options.getUserInfo) {
|
|
@@ -104,7 +104,7 @@ export const huggingface = (options: HuggingFaceOptions) => {
|
|
|
104
104
|
return {
|
|
105
105
|
user: {
|
|
106
106
|
id: profile.sub,
|
|
107
|
-
name: profile.name || profile.preferred_username,
|
|
107
|
+
name: profile.name || profile.preferred_username || "",
|
|
108
108
|
email: profile.email,
|
|
109
109
|
image: profile.picture,
|
|
110
110
|
emailVerified: profile.email_verified ?? false,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as z from "zod";
|
|
2
|
+
import type { AwaitableFunction } from "../types";
|
|
2
3
|
import { apple } from "./apple";
|
|
3
4
|
import { atlassian } from "./atlassian";
|
|
4
5
|
import { cognito } from "./cognito";
|
|
@@ -21,6 +22,7 @@ import { notion } from "./notion";
|
|
|
21
22
|
import { paybin } from "./paybin";
|
|
22
23
|
import { paypal } from "./paypal";
|
|
23
24
|
import { polar } from "./polar";
|
|
25
|
+
import { railway } from "./railway";
|
|
24
26
|
import { reddit } from "./reddit";
|
|
25
27
|
import { roblox } from "./roblox";
|
|
26
28
|
import { salesforce } from "./salesforce";
|
|
@@ -66,6 +68,7 @@ export const socialProviders = {
|
|
|
66
68
|
paybin,
|
|
67
69
|
paypal,
|
|
68
70
|
polar,
|
|
71
|
+
railway,
|
|
69
72
|
vercel,
|
|
70
73
|
};
|
|
71
74
|
|
|
@@ -81,11 +84,11 @@ export const SocialProviderListEnum = z
|
|
|
81
84
|
export type SocialProvider = z.infer<typeof SocialProviderListEnum>;
|
|
82
85
|
|
|
83
86
|
export type SocialProviders = {
|
|
84
|
-
[K in SocialProviderList[number]]?:
|
|
85
|
-
(typeof socialProviders)[K]
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
87
|
+
[K in SocialProviderList[number]]?: AwaitableFunction<
|
|
88
|
+
Parameters<(typeof socialProviders)[K]>[0] & {
|
|
89
|
+
enabled?: boolean | undefined;
|
|
90
|
+
}
|
|
91
|
+
>;
|
|
89
92
|
};
|
|
90
93
|
|
|
91
94
|
export * from "./apple";
|
|
@@ -112,6 +115,7 @@ export * from "./notion";
|
|
|
112
115
|
export * from "./paybin";
|
|
113
116
|
export * from "./paypal";
|
|
114
117
|
export * from "./polar";
|
|
118
|
+
export * from "./railway";
|
|
115
119
|
export * from "./reddit";
|
|
116
120
|
export * from "./roblox";
|
|
117
121
|
export * from "./salesforce";
|
|
@@ -161,7 +161,7 @@ export const kakao = (options: KakaoOptions) => {
|
|
|
161
161
|
const kakaoProfile = account.profile || {};
|
|
162
162
|
const user = {
|
|
163
163
|
id: String(profile.id),
|
|
164
|
-
name: kakaoProfile.nickname || account.name ||
|
|
164
|
+
name: kakaoProfile.nickname || account.name || "",
|
|
165
165
|
email: account.email,
|
|
166
166
|
image:
|
|
167
167
|
kakaoProfile.profile_image_url || kakaoProfile.thumbnail_image_url,
|
|
@@ -147,7 +147,7 @@ export const line = (options: LineOptions) => {
|
|
|
147
147
|
const userMap = await options.mapProfileToUser?.(profile as any);
|
|
148
148
|
// ID preference order
|
|
149
149
|
const id = (profile as any).sub || (profile as any).userId;
|
|
150
|
-
const name = (profile as any).name || (profile as any).displayName;
|
|
150
|
+
const name = (profile as any).name || (profile as any).displayName || "";
|
|
151
151
|
const image =
|
|
152
152
|
(profile as any).picture || (profile as any).pictureUrl || undefined;
|
|
153
153
|
const email = (profile as any).email;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { base64 } from "@better-auth/utils/base64";
|
|
2
2
|
import { betterFetch } from "@better-fetch/fetch";
|
|
3
|
-
import { decodeJwt } from "jose";
|
|
3
|
+
import { decodeJwt, decodeProtectedHeader, importJWK, jwtVerify } from "jose";
|
|
4
4
|
import { logger } from "../env";
|
|
5
|
+
import { APIError } from "../error";
|
|
5
6
|
import type { OAuthProvider, ProviderOptions } from "../oauth2";
|
|
6
7
|
import {
|
|
7
8
|
createAuthorizationURL,
|
|
@@ -174,6 +175,56 @@ export const microsoft = (options: MicrosoftOptions) => {
|
|
|
174
175
|
tokenEndpoint,
|
|
175
176
|
});
|
|
176
177
|
},
|
|
178
|
+
async verifyIdToken(token, nonce) {
|
|
179
|
+
if (options.disableIdTokenSignIn) {
|
|
180
|
+
return false;
|
|
181
|
+
}
|
|
182
|
+
if (options.verifyIdToken) {
|
|
183
|
+
return options.verifyIdToken(token, nonce);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
try {
|
|
187
|
+
const { kid, alg: jwtAlg } = decodeProtectedHeader(token);
|
|
188
|
+
if (!kid || !jwtAlg) return false;
|
|
189
|
+
|
|
190
|
+
const publicKey = await getMicrosoftPublicKey(kid, tenant, authority);
|
|
191
|
+
const verifyOptions: {
|
|
192
|
+
algorithms: [string];
|
|
193
|
+
audience: string;
|
|
194
|
+
maxTokenAge: string;
|
|
195
|
+
issuer?: string;
|
|
196
|
+
} = {
|
|
197
|
+
algorithms: [jwtAlg],
|
|
198
|
+
audience: options.clientId,
|
|
199
|
+
maxTokenAge: "1h",
|
|
200
|
+
};
|
|
201
|
+
/**
|
|
202
|
+
* Issuer varies per user's tenant for multi-tenant endpoints, so only validate for specific tenants.
|
|
203
|
+
* @see https://learn.microsoft.com/en-us/entra/identity-platform/v2-protocols#endpoints
|
|
204
|
+
*/
|
|
205
|
+
if (
|
|
206
|
+
tenant !== "common" &&
|
|
207
|
+
tenant !== "organizations" &&
|
|
208
|
+
tenant !== "consumers"
|
|
209
|
+
) {
|
|
210
|
+
verifyOptions.issuer = `${authority}/${tenant}/v2.0`;
|
|
211
|
+
}
|
|
212
|
+
const { payload: jwtClaims } = await jwtVerify(
|
|
213
|
+
token,
|
|
214
|
+
publicKey,
|
|
215
|
+
verifyOptions,
|
|
216
|
+
);
|
|
217
|
+
|
|
218
|
+
if (nonce && jwtClaims.nonce !== nonce) {
|
|
219
|
+
return false;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
return true;
|
|
223
|
+
} catch (error) {
|
|
224
|
+
logger.error("Failed to verify ID token:", error);
|
|
225
|
+
return false;
|
|
226
|
+
}
|
|
227
|
+
},
|
|
177
228
|
async getUserInfo(token) {
|
|
178
229
|
if (options.getUserInfo) {
|
|
179
230
|
return options.getUserInfo(token);
|
|
@@ -257,3 +308,35 @@ export const microsoft = (options: MicrosoftOptions) => {
|
|
|
257
308
|
options,
|
|
258
309
|
} satisfies OAuthProvider;
|
|
259
310
|
};
|
|
311
|
+
|
|
312
|
+
export const getMicrosoftPublicKey = async (
|
|
313
|
+
kid: string,
|
|
314
|
+
tenant: string,
|
|
315
|
+
authority: string,
|
|
316
|
+
) => {
|
|
317
|
+
const { data } = await betterFetch<{
|
|
318
|
+
keys: Array<{
|
|
319
|
+
kid: string;
|
|
320
|
+
alg: string;
|
|
321
|
+
kty: string;
|
|
322
|
+
use: string;
|
|
323
|
+
n: string;
|
|
324
|
+
e: string;
|
|
325
|
+
x5c?: string[];
|
|
326
|
+
x5t?: string;
|
|
327
|
+
}>;
|
|
328
|
+
}>(`${authority}/${tenant}/discovery/v2.0/keys`);
|
|
329
|
+
|
|
330
|
+
if (!data?.keys) {
|
|
331
|
+
throw new APIError("BAD_REQUEST", {
|
|
332
|
+
message: "Keys not found",
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
const jwk = data.keys.find((key) => key.kid === kid);
|
|
337
|
+
if (!jwk) {
|
|
338
|
+
throw new Error(`JWK with kid ${kid} not found`);
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
return await importJWK(jwk, jwk.alg);
|
|
342
|
+
};
|
|
@@ -96,7 +96,7 @@ export const naver = (options: NaverOptions) => {
|
|
|
96
96
|
const res = profile.response || {};
|
|
97
97
|
const user = {
|
|
98
98
|
id: res.id,
|
|
99
|
-
name: res.name || res.nickname,
|
|
99
|
+
name: res.name || res.nickname || "",
|
|
100
100
|
email: res.email,
|
|
101
101
|
image: res.profile_image,
|
|
102
102
|
emailVerified: false,
|
|
@@ -94,7 +94,7 @@ export const notion = (options: NotionOptions) => {
|
|
|
94
94
|
return {
|
|
95
95
|
user: {
|
|
96
96
|
id: userProfile.id,
|
|
97
|
-
name: userProfile.name || "
|
|
97
|
+
name: userProfile.name || "",
|
|
98
98
|
email: userProfile.person?.email || null,
|
|
99
99
|
image: userProfile.avatar_url,
|
|
100
100
|
emailVerified: false,
|
|
@@ -104,11 +104,7 @@ export const paybin = (options: PaybinOptions) => {
|
|
|
104
104
|
return {
|
|
105
105
|
user: {
|
|
106
106
|
id: user.sub,
|
|
107
|
-
name:
|
|
108
|
-
user.name ||
|
|
109
|
-
user.preferred_username ||
|
|
110
|
-
(user.email ? user.email.split("@")[0] : "User") ||
|
|
111
|
-
"User",
|
|
107
|
+
name: user.name || user.preferred_username || "",
|
|
112
108
|
email: user.email,
|
|
113
109
|
image: user.picture,
|
|
114
110
|
emailVerified: user.email_verified || false,
|
|
@@ -96,7 +96,7 @@ export const polar = (options: PolarOptions) => {
|
|
|
96
96
|
return {
|
|
97
97
|
user: {
|
|
98
98
|
id: profile.id,
|
|
99
|
-
name: profile.public_name || profile.username,
|
|
99
|
+
name: profile.public_name || profile.username || "",
|
|
100
100
|
email: profile.email,
|
|
101
101
|
image: profile.avatar_url,
|
|
102
102
|
emailVerified: profile.email_verified ?? false,
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { betterFetch } from "@better-fetch/fetch";
|
|
2
|
+
import type { OAuthProvider, ProviderOptions } from "../oauth2";
|
|
3
|
+
import {
|
|
4
|
+
createAuthorizationURL,
|
|
5
|
+
refreshAccessToken,
|
|
6
|
+
validateAuthorizationCode,
|
|
7
|
+
} from "../oauth2";
|
|
8
|
+
|
|
9
|
+
const authorizationEndpoint = "https://backboard.railway.com/oauth/auth";
|
|
10
|
+
const tokenEndpoint = "https://backboard.railway.com/oauth/token";
|
|
11
|
+
const userinfoEndpoint = "https://backboard.railway.com/oauth/me";
|
|
12
|
+
|
|
13
|
+
export interface RailwayProfile {
|
|
14
|
+
/** The user's unique ID (OAuth `sub` claim). */
|
|
15
|
+
sub: string;
|
|
16
|
+
/** The user's email address. */
|
|
17
|
+
email: string;
|
|
18
|
+
/** The user's display name. */
|
|
19
|
+
name: string;
|
|
20
|
+
/** URL of the user's profile picture. */
|
|
21
|
+
picture: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface RailwayOptions extends ProviderOptions<RailwayProfile> {
|
|
25
|
+
clientId: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export const railway = (options: RailwayOptions) => {
|
|
29
|
+
return {
|
|
30
|
+
id: "railway",
|
|
31
|
+
name: "Railway",
|
|
32
|
+
createAuthorizationURL({ state, scopes, codeVerifier, redirectURI }) {
|
|
33
|
+
const _scopes = options.disableDefaultScope
|
|
34
|
+
? []
|
|
35
|
+
: ["openid", "email", "profile"];
|
|
36
|
+
if (options.scope) _scopes.push(...options.scope);
|
|
37
|
+
if (scopes) _scopes.push(...scopes);
|
|
38
|
+
return createAuthorizationURL({
|
|
39
|
+
id: "railway",
|
|
40
|
+
options,
|
|
41
|
+
authorizationEndpoint,
|
|
42
|
+
scopes: _scopes,
|
|
43
|
+
state,
|
|
44
|
+
codeVerifier,
|
|
45
|
+
redirectURI,
|
|
46
|
+
});
|
|
47
|
+
},
|
|
48
|
+
validateAuthorizationCode: async ({ code, codeVerifier, redirectURI }) => {
|
|
49
|
+
return validateAuthorizationCode({
|
|
50
|
+
code,
|
|
51
|
+
codeVerifier,
|
|
52
|
+
redirectURI,
|
|
53
|
+
options,
|
|
54
|
+
tokenEndpoint,
|
|
55
|
+
authentication: "basic",
|
|
56
|
+
});
|
|
57
|
+
},
|
|
58
|
+
refreshAccessToken: options.refreshAccessToken
|
|
59
|
+
? options.refreshAccessToken
|
|
60
|
+
: async (refreshToken) => {
|
|
61
|
+
return refreshAccessToken({
|
|
62
|
+
refreshToken,
|
|
63
|
+
options: {
|
|
64
|
+
clientId: options.clientId,
|
|
65
|
+
clientKey: options.clientKey,
|
|
66
|
+
clientSecret: options.clientSecret,
|
|
67
|
+
},
|
|
68
|
+
tokenEndpoint,
|
|
69
|
+
authentication: "basic",
|
|
70
|
+
});
|
|
71
|
+
},
|
|
72
|
+
async getUserInfo(token) {
|
|
73
|
+
if (options.getUserInfo) {
|
|
74
|
+
return options.getUserInfo(token);
|
|
75
|
+
}
|
|
76
|
+
const { data: profile, error } = await betterFetch<RailwayProfile>(
|
|
77
|
+
userinfoEndpoint,
|
|
78
|
+
{ headers: { authorization: `Bearer ${token.accessToken}` } },
|
|
79
|
+
);
|
|
80
|
+
if (error || !profile) {
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
const userMap = await options.mapProfileToUser?.(profile);
|
|
84
|
+
// Railway does not provide an email_verified claim.
|
|
85
|
+
// We default to false for security consistency.
|
|
86
|
+
return {
|
|
87
|
+
user: {
|
|
88
|
+
id: profile.sub,
|
|
89
|
+
name: profile.name,
|
|
90
|
+
email: profile.email,
|
|
91
|
+
image: profile.picture,
|
|
92
|
+
emailVerified: false,
|
|
93
|
+
...userMap,
|
|
94
|
+
},
|
|
95
|
+
data: profile,
|
|
96
|
+
};
|
|
97
|
+
},
|
|
98
|
+
options,
|
|
99
|
+
} satisfies OAuthProvider<RailwayProfile>;
|
|
100
|
+
};
|
|
@@ -197,7 +197,8 @@ export const tiktok = (options: TiktokOptions) => {
|
|
|
197
197
|
user: {
|
|
198
198
|
email: profile.data.user.email || profile.data.user.username,
|
|
199
199
|
id: profile.data.user.open_id,
|
|
200
|
-
name:
|
|
200
|
+
name:
|
|
201
|
+
profile.data.user.display_name || profile.data.user.username || "",
|
|
201
202
|
image: profile.data.user.avatar_large_url,
|
|
202
203
|
emailVerified: false,
|
|
203
204
|
},
|
|
@@ -73,7 +73,7 @@ export const vercel = (options: VercelOptions) => {
|
|
|
73
73
|
return {
|
|
74
74
|
user: {
|
|
75
75
|
id: profile.sub,
|
|
76
|
-
name: profile.name ?? profile.preferred_username,
|
|
76
|
+
name: profile.name ?? profile.preferred_username ?? "",
|
|
77
77
|
email: profile.email,
|
|
78
78
|
image: profile.picture,
|
|
79
79
|
emailVerified: profile.email_verified ?? false,
|
|
@@ -96,11 +96,6 @@ export interface ZoomProfile extends Record<string, any> {
|
|
|
96
96
|
login_types: LoginType[];
|
|
97
97
|
/** User's personal meeting URL (Example: "example.com") */
|
|
98
98
|
personal_meeting_url: string;
|
|
99
|
-
/** This field has been deprecated and will not be supported in the future.
|
|
100
|
-
* Use the phone_numbers field instead of this field.
|
|
101
|
-
* The user's phone number (Example: "+1 800000000") */
|
|
102
|
-
// @deprecated true
|
|
103
|
-
phone_number?: string | undefined;
|
|
104
99
|
/** The URL for user's profile picture (Example: "example.com") */
|
|
105
100
|
pic_url: string;
|
|
106
101
|
/** Personal Meeting ID (PMI) (Example: 3542471135) */
|
|
@@ -131,9 +126,6 @@ export interface ZoomProfile extends Record<string, any> {
|
|
|
131
126
|
employee_unique_id?: string | undefined;
|
|
132
127
|
/** The manager for the user (Example: "thill@example.com") */
|
|
133
128
|
manager?: string | undefined;
|
|
134
|
-
/** The user's country for the company phone number (Example: "US")
|
|
135
|
-
* @deprecated true */
|
|
136
|
-
phone_country?: string | undefined;
|
|
137
129
|
/** The phone number's ISO country code (Example: "+1") */
|
|
138
130
|
phone_numbers?: PhoneNumber[] | undefined;
|
|
139
131
|
/** The user's plan type (Example: "1") */
|
package/src/types/context.ts
CHANGED
|
@@ -12,29 +12,66 @@ import type { DBAdapter, Where } from "../db/adapter";
|
|
|
12
12
|
import type { createLogger } from "../env";
|
|
13
13
|
import type { OAuthProvider } from "../oauth2";
|
|
14
14
|
import type { BetterAuthCookie, BetterAuthCookies } from "./cookie";
|
|
15
|
-
import type { LiteralString } from "./helper";
|
|
15
|
+
import type { Awaitable, LiteralString } from "./helper";
|
|
16
16
|
import type {
|
|
17
17
|
BetterAuthOptions,
|
|
18
18
|
BetterAuthRateLimitOptions,
|
|
19
19
|
} from "./init-options";
|
|
20
20
|
import type { BetterAuthPlugin } from "./plugin";
|
|
21
|
+
import type { SecretConfig } from "./secret";
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* @internal
|
|
25
|
+
*/
|
|
26
|
+
type InferPluginID<O extends BetterAuthOptions> =
|
|
27
|
+
O["plugins"] extends Array<infer P>
|
|
28
|
+
? P extends BetterAuthPlugin
|
|
29
|
+
? P["id"]
|
|
30
|
+
: never
|
|
31
|
+
: never;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* @internal
|
|
35
|
+
*/
|
|
36
|
+
type InferPluginOptions<
|
|
37
|
+
O extends BetterAuthOptions,
|
|
38
|
+
ID extends BetterAuthPluginRegistryIdentifier | LiteralString,
|
|
39
|
+
> =
|
|
40
|
+
O["plugins"] extends Array<infer P>
|
|
41
|
+
? P extends BetterAuthPlugin
|
|
42
|
+
? P["id"] extends ID
|
|
43
|
+
? P extends { options: infer O }
|
|
44
|
+
? O
|
|
45
|
+
: never
|
|
46
|
+
: never
|
|
47
|
+
: never
|
|
48
|
+
: never;
|
|
21
49
|
|
|
22
50
|
/**
|
|
23
51
|
* Mutators are defined in each plugin
|
|
24
52
|
*
|
|
25
53
|
* @example
|
|
26
54
|
* ```ts
|
|
55
|
+
* interface MyPluginOptions {
|
|
56
|
+
* useFeature: boolean
|
|
57
|
+
* }
|
|
58
|
+
*
|
|
59
|
+
* const createMyPlugin = <Options extends MyPluginOptions>(options?: Options) => ({
|
|
60
|
+
* id: 'my-plugin',
|
|
61
|
+
* options,
|
|
62
|
+
* } satisfies BetterAuthPlugin);
|
|
63
|
+
*
|
|
27
64
|
* declare module "@better-auth/core" {
|
|
28
|
-
* interface BetterAuthPluginRegistry<
|
|
29
|
-
* '
|
|
30
|
-
* creator: typeof
|
|
65
|
+
* interface BetterAuthPluginRegistry<AuthOptions, Options> {
|
|
66
|
+
* 'my-plugin': {
|
|
67
|
+
* creator: Options extends MyPluginOptions ? typeof createMyPlugin<Options>: typeof createMyPlugin
|
|
31
68
|
* }
|
|
32
69
|
* }
|
|
33
70
|
* }
|
|
34
71
|
* ```
|
|
35
72
|
*/
|
|
36
73
|
// biome-ignore lint/correctness/noUnusedVariables: Auth and Context is used in the declaration merging
|
|
37
|
-
export interface BetterAuthPluginRegistry<
|
|
74
|
+
export interface BetterAuthPluginRegistry<AuthOptions, Options> {}
|
|
38
75
|
export type BetterAuthPluginRegistryIdentifier = keyof BetterAuthPluginRegistry<
|
|
39
76
|
unknown,
|
|
40
77
|
unknown
|
|
@@ -67,7 +104,10 @@ export interface InternalAdapter<
|
|
|
67
104
|
T,
|
|
68
105
|
): Promise<T & Account>;
|
|
69
106
|
|
|
70
|
-
listSessions(
|
|
107
|
+
listSessions(
|
|
108
|
+
userId: string,
|
|
109
|
+
options?: { onlyActiveSessions?: boolean | undefined } | undefined,
|
|
110
|
+
): Promise<Session[]>;
|
|
71
111
|
|
|
72
112
|
listUsers(
|
|
73
113
|
limit?: number | undefined,
|
|
@@ -94,6 +134,11 @@ export interface InternalAdapter<
|
|
|
94
134
|
|
|
95
135
|
findSessions(
|
|
96
136
|
sessionTokens: string[],
|
|
137
|
+
options?:
|
|
138
|
+
| {
|
|
139
|
+
onlyActiveSessions?: boolean | undefined;
|
|
140
|
+
}
|
|
141
|
+
| undefined,
|
|
97
142
|
): Promise<{ session: Session; user: User }[]>;
|
|
98
143
|
|
|
99
144
|
updateSession(
|
|
@@ -183,12 +228,21 @@ type CheckPasswordFn<Options extends BetterAuthOptions = BetterAuthOptions> = (
|
|
|
183
228
|
ctx: GenericEndpointContext<Options>,
|
|
184
229
|
) => Promise<boolean>;
|
|
185
230
|
|
|
186
|
-
export type PluginContext = {
|
|
187
|
-
getPlugin: <
|
|
231
|
+
export type PluginContext<Options extends BetterAuthOptions> = {
|
|
232
|
+
getPlugin: <
|
|
233
|
+
ID extends BetterAuthPluginRegistryIdentifier | LiteralString,
|
|
234
|
+
PluginOptions extends InferPluginOptions<Options, ID>,
|
|
235
|
+
>(
|
|
188
236
|
pluginId: ID,
|
|
189
237
|
) =>
|
|
190
238
|
| (ID extends BetterAuthPluginRegistryIdentifier
|
|
191
|
-
?
|
|
239
|
+
? BetterAuthPluginRegistry<Options, PluginOptions>[ID] extends {
|
|
240
|
+
creator: infer C;
|
|
241
|
+
}
|
|
242
|
+
? C extends (...args: any[]) => infer R
|
|
243
|
+
? R
|
|
244
|
+
: never
|
|
245
|
+
: never
|
|
192
246
|
: BetterAuthPlugin)
|
|
193
247
|
| null;
|
|
194
248
|
/**
|
|
@@ -206,7 +260,7 @@ export type PluginContext = {
|
|
|
206
260
|
*/
|
|
207
261
|
hasPlugin: <ID extends BetterAuthPluginRegistryIdentifier | LiteralString>(
|
|
208
262
|
pluginId: ID,
|
|
209
|
-
) => boolean;
|
|
263
|
+
) => ID extends InferPluginID<Options> ? true : boolean;
|
|
210
264
|
};
|
|
211
265
|
|
|
212
266
|
export type InfoContext = {
|
|
@@ -216,10 +270,15 @@ export type InfoContext = {
|
|
|
216
270
|
};
|
|
217
271
|
|
|
218
272
|
export type AuthContext<Options extends BetterAuthOptions = BetterAuthOptions> =
|
|
219
|
-
PluginContext &
|
|
273
|
+
PluginContext<Options> &
|
|
220
274
|
InfoContext & {
|
|
221
275
|
options: Options;
|
|
222
276
|
trustedOrigins: string[];
|
|
277
|
+
/**
|
|
278
|
+
* Resolved list of trusted providers for account linking.
|
|
279
|
+
* Populated from "account.accountLinking.trustedProviders" (supports static array or async function).
|
|
280
|
+
*/
|
|
281
|
+
trustedProviders: string[];
|
|
223
282
|
/**
|
|
224
283
|
* Verifies whether url is a trusted origin according to the "trustedOrigins" configuration
|
|
225
284
|
* @param url The url to verify against the "trustedOrigins" configuration
|
|
@@ -281,6 +340,7 @@ export type AuthContext<Options extends BetterAuthOptions = BetterAuthOptions> =
|
|
|
281
340
|
internalAdapter: InternalAdapter<Options>;
|
|
282
341
|
createAuthCookie: CreateCookieGetterFn;
|
|
283
342
|
secret: string;
|
|
343
|
+
secretConfig: string | SecretConfig;
|
|
284
344
|
sessionConfig: {
|
|
285
345
|
updateAge: number;
|
|
286
346
|
expiresIn: number;
|
|
@@ -341,7 +401,7 @@ export type AuthContext<Options extends BetterAuthOptions = BetterAuthOptions> =
|
|
|
341
401
|
* This is inferred from the `options.advanced?.backgroundTasks?.handler` option.
|
|
342
402
|
* Defaults to a no-op that just runs the promise.
|
|
343
403
|
*/
|
|
344
|
-
runInBackground: (promise: Promise<
|
|
404
|
+
runInBackground: (promise: Promise<unknown>) => void;
|
|
345
405
|
/**
|
|
346
406
|
* Runs a task in the background if `runInBackground` is configured,
|
|
347
407
|
* otherwise awaits the task directly.
|
|
@@ -351,6 +411,6 @@ export type AuthContext<Options extends BetterAuthOptions = BetterAuthOptions> =
|
|
|
351
411
|
* mitigation), but still ensure the operation completes.
|
|
352
412
|
*/
|
|
353
413
|
runInBackgroundOrAwait: (
|
|
354
|
-
promise: Promise<unknown> |
|
|
355
|
-
) =>
|
|
414
|
+
promise: Promise<unknown> | void,
|
|
415
|
+
) => Awaitable<unknown>;
|
|
356
416
|
};
|
package/src/types/helper.ts
CHANGED
|
@@ -8,6 +8,7 @@ export type Primitive =
|
|
|
8
8
|
| undefined;
|
|
9
9
|
|
|
10
10
|
export type Awaitable<T> = T | Promise<T>;
|
|
11
|
+
export type AwaitableFunction<T> = T | (() => Awaitable<T>);
|
|
11
12
|
export type LiteralString = "" | (string & Record<never, never>);
|
|
12
13
|
export type LiteralUnion<LiteralType, BaseType extends Primitive> =
|
|
13
14
|
| LiteralType
|
|
@@ -16,3 +17,11 @@ export type LiteralUnion<LiteralType, BaseType extends Primitive> =
|
|
|
16
17
|
export type Prettify<T> = {
|
|
17
18
|
[K in keyof T]: T[K];
|
|
18
19
|
} & {};
|
|
20
|
+
|
|
21
|
+
export type UnionToIntersection<U> = (
|
|
22
|
+
U extends any
|
|
23
|
+
? (k: U) => void
|
|
24
|
+
: never
|
|
25
|
+
) extends (k: infer I) => void
|
|
26
|
+
? I
|
|
27
|
+
: never;
|