[GH-ISSUE #4039] Duplicate accounts can be created via sign-up requests (email+password) #27129

Closed
opened 2026-04-17 17:57:24 -05:00 by GiteaMirror · 4 comments
Owner

Originally created by @ikemHood on GitHub (Aug 16, 2025).
Original GitHub issue: https://github.com/better-auth/better-auth/issues/4039

To Reproduce

  1. Spin up a backend with Better Auth and MongoDB adapter (minimal config below).
  2. Enable emailAndPassword with email verification (default OTP email flow).
  3. From a client or script, send 2+ concurrent POST requests to the email sign-up endpoint (e.g., /api/v1/auth/sign-up/email) using the same email within a very short window (tens of milliseconds).
  4. Observe that multiple user documents are created in the database for the same email, or that two sign-up flows both report success.

Reproduction payload (example):

{
  "name": "John Deo",
  "email": "JohnDeo@yopmail.com",
  "password": "Jhon1234Deo",
  "roles": "SME",
  "image": "",
  "callbackURL": "",
  "rememberMe": true
}

Current vs. Expected behavior

  • Current: When two sign-up requests for the same email arrive nearly simultaneously, multiple users can be created (duplicate accounts) or the system proceeds with duplicated sign-up states.
  • Expected: The second (and subsequent) concurrent request(s) should be rejected (e.g., 409 Conflict), or deduplicated/serialized so that only a single user record exists per email.

What version of Better Auth are you using?

better-auth@^1.3.6

System info

Output of npx envinfo --system --browsers (omitted here; reproducible in typical Node 18+/Bun envs with MongoDB). Happy to provide if needed.

Which area(s) are affected?

  • Backend
  • Package
  • Types (indirectly if constraints are expected at type level)

Auth config (if applicable)

Minimal reproduction based on our setup (MongoDB adapter + email/password + email OTP):

import { betterAuth } from "better-auth";
import { mongodbAdapter } from "better-auth/adapters/mongodb";
import { emailOTP } from "better-auth/plugins";
import { MongoClient } from "mongodb";

const client = new MongoClient(process.env.MONGODB_URI!);

export const auth = betterAuth({
  database: mongodbAdapter(client.db(process.env.DATABASE_NAME!)),
  appName: "ReproApp",

  plugins: [
    emailOTP({
      overrideDefaultEmailVerification: true,
      async sendVerificationOTP({ email, otp, type }) {
        // send email with OTP (omitted)
      },
    }),
  ],

  emailAndPassword: {
    enabled: true,
    requireEmailVerification: true,
  },

  // default session/settings otherwise
});

Sign-up endpoint used (Better Auth default handler): POST /api/v1/auth/sign-up/email with JSON body shown above.

Additional context

  • We log OTP issuance and see multiple OTPs issued when duplicate requests are fired concurrently.
  • DB: MongoDB 6+, adapter better-auth/adapters/mongodb.
  • Expectation is that Better Auth should guard against duplicate account creation by enforcing a unique constraint at the application layer and/or within adapter transaction/atomic upsert semantics.
  • If the intended pattern is to rely on a unique index at the DB level and propagate a 409, please confirm recommended schema/index config for adapters so that the library returns a stable error code.

Happy to provide a small repo and logs if needed.

Originally created by @ikemHood on GitHub (Aug 16, 2025). Original GitHub issue: https://github.com/better-auth/better-auth/issues/4039 ### To Reproduce 1. Spin up a backend with Better Auth and MongoDB adapter (minimal config below). 2. Enable `emailAndPassword` with email verification (default OTP email flow). 3. From a client or script, send 2+ concurrent POST requests to the email sign-up endpoint (e.g., `/api/v1/auth/sign-up/email`) using the same email within a very short window (tens of milliseconds). 4. Observe that multiple user documents are created in the database for the same email, or that two sign-up flows both report success. Reproduction payload (example): ```json { "name": "John Deo", "email": "JohnDeo@yopmail.com", "password": "Jhon1234Deo", "roles": "SME", "image": "", "callbackURL": "", "rememberMe": true } ``` ### Current vs. Expected behavior - Current: When two sign-up requests for the same email arrive nearly simultaneously, multiple users can be created (duplicate accounts) or the system proceeds with duplicated sign-up states. - Expected: The second (and subsequent) concurrent request(s) should be rejected (e.g., 409 Conflict), or deduplicated/serialized so that only a single user record exists per email. ### What version of Better Auth are you using? `better-auth@^1.3.6` ### System info Output of `npx envinfo --system --browsers` (omitted here; reproducible in typical Node 18+/Bun envs with MongoDB). Happy to provide if needed. ### Which area(s) are affected? - Backend - Package - Types (indirectly if constraints are expected at type level) ### Auth config (if applicable) Minimal reproduction based on our setup (MongoDB adapter + email/password + email OTP): ```ts import { betterAuth } from "better-auth"; import { mongodbAdapter } from "better-auth/adapters/mongodb"; import { emailOTP } from "better-auth/plugins"; import { MongoClient } from "mongodb"; const client = new MongoClient(process.env.MONGODB_URI!); export const auth = betterAuth({ database: mongodbAdapter(client.db(process.env.DATABASE_NAME!)), appName: "ReproApp", plugins: [ emailOTP({ overrideDefaultEmailVerification: true, async sendVerificationOTP({ email, otp, type }) { // send email with OTP (omitted) }, }), ], emailAndPassword: { enabled: true, requireEmailVerification: true, }, // default session/settings otherwise }); ``` Sign-up endpoint used (Better Auth default handler): `POST /api/v1/auth/sign-up/email` with JSON body shown above. ### Additional context - We log OTP issuance and see multiple OTPs issued when duplicate requests are fired concurrently. - DB: MongoDB 6+, adapter `better-auth/adapters/mongodb`. - Expectation is that Better Auth should guard against duplicate account creation by enforcing a unique constraint at the application layer and/or within adapter transaction/atomic upsert semantics. - If the intended pattern is to rely on a unique index at the DB level and propagate a 409, please confirm recommended schema/index config for adapters so that the library returns a stable error code. Happy to provide a small repo and logs if needed.
GiteaMirror added the lockedbug labels 2026-04-17 17:57:24 -05:00
Author
Owner

@dosubot[bot] commented on GitHub (Aug 16, 2025):

Hi @ikemHood! I'm Dosu and I’m helping the better-auth team.

Better Auth v1.3.6 with the MongoDB adapter does not prevent duplicate user accounts when concurrent sign-up requests are made with the same email. The sign-up flow checks for an existing user before creating a new one, but this check is not atomic, so race conditions can result in duplicate accounts if two requests happen nearly simultaneously. There is no explicit locking or transaction to serialize these requests, and the unique: true option in the adapter config does not create a unique index in MongoDB.

To reliably prevent duplicates, you should manually create a unique index on the email field in your MongoDB user collection. For example, you can run:

db.users.createIndex({ email: 1 }, { unique: true, name: "user_email_key" })

This ensures that only one user document per email can exist, even under high concurrency. If a duplicate is attempted, MongoDB will throw a duplicate key error. Currently, Better Auth does not map this error to a 409 Conflict; it returns a generic "FAILED_TO_CREATE_USER" error with a 422 status. You may want to catch this error in your API layer and translate it to a 409 Conflict for clarity.

This approach is confirmed as the recommended pattern for deduplication in concurrent sign-up scenarios with Better Auth and MongoDB citation.

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other  Chat with Dosu Join Discord Share on X

<!-- gh-comment-id:3193450348 --> @dosubot[bot] commented on GitHub (Aug 16, 2025): <!-- Greeting --> Hi @ikemHood! I'm [Dosu](https://go.dosu.dev/dosubot) and I’m helping the better-auth team. <!-- Answer --> Better Auth v1.3.6 with the MongoDB adapter does not prevent duplicate user accounts when concurrent sign-up requests are made with the same email. The sign-up flow checks for an existing user before creating a new one, but this check is not atomic, so race conditions can result in duplicate accounts if two requests happen nearly simultaneously. There is no explicit locking or transaction to serialize these requests, and the `unique: true` option in the adapter config does not create a unique index in MongoDB. To reliably prevent duplicates, you should manually create a unique index on the `email` field in your MongoDB user collection. For example, you can run: ```js db.users.createIndex({ email: 1 }, { unique: true, name: "user_email_key" }) ``` This ensures that only one user document per email can exist, even under high concurrency. If a duplicate is attempted, MongoDB will throw a duplicate key error. Currently, Better Auth does not map this error to a 409 Conflict; it returns a generic "FAILED_TO_CREATE_USER" error with a 422 status. You may want to catch this error in your API layer and translate it to a 409 Conflict for clarity. This approach is confirmed as the recommended pattern for deduplication in concurrent sign-up scenarios with Better Auth and MongoDB [citation](https://github.com/better-auth/better-auth/issues/247#issuecomment-2423857228). <!-- Dosu Comment Footer --> *To reply, just mention [@dosu](https://go.dosu.dev/dosubot).* --- <sup>How did I do? [Good](https://app.dosu.dev/response-feedback/939d9ea2-ba72-4d1c-a868-530e1d0690b8?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/939d9ea2-ba72-4d1c-a868-530e1d0690b8?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/939d9ea2-ba72-4d1c-a868-530e1d0690b8?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/939d9ea2-ba72-4d1c-a868-530e1d0690b8?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/939d9ea2-ba72-4d1c-a868-530e1d0690b8?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/939d9ea2-ba72-4d1c-a868-530e1d0690b8?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/939d9ea2-ba72-4d1c-a868-530e1d0690b8?feedback_type=other)</sup>&nbsp;&nbsp;[![Chat with Dosu](https://dosu.dev/dosu-chat-badge.svg)](https://app.dosu.dev/cdda13d9-dd27-4d31-b09a-5d8bec92de21/ask?utm_source=github)&nbsp;[![Join Discord](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&label=)](https://go.dosu.dev/discord-bot)&nbsp;[![Share on X](https://img.shields.io/badge/X-share-black)](https://twitter.com/intent/tweet?text=%40dosu_ai%20helped%20me%20solve%20this%20issue!&url=https%3A//github.com/better-auth/better-auth/issues/4039)
Author
Owner

@iamsg97 commented on GitHub (Aug 16, 2025):

So as per the above explanation, this is not a bug?
I am wondering is it worth giving a shot, or not!

<!-- gh-comment-id:3193656378 --> @iamsg97 commented on GitHub (Aug 16, 2025): So as per the above explanation, this is not a `bug`? I am wondering is it worth giving a shot, or not!
Author
Owner

@ikemHood commented on GitHub (Aug 16, 2025):

Happens even when the request are not concurrent.

<!-- gh-comment-id:3193668538 --> @ikemHood commented on GitHub (Aug 16, 2025): Happens even when the request are not concurrent.
Author
Owner

@dosubot[bot] commented on GitHub (Nov 15, 2025):

Hi, @ikemHood. I'm Dosu, and I'm helping the better-auth team manage their backlog and am marking this issue as stale.

Issue Summary:

  • You reported that Better Auth v1.3.6 with the MongoDB adapter can create duplicate user accounts when multiple sign-up requests with the same email occur, even without concurrency.
  • The root cause is a non-atomic check before user creation combined with the lack of a unique index on the email field by default in MongoDB.
  • The recommended workaround is to manually create a unique index on the email field to prevent duplicates.
  • Better Auth currently returns a generic error on duplicates rather than a 409 Conflict response.
  • The issue has been acknowledged and the resolution approach is documented.

Next Steps:

  • Please confirm if this issue is still relevant with the latest version of better-auth.
  • If it is, you can keep the discussion open by commenting here; otherwise, I will automatically close this issue in 7 days.

Thank you for your understanding and contribution!

<!-- gh-comment-id:3536634117 --> @dosubot[bot] commented on GitHub (Nov 15, 2025): Hi, @ikemHood. I'm [Dosu](https://dosu.dev), and I'm helping the better-auth team manage their backlog and am marking this issue as stale. **Issue Summary:** - You reported that Better Auth v1.3.6 with the MongoDB adapter can create duplicate user accounts when multiple sign-up requests with the same email occur, even without concurrency. - The root cause is a non-atomic check before user creation combined with the lack of a unique index on the email field by default in MongoDB. - The recommended workaround is to manually create a unique index on the email field to prevent duplicates. - Better Auth currently returns a generic error on duplicates rather than a 409 Conflict response. - The issue has been acknowledged and the resolution approach is documented. **Next Steps:** - Please confirm if this issue is still relevant with the latest version of better-auth. - If it is, you can keep the discussion open by commenting here; otherwise, I will automatically close this issue in 7 days. Thank you for your understanding and contribution!
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#27129