[GH-ISSUE #4065] Questions on phone number verification #18450

Closed
opened 2026-04-15 16:54:02 -05:00 by GiteaMirror · 5 comments
Owner

Originally created by @matthewnaples on GitHub (Aug 18, 2025).
Original GitHub issue: https://github.com/better-auth/better-auth/issues/4065

Hello, it seems like there are a few things that seem vague to me in the docs related to phone number authentication.

  1. I'm wondering why you can sign up without a password using the phone number plugin, but when signing in you need to provide a password? You can pass the signUpOnVerification and a user will be created without them having to set a password, but when you call authClient.signIn.phoneNumber(...), you are required to provide a password. I would expect that, if you can sign up without a password, you can use the phone number verification to sign in with a password. maybe this is already handled depending on question 2

  2. When passing thesignUpOnVerification argument, if the given user exists, will it throw an error saying something like "user already exists"? Will it silently create a duplicate user? Or will it find the user and log them in by creating a session (assuming you don't disable the session)? If it does find the user and log them in, are they identified by their phone number or by their temp email?

Thanks for the help!

Originally created by @matthewnaples on GitHub (Aug 18, 2025). Original GitHub issue: https://github.com/better-auth/better-auth/issues/4065 Hello, it seems like there are a few things that seem vague to me in the docs related to phone number authentication. 1. I'm wondering why you can sign up without a password using the phone number plugin, but when signing in you need to provide a password? You can pass the signUpOnVerification and a user will be created without them having to set a password, but when you call `authClient.signIn.phoneNumber(...)`, you are required to provide a password. I would expect that, if you can sign up without a password, you can use the phone number verification to sign in with a password. maybe this is already handled depending on question 2 2. When passing the`signUpOnVerification` argument, if the given user exists, will it throw an error saying something like "user already exists"? Will it silently create a duplicate user? Or will it find the user and log them in by creating a session (assuming you don't disable the session)? If it does find the user and log them in, are they identified by their phone number or by their temp email? Thanks for the help!
GiteaMirror added the locked label 2026-04-15 16:54:02 -05:00
Author
Owner

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

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

Here’s what’s happening with phone number authentication in Better Auth:

You can sign up without a password using the phone number plugin because the signUpOnVerification option creates a user with a temporary email and marks their phone number as verified. This flow is designed for quick onboarding via OTP, but it does not set a password for the user. When you try to sign in with authClient.signIn.phoneNumber, a password is required because the sign-in endpoint checks for a credential account and verifies the password before creating a session. If the user never set a password, sign-in will fail until they do. Passwordless sign-in via phone number and OTP is not supported by default—sign-in always requires a password for credential-based accounts. If you want users to sign in with a password after phone verification, you’ll need to let them set a password after they’ve signed up and verified their phone number. Docs and code, source.

When you use signUpOnVerification, if the user already exists, the system does not throw an error or create a duplicate. Instead, it updates the existing user to set phoneNumberVerified to true and creates a session (unless you disable session creation). The user is identified internally by their user ID, but the phone number is stored as a unique field and is the key identifier for phone number authentication. The temporary email is used for sign-up, but the phone number is what matters for authentication and lookup. Docs, test evidence.

If you want users to set a password after phone verification, you can prompt them to do so once their session is created. This enables credential-based sign-in with their phone number and password going forward.

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:3196294776 --> @dosubot[bot] commented on GitHub (Aug 18, 2025): <!-- Greeting --> Hi @matthewnaples! I'm [Dosu](https://go.dosu.dev/dosubot) and I’m helping the better-auth team. <!-- Answer --> Here’s what’s happening with phone number authentication in Better Auth: You can sign up without a password using the phone number plugin because the `signUpOnVerification` option creates a user with a temporary email and marks their phone number as verified. This flow is designed for quick onboarding via OTP, but it does not set a password for the user. When you try to sign in with `authClient.signIn.phoneNumber`, a password is required because the sign-in endpoint checks for a credential account and verifies the password before creating a session. If the user never set a password, sign-in will fail until they do. Passwordless sign-in via phone number and OTP is not supported by default—sign-in always requires a password for credential-based accounts. If you want users to sign in with a password after phone verification, you’ll need to let them set a password after they’ve signed up and verified their phone number. [Docs and code](https://better-auth.com/docs/plugins/phone-number), [source](https://github.com/better-auth/better-auth/blob/efa60af1c2d45a735ed397171bfca513b7e202ca/packages/better-auth/src/plugins/phone-number/index.ts). When you use `signUpOnVerification`, if the user already exists, the system does not throw an error or create a duplicate. Instead, it updates the existing user to set `phoneNumberVerified` to true and creates a session (unless you disable session creation). The user is identified internally by their user ID, but the phone number is stored as a unique field and is the key identifier for phone number authentication. The temporary email is used for sign-up, but the phone number is what matters for authentication and lookup. [Docs](https://better-auth.com/docs/plugins/phone-number), [test evidence](https://github.com/better-auth/better-auth/blob/efa60af1c2d45a735ed397171bfca513b7e202ca/packages/better-auth/src/plugins/phone-number/phone-number.test.ts). If you want users to set a password after phone verification, you can prompt them to do so once their session is created. This enables credential-based sign-in with their phone number and password going forward. <!-- 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/dc4539c8-46a3-4f64-89b5-dc56491909b5?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/dc4539c8-46a3-4f64-89b5-dc56491909b5?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/dc4539c8-46a3-4f64-89b5-dc56491909b5?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/dc4539c8-46a3-4f64-89b5-dc56491909b5?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/dc4539c8-46a3-4f64-89b5-dc56491909b5?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/dc4539c8-46a3-4f64-89b5-dc56491909b5?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/dc4539c8-46a3-4f64-89b5-dc56491909b5?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/4065)
Author
Owner

@matthewnaples commented on GitHub (Aug 18, 2025):

Alright, I just experimented a bit. The bot comment above is probably misleading.

My goal was to build a passwordless login where users can sign in / sign up with phone number and OTP only. They shouldn't need to be on a dedicated sign-up or sign-in page, as the decision to sign up or sign in can be inferred based on the user's presence in the db.

To facilitate this I just added the signUpOnVerification to the endpoint, and that is the only thing you need. You don't need to call the signIn method in this setup. signUpOnVerification will know when it needs to sign a user up + create a session, or just create the session for the existing user.

I have not tested out what happens when I update a user's email and try again. There's a chance the process tries to identify a user by email but I assume it will work as expected.

<!-- gh-comment-id:3197462103 --> @matthewnaples commented on GitHub (Aug 18, 2025): Alright, I just experimented a bit. The bot comment above is probably misleading. My goal was to build a passwordless login where users can sign in / sign up with phone number and OTP only. They shouldn't need to be on a dedicated sign-up or sign-in page, as the decision to sign up or sign in can be inferred based on the user's presence in the db. To facilitate this I just added the signUpOnVerification to the endpoint, and that is the only thing you need. You don't need to call the signIn method in this setup. signUpOnVerification will know when it needs to sign a user up + create a session, or just create the session for the existing user. I have not tested out what happens when I update a user's email and try again. There's a chance the process tries to identify a user by email but I assume it will work as expected.
Author
Owner

@SushiiReboot commented on GitHub (Aug 19, 2025):

The docs do explain this.

Why do I need a password to sign in if I signed up via phone number (OTP)?

That’s because there are two separate flows:

Flow Description
OTP flow sendOtp → verify — used to sign in without a password (creates a session after verification)
Credential flow signIn.phoneNumber({ phoneNumber, password }) — only for users that already have a password

So if a user was created via signUpOnVerification, they should continue using the OTP flow (i.e. send → verify) to log in.
The signIn.phoneNumber(...) method is only for accounts that specifically use “phone number + password” as credentials.


What happens if I pass signUpOnVerification and the user already exists?

It will not create a duplicate.

When the phone number already exists:

  • It sends the OTP
  • Verifies it
  • Logs in the existing user (and creates a session unless disableSession is set to true)

So in that case, the flow acts as “sign in via phone number + OTP”, not sign-up.

So basically: the user is looked up by phone number and the temporary email is not used for identification (it’s only used when creating a brand-new user)

<!-- gh-comment-id:3202280683 --> @SushiiReboot commented on GitHub (Aug 19, 2025): The docs do explain this. ### Why do I need a password to sign in if I signed up via phone number (OTP)? That’s because there are **two separate flows**: | Flow | Description | |------|--------------------------------------------------------------| | **OTP flow** | `sendOtp → verify` — used to sign in without a password (creates a session after verification) | | **Credential flow** | `signIn.phoneNumber({ phoneNumber, password })` — only for users that already have a password | So if a user was created via `signUpOnVerification`, they **should continue using the OTP flow** (i.e. send → verify) to log in. The `signIn.phoneNumber(...)` method is only for accounts that *specifically* use “phone number + password” as credentials. --- ### What happens if I pass `signUpOnVerification` and the user already exists? It will **not** create a duplicate. When the phone number already exists: - It sends the OTP - Verifies it - Logs in the existing user (and creates a session unless `disableSession` is set to true) So in that case, the flow acts as **“sign in via phone number + OTP”**, not sign-up. So basically: the user is looked up by **phone number** and the temporary email is *not* used for identification (it’s only used when creating a brand-new user)
Author
Owner

@matthewnaples commented on GitHub (Aug 19, 2025):

Thank you for clarification. Will close this issue 👍

<!-- gh-comment-id:3202289758 --> @matthewnaples commented on GitHub (Aug 19, 2025): Thank you for clarification. Will close this issue 👍
Author
Owner

@ermais commented on GitHub (Oct 29, 2025):

ERROR [Better Auth]: Credential account not found { phoneNumber: Got this erorr after send Otp and verify the user, try to sign in phone. I have requested password reset it sent me otp and provided that otp and got success but It doesn't set the password. so when I try to sign in phone and password throw that error any help, I have actuallly use direct api end point for mobile applicaiton level.

<!-- gh-comment-id:3462923004 --> @ermais commented on GitHub (Oct 29, 2025): ERROR [Better Auth]: Credential account not found { phoneNumber: Got this erorr after send Otp and verify the user, try to sign in phone. I have requested password reset it sent me otp and provided that otp and got success but It doesn't set the password. so when I try to sign in phone and password throw that error any help, I have actuallly use direct api end point for mobile applicaiton level.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#18450