From 07efd2578848fb8c3d2b0e0778c2059f912e5af1 Mon Sep 17 00:00:00 2001 From: Kinfe123 Date: Sun, 13 Apr 2025 16:40:12 +0300 Subject: [PATCH 1/6] fix: username empty field on update guard --- .../src/plugins/username/error-codes.ts | 1 + .../better-auth/src/plugins/username/index.ts | 18 +++++++++++++----- .../src/plugins/username/username.test.ts | 1 + 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/packages/better-auth/src/plugins/username/error-codes.ts b/packages/better-auth/src/plugins/username/error-codes.ts index 659b7be056..0fdbddecb1 100644 --- a/packages/better-auth/src/plugins/username/error-codes.ts +++ b/packages/better-auth/src/plugins/username/error-codes.ts @@ -6,4 +6,5 @@ export const USERNAME_ERROR_CODES = { USERNAME_TOO_SHORT: "username is too short", USERNAME_TOO_LONG: "username is too long", INVALID_USERNAME: "username is invalid", + USERNAME_IS_EMPTY: "username is empty", }; diff --git a/packages/better-auth/src/plugins/username/index.ts b/packages/better-auth/src/plugins/username/index.ts index aa884fa8fd..7134c08fa0 100644 --- a/packages/better-auth/src/plugins/username/index.ts +++ b/packages/better-auth/src/plugins/username/index.ts @@ -97,7 +97,7 @@ export const username = (options?: UsernameOptions) => { const minUsernameLength = options?.minUsernameLength || 3; const maxUsernameLength = options?.maxUsernameLength || 30; - + console.log("Username", ctx.body.username) if (ctx.body.username.length < minUsernameLength) { ctx.context.logger.error("Username too short", { username: ctx.body.username, @@ -118,13 +118,11 @@ export const username = (options?: UsernameOptions) => { const validator = options?.usernameValidator || defaultUsernameValidator; - - if (!validator(ctx.body.username)) { + if (ctx.body.username.length === 0 || !validator(ctx.body.username)) { throw new APIError("UNPROCESSABLE_ENTITY", { message: ERROR_CODES.INVALID_USERNAME, }); } - const user = await ctx.context.adapter.findOne< User & { username: string } >({ @@ -235,7 +233,12 @@ export const username = (options?: UsernameOptions) => { }, handler: createAuthMiddleware(async (ctx) => { const username = ctx.body.username; +<<<<<<< HEAD if (username !== undefined && typeof username === "string") { +======= + console.log({ username }) + if (username) { +>>>>>>> 526b6398 (fix: username empty field on update guard) const minUsernameLength = options?.minUsernameLength || 3; const maxUsernameLength = options?.maxUsernameLength || 30; if (username.length < minUsernameLength) { @@ -252,7 +255,6 @@ export const username = (options?: UsernameOptions) => { const validator = options?.usernameValidator || defaultUsernameValidator; - const valid = await validator(username); if (!valid) { throw new APIError("UNPROCESSABLE_ENTITY", { @@ -273,6 +275,12 @@ export const username = (options?: UsernameOptions) => { message: ERROR_CODES.USERNAME_IS_ALREADY_TAKEN, }); } + } else { + if (typeof username === "string" ) { + throw new APIError("UNPROCESSABLE_ENTITY", { + message: ERROR_CODES.USERNAME_IS_EMPTY, + }); + } } }), }, diff --git a/packages/better-auth/src/plugins/username/username.test.ts b/packages/better-auth/src/plugins/username/username.test.ts index 6fc9684663..aaab2ccf48 100644 --- a/packages/better-auth/src/plugins/username/username.test.ts +++ b/packages/better-auth/src/plugins/username/username.test.ts @@ -9,6 +9,7 @@ describe("username", async (it) => { plugins: [ username({ minUsernameLength: 4, + maxUsernameLength: 20, }), ], }, From 913fe8f4deda081e8a65e20a7da10ce7c6fdd6ec Mon Sep 17 00:00:00 2001 From: Kinfe123 Date: Mon, 14 Apr 2025 07:56:09 +0300 Subject: [PATCH 2/6] fix: docs on oauth refresh token fn --- docs/content/docs/concepts/oauth.mdx | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/content/docs/concepts/oauth.mdx b/docs/content/docs/concepts/oauth.mdx index 1bee2ffffe..632e8956b9 100644 --- a/docs/content/docs/concepts/oauth.mdx +++ b/docs/content/docs/concepts/oauth.mdx @@ -5,13 +5,13 @@ description: How Better Auth handles OAuth Better Auth comes with built-in support for OAuth 2.0 and OpenID Connect. This allows you to authenticate users via popular OAuth providers like Google, Facebook, GitHub, and more. -If your desired provider isn’t directly supported, you can use the [Generic OAuth Plugin](/docs/plugins/generic-oauth) for custom integrations. +If your desired provider isn't directly supported, you can use the [Generic OAuth Plugin](/docs/plugins/generic-oauth) for custom integrations. ## Configuring Social Providers To enable a social provider, you need to provide `clientId` and `clientSecret` for the provider. -Here’s an example of how to configure Google as a provider: +Here's an example of how to configure Google as a provider: ```ts title="auth.ts" import { betterAuth } from "better-auth"; @@ -37,17 +37,17 @@ export const auth = betterAuth({ **disableSignUp:** Disables sign-up for new users. -**disableIdTokenSignIn:** Disables the use of the ID token for sign-in. By default, it’s enabled for some providers like Google and Apple. +**disableIdTokenSignIn:** Disables the use of the ID token for sign-in. By default, it's enabled for some providers like Google and Apple. **verifyIdToken** A custom function to verify the ID token. -**getUserInfo** A custom function to fetch user information from the provider. Given the tokens returned from the provider, this function should return the user’s information. +**getUserInfo** A custom function to fetch user information from the provider. Given the tokens returned from the provider, this function should return the user's information. **mapProfileToUser** A custom function to map the user profile returned from the provider to the user object in your database. -**refreshAccessToken**: A custom function to refresh the token. Given the default implementation, you can provide a custom function to refresh the token. +**refreshAccessToken**: A custom function to refresh the token. This feature is only supported for built-in social providers (Google, Facebook, GitHub, etc.) and is not currently supported for custom OAuth providers configured through the Generic OAuth Plugin. For built-in providers, you can provide a custom function to refresh the token if needed. -Useful, if you have additional fields in your user object you want to populate from the provider’s profile. Or if you want to change how by default the user object is mapped. +Useful, if you have additio:nal fields in your user object you want to populate from the provider's profile. Or if you want to change how by default the user object is mapped. ```ts title="auth.ts" import { betterAuth } from "better-auth"; @@ -71,14 +71,14 @@ export const auth = betterAuth({ ## How OAuth Works in Better Auth -Here’s what happens when a user selects a provider to authenticate with: +Here's what happens when a user selects a provider to authenticate with: 1. **Configuration Check:** Ensure the necessary provider details (e.g., client ID, secret) are configured. 2. **State Generation:** Generate and save a state token in your database for CSRF protection. 3. **PKCE Support:** If applicable, create a PKCE code challenge and verifier for secure exchanges. -4. **Authorization URL Construction:** Build the provider’s authorization URL with parameters like client ID, redirect URI, state, etc. The callback URL usually follows the pattern `/api/auth/callback/${providerName}`. +4. **Authorization URL Construction:** Build the provider's authorization URL with parameters like client ID, redirect URI, state, etc. The callback URL usually follows the pattern `/api/auth/callback/${providerName}`. 5. **User Redirection:** - - If redirection is enabled, users are redirected to the provider’s login page. + - If redirection is enabled, users are redirected to the provider's login page. - If redirection is disabled, the authorization URL is returned for the client to handle the redirection. ### Post-Login Flow @@ -87,7 +87,7 @@ After the user completes the login process, the provider redirects them back to 1. **Token Exchange:** The code is exchanged for an access token and user information. 2. **User Handling:** - - If the user doesn’t exist, a new account is created. + - If the user doesn't exist, a new account is created. - If the user exists, they are logged in. - If the user has multiple accounts across providers, Better Auth links them based on your configuration. Learn more about [account linking](/docs/concepts/users-accounts#account-linking). 3. **Session Creation:** A new session is created for the user. From cd0eb1ba690677cafdd9de957475809d7fd6d450 Mon Sep 17 00:00:00 2001 From: Kinfe123 Date: Mon, 14 Apr 2025 08:02:40 +0300 Subject: [PATCH 3/6] merging with main --- .../src/plugins/username/error-codes.ts | 1 - .../better-auth/src/plugins/username/index.ts | 18 +++++------------- 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/packages/better-auth/src/plugins/username/error-codes.ts b/packages/better-auth/src/plugins/username/error-codes.ts index 0fdbddecb1..659b7be056 100644 --- a/packages/better-auth/src/plugins/username/error-codes.ts +++ b/packages/better-auth/src/plugins/username/error-codes.ts @@ -6,5 +6,4 @@ export const USERNAME_ERROR_CODES = { USERNAME_TOO_SHORT: "username is too short", USERNAME_TOO_LONG: "username is too long", INVALID_USERNAME: "username is invalid", - USERNAME_IS_EMPTY: "username is empty", }; diff --git a/packages/better-auth/src/plugins/username/index.ts b/packages/better-auth/src/plugins/username/index.ts index 7134c08fa0..d4f5df7a52 100644 --- a/packages/better-auth/src/plugins/username/index.ts +++ b/packages/better-auth/src/plugins/username/index.ts @@ -97,7 +97,7 @@ export const username = (options?: UsernameOptions) => { const minUsernameLength = options?.minUsernameLength || 3; const maxUsernameLength = options?.maxUsernameLength || 30; - console.log("Username", ctx.body.username) + if (ctx.body.username.length < minUsernameLength) { ctx.context.logger.error("Username too short", { username: ctx.body.username, @@ -118,11 +118,13 @@ export const username = (options?: UsernameOptions) => { const validator = options?.usernameValidator || defaultUsernameValidator; - if (ctx.body.username.length === 0 || !validator(ctx.body.username)) { + + if (!validator(ctx.body.username)) { throw new APIError("UNPROCESSABLE_ENTITY", { message: ERROR_CODES.INVALID_USERNAME, }); } + const user = await ctx.context.adapter.findOne< User & { username: string } >({ @@ -233,12 +235,7 @@ export const username = (options?: UsernameOptions) => { }, handler: createAuthMiddleware(async (ctx) => { const username = ctx.body.username; -<<<<<<< HEAD - if (username !== undefined && typeof username === "string") { -======= - console.log({ username }) if (username) { ->>>>>>> 526b6398 (fix: username empty field on update guard) const minUsernameLength = options?.minUsernameLength || 3; const maxUsernameLength = options?.maxUsernameLength || 30; if (username.length < minUsernameLength) { @@ -255,6 +252,7 @@ export const username = (options?: UsernameOptions) => { const validator = options?.usernameValidator || defaultUsernameValidator; + const valid = await validator(username); if (!valid) { throw new APIError("UNPROCESSABLE_ENTITY", { @@ -275,12 +273,6 @@ export const username = (options?: UsernameOptions) => { message: ERROR_CODES.USERNAME_IS_ALREADY_TAKEN, }); } - } else { - if (typeof username === "string" ) { - throw new APIError("UNPROCESSABLE_ENTITY", { - message: ERROR_CODES.USERNAME_IS_EMPTY, - }); - } } }), }, From 97ed4d6b0180e3c685ed9b5ca7073a5a30e21af4 Mon Sep 17 00:00:00 2001 From: Kinfe123 Date: Mon, 14 Apr 2025 08:05:22 +0300 Subject: [PATCH 4/6] merging with main --- packages/better-auth/src/plugins/username/index.ts | 4 ++-- packages/better-auth/src/plugins/username/username.test.ts | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/better-auth/src/plugins/username/index.ts b/packages/better-auth/src/plugins/username/index.ts index d4f5df7a52..f4f95fed1a 100644 --- a/packages/better-auth/src/plugins/username/index.ts +++ b/packages/better-auth/src/plugins/username/index.ts @@ -235,7 +235,7 @@ export const username = (options?: UsernameOptions) => { }, handler: createAuthMiddleware(async (ctx) => { const username = ctx.body.username; - if (username) { + if (username !== undefined && typeof username === "string") { const minUsernameLength = options?.minUsernameLength || 3; const maxUsernameLength = options?.maxUsernameLength || 30; if (username.length < minUsernameLength) { @@ -293,4 +293,4 @@ export const username = (options?: UsernameOptions) => { }, $ERROR_CODES: ERROR_CODES, } satisfies BetterAuthPlugin; -}; +}; \ No newline at end of file diff --git a/packages/better-auth/src/plugins/username/username.test.ts b/packages/better-auth/src/plugins/username/username.test.ts index aaab2ccf48..6fc9684663 100644 --- a/packages/better-auth/src/plugins/username/username.test.ts +++ b/packages/better-auth/src/plugins/username/username.test.ts @@ -9,7 +9,6 @@ describe("username", async (it) => { plugins: [ username({ minUsernameLength: 4, - maxUsernameLength: 20, }), ], }, From 755da99fb059a81e21a319be501d07cbcf1fd208 Mon Sep 17 00:00:00 2001 From: Kinfe123 Date: Mon, 14 Apr 2025 08:07:24 +0300 Subject: [PATCH 5/6] merging with main --- packages/better-auth/src/plugins/username/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/better-auth/src/plugins/username/index.ts b/packages/better-auth/src/plugins/username/index.ts index f4f95fed1a..aa884fa8fd 100644 --- a/packages/better-auth/src/plugins/username/index.ts +++ b/packages/better-auth/src/plugins/username/index.ts @@ -293,4 +293,4 @@ export const username = (options?: UsernameOptions) => { }, $ERROR_CODES: ERROR_CODES, } satisfies BetterAuthPlugin; -}; \ No newline at end of file +}; From 14f135bf413892e09b16dba6b06d07ad1f9a92b6 Mon Sep 17 00:00:00 2001 From: Kinfe123 Date: Mon, 14 Apr 2025 08:13:53 +0300 Subject: [PATCH 6/6] typo --- docs/content/docs/concepts/oauth.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/docs/concepts/oauth.mdx b/docs/content/docs/concepts/oauth.mdx index 632e8956b9..3ffcda3970 100644 --- a/docs/content/docs/concepts/oauth.mdx +++ b/docs/content/docs/concepts/oauth.mdx @@ -47,7 +47,7 @@ export const auth = betterAuth({ **refreshAccessToken**: A custom function to refresh the token. This feature is only supported for built-in social providers (Google, Facebook, GitHub, etc.) and is not currently supported for custom OAuth providers configured through the Generic OAuth Plugin. For built-in providers, you can provide a custom function to refresh the token if needed. -Useful, if you have additio:nal fields in your user object you want to populate from the provider's profile. Or if you want to change how by default the user object is mapped. +Useful, if you have additional fields in your user object you want to populate from the provider's profile. Or if you want to change how by default the user object is mapped. ```ts title="auth.ts" import { betterAuth } from "better-auth";