The twoFactorRedirect does not specify TOTP or OTP #1742

Closed
opened 2026-03-13 09:00:07 -05:00 by GiteaMirror · 14 comments
Owner

Originally created by @stefandevo on GitHub (Aug 20, 2025).

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

My user can enable TOTP then twoFactorRedirect will be true and I have to validate using the verifyTotp method. However, if the user want OTP always through SMS or Email I need to manually use sendOTP and use verifyOtp but how can I now from the login result what the user preference is. Of course I use the sendOTP as a fallback if the user don't have the authenticator app, but what if he don't use authenticator app and always wants the sendOTP to be done. How should we setup this

Current vs. Expected behavior

Able to know TOTP or OTP setup

What version of Better Auth are you using?

1.x.x

System info

-

Which area(s) are affected? (Select all that apply)

Client

Auth config (if applicable)

import { betterAuth } from "better-auth"
export const auth = betterAuth({
  emailAndPassword: {  
    enabled: true
  },

});

Additional context

No response

Originally created by @stefandevo on GitHub (Aug 20, 2025). ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce My user can enable TOTP then twoFactorRedirect will be true and I have to validate using the verifyTotp method. However, if the user want OTP always through SMS or Email I need to manually use sendOTP and use verifyOtp but how can I now from the login result what the user preference is. Of course I use the sendOTP as a fallback if the user don't have the authenticator app, but what if he don't use authenticator app and always wants the sendOTP to be done. How should we setup this ### Current vs. Expected behavior Able to know TOTP or OTP setup ### What version of Better Auth are you using? 1.x.x ### System info ```bash - ``` ### Which area(s) are affected? (Select all that apply) Client ### Auth config (if applicable) ```typescript import { betterAuth } from "better-auth" export const auth = betterAuth({ emailAndPassword: { enabled: true }, }); ``` ### Additional context _No response_
GiteaMirror added the enhancement label 2026-03-13 09:00:07 -05:00
Author
Owner

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

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

You're correct—Better Auth's twoFactorRedirect only signals that 2FA is required, but it doesn't specify whether TOTP or OTP (SMS/Email) is expected or preferred by the user. This is by design: the core framework manages 2FA via plugins, but doesn't track or expose the user's 2FA method preference in the login response or session. Both TOTP and OTP can be enabled or disabled via plugin config, but the distinction isn't surfaced automatically in the client flow or API response (docs, code).

To support user preference (e.g., always use OTP), you'll need to manage this at the application layer. The typical approach is to add a custom field to your user model (like preferred2faMethod: 'totp' | 'otp') and set it based on user choice during 2FA setup. After login, when you receive twoFactorRedirect: true, fetch the user's preference and route them to the correct verification flow (verifyTotp or sendOTP/verifyOtp). If you want to fallback to OTP when TOTP isn't set up, check for the presence of a TOTP secret or similar flag in your user data.

There's no built-in way to detect or enforce this preference in Better Auth 1.x.x, so this logic needs to be handled in your integration. You can disable either TOTP or OTP globally via plugin options if you want to restrict available methods (discussion).

To reply, just mention @dosu.


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

@dosubot[bot] commented on GitHub (Aug 20, 2025): <!-- Greeting --> Hi @stefandevo! I'm [Dosu](https://go.dosu.dev/dosubot) and I’m helping the better-auth team. <!-- Answer --> You're correct—Better Auth's twoFactorRedirect only signals that 2FA is required, but it doesn't specify whether TOTP or OTP (SMS/Email) is expected or preferred by the user. This is by design: the core framework manages 2FA via plugins, but doesn't track or expose the user's 2FA method preference in the login response or session. Both TOTP and OTP can be enabled or disabled via plugin config, but the distinction isn't surfaced automatically in the client flow or API response ([docs](https://better-auth.com/docs/plugins/2fa), [code](https://github.com/better-auth/better-auth/blob/4472f679f09697d6743470cb58c4d4ee32eaa5f0/packages/better-auth/src/plugins/two-factor/index.ts)). To support user preference (e.g., always use OTP), you'll need to manage this at the application layer. The typical approach is to add a custom field to your user model (like `preferred2faMethod: 'totp' | 'otp'`) and set it based on user choice during 2FA setup. After login, when you receive twoFactorRedirect: true, fetch the user's preference and route them to the correct verification flow (verifyTotp or sendOTP/verifyOtp). If you want to fallback to OTP when TOTP isn't set up, check for the presence of a TOTP secret or similar flag in your user data. There's no built-in way to detect or enforce this preference in Better Auth 1.x.x, so this logic needs to be handled in your integration. You can disable either TOTP or OTP globally via plugin options if you want to restrict available methods ([discussion](https://github.com/better-auth/better-auth/issues/409#issuecomment-2505323783)). <!-- 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/1b2a3eb2-8492-4000-9359-04a17388cf24?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/1b2a3eb2-8492-4000-9359-04a17388cf24?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/1b2a3eb2-8492-4000-9359-04a17388cf24?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/1b2a3eb2-8492-4000-9359-04a17388cf24?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/1b2a3eb2-8492-4000-9359-04a17388cf24?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/1b2a3eb2-8492-4000-9359-04a17388cf24?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/1b2a3eb2-8492-4000-9359-04a17388cf24?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/4101)
Author
Owner

@stefandevo commented on GitHub (Aug 20, 2025):

@dosu ok clear, I can add this into the user model, but upon login we should receive that value because we can't do a fetch of the user's preference because we are not authenticated yet. So is it possible to pass this info with the login result?

@stefandevo commented on GitHub (Aug 20, 2025): @dosu ok clear, I can add this into the user model, but upon login we should receive that value because we can't do a fetch of the user's preference because we are not authenticated yet. So is it possible to pass this info with the login result?
Author
Owner

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

Better Auth doesn't include the user's 2FA method preference (like TOTP vs OTP) in the login result by default. Even if you add a custom field (e.g., preferred2faMethod) to your user model, it won't automatically appear in the login response—you have to manually add it in the sign-in endpoint handler. This means you need to modify the login response code to include your custom field from the user object if you want it available before full authentication is complete (source).

For example, after fetching the user in your sign-in handler, you could do:

return ctx.json({
  // ...other fields
  user: {
    id: user.user.id,
    email: user.user.email,
    // ...other fields
    preferred2faMethod: user.user.preferred2faMethod, // <-- add this
  },
});

There are no hooks or plugins that automate this; it must be done explicitly in your handler code (docs). If you use OIDC, you can customize user info claims with a function, but that's specific to OIDC flows and not the core login response.

Just be sure only to expose non-sensitive preference data in the login result for privacy and security.

To reply, just mention @dosu.


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

@dosubot[bot] commented on GitHub (Aug 20, 2025): <!-- Answer --> Better Auth doesn't include the user's 2FA method preference (like TOTP vs OTP) in the login result by default. Even if you add a custom field (e.g., preferred2faMethod) to your user model, it won't automatically appear in the login response—you have to manually add it in the sign-in endpoint handler. This means you need to modify the login response code to include your custom field from the user object if you want it available before full authentication is complete ([source](https://github.com/better-auth/better-auth/blob/4472f679f09697d6743470cb58c4d4ee32eaa5f0/packages/better-auth/src/api/routes/sign-in.ts)). For example, after fetching the user in your sign-in handler, you could do: ```ts return ctx.json({ // ...other fields user: { id: user.user.id, email: user.user.email, // ...other fields preferred2faMethod: user.user.preferred2faMethod, // <-- add this }, }); ``` There are no hooks or plugins that automate this; it must be done explicitly in your handler code ([docs](https://github.com/better-auth/better-auth/blob/4472f679f09697d6743470cb58c4d4ee32eaa5f0/docs/content/docs/reference/options.mdx)). If you use OIDC, you can customize user info claims with a function, but that's specific to OIDC flows and not the core login response. Just be sure only to expose non-sensitive preference data in the login result for privacy and security. <!-- 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/c1453abf-b2ba-4599-89b0-c8100f70e778?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/c1453abf-b2ba-4599-89b0-c8100f70e778?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/c1453abf-b2ba-4599-89b0-c8100f70e778?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/c1453abf-b2ba-4599-89b0-c8100f70e778?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/c1453abf-b2ba-4599-89b0-c8100f70e778?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/c1453abf-b2ba-4599-89b0-c8100f70e778?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/c1453abf-b2ba-4599-89b0-c8100f70e778?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/4101)
Author
Owner

@stefandevo commented on GitHub (Aug 20, 2025):

@dosu not sure where this handler code resides, or do you mean I have to change the plugin to support this, ref "it must be done explicitly in your handler code" Can you give me an example how to do this in my server code?

@stefandevo commented on GitHub (Aug 20, 2025): @dosu not sure where this handler code resides, or do you mean I have to change the plugin to support this, ref "it must be done explicitly in your handler code" Can you give me an example how to do this in my server code?
Author
Owner

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

You don't need to change any plugin code—just your server/API route handler that returns the login response. In Better Auth, the handler code for sign-in lives in your server-side API route (for example, in a Next.js or Remix route, or in the core handler at packages/better-auth/src/api/routes/sign-in.ts).

To include a custom field like preferred2faMethod in the login response, make sure your user model has that field, and then add it to the response object in your handler. For example, in the sign-in handler:

return ctx.json({
  redirect: !!ctx.body.callbackURL,
  token: session.token,
  url: ctx.body.callbackURL,
  user: {
    id: user.user.id,
    email: user.user.email,
    name: user.user.name,
    image: user.user.image,
    emailVerified: user.user.emailVerified,
    createdAt: user.user.createdAt,
    updatedAt: user.user.updatedAt,
    preferred2faMethod: user.user.preferred2faMethod, // <-- add this line
  },
});

This way, your client will receive the user's 2FA preference in the login result and can route to the correct verification flow. No plugin changes are needed—just update your handler code where you construct the login response.

To reply, just mention @dosu.


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

@dosubot[bot] commented on GitHub (Aug 20, 2025): <!-- Answer --> You don't need to change any plugin code—just your server/API route handler that returns the login response. In Better Auth, the handler code for sign-in lives in your server-side API route (for example, in a Next.js or Remix route, or in the core handler at [`packages/better-auth/src/api/routes/sign-in.ts`](https://github.com/better-auth/better-auth/blob/4472f679f09697d6743470cb58c4d4ee32eaa5f0/packages/better-auth/src/api/routes/sign-in.ts)). To include a custom field like `preferred2faMethod` in the login response, make sure your user model has that field, and then add it to the response object in your handler. For example, in the sign-in handler: ```ts return ctx.json({ redirect: !!ctx.body.callbackURL, token: session.token, url: ctx.body.callbackURL, user: { id: user.user.id, email: user.user.email, name: user.user.name, image: user.user.image, emailVerified: user.user.emailVerified, createdAt: user.user.createdAt, updatedAt: user.user.updatedAt, preferred2faMethod: user.user.preferred2faMethod, // <-- add this line }, }); ``` This way, your client will receive the user's 2FA preference in the login result and can route to the correct verification flow. No plugin changes are needed—just update your handler code where you construct the login response. <!-- 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/bb9f1d44-c15f-404e-8d0a-a37d91da6146?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/bb9f1d44-c15f-404e-8d0a-a37d91da6146?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/bb9f1d44-c15f-404e-8d0a-a37d91da6146?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/bb9f1d44-c15f-404e-8d0a-a37d91da6146?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/bb9f1d44-c15f-404e-8d0a-a37d91da6146?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/bb9f1d44-c15f-404e-8d0a-a37d91da6146?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/bb9f1d44-c15f-404e-8d0a-a37d91da6146?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/4101)
Author
Owner

@stefandevo commented on GitHub (Aug 20, 2025):

@dosu - Ok, so we are using Tanstack Start (https://www.better-auth.com/docs/integrations/tanstack) so you mean we need to override this code:

import { auth } from '@/lib/auth' // import your auth instance
import { createServerFileRoute } from '@tanstack/react-start/server'
 
export const ServerRoute = createServerFileRoute('/api/auth/$').methods({
  GET: ({ request }) => {
    return auth.handler(request)
  },
  POST: ({ request }) => {
    return auth.handler(request)
  },
})

is this correct?

@stefandevo commented on GitHub (Aug 20, 2025): @dosu - Ok, so we are using Tanstack Start (https://www.better-auth.com/docs/integrations/tanstack) so you mean we need to override this code: ``` import { auth } from '@/lib/auth' // import your auth instance import { createServerFileRoute } from '@tanstack/react-start/server' export const ServerRoute = createServerFileRoute('/api/auth/$').methods({ GET: ({ request }) => { return auth.handler(request) }, POST: ({ request }) => { return auth.handler(request) }, }) ``` is this correct?
Author
Owner

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

You don't need to override the Tanstack Start route code itself. The standard pattern is to delegate requests to auth.handler(request) in your route, as in your example. To include custom fields like preferred2faMethod in the login response, you need to customize the handler logic that constructs the response—typically in your sign-in handler or user serialization logic, not in the route mounting code. There’s no built-in extension point for modifying the response directly in the Tanstack Start route; you’d need to update the handler that generates the login response to include your custom field before it’s returned to the client. The route code stays the same, but the handler’s output must be customized upstream reference.

To reply, just mention @dosu.


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

@dosubot[bot] commented on GitHub (Aug 20, 2025): <!-- Answer --> You don't need to override the Tanstack Start route code itself. The standard pattern is to delegate requests to auth.handler(request) in your route, as in your example. To include custom fields like preferred2faMethod in the login response, you need to customize the handler logic that constructs the response—typically in your sign-in handler or user serialization logic, not in the route mounting code. There’s no built-in extension point for modifying the response directly in the Tanstack Start route; you’d need to update the handler that generates the login response to include your custom field before it’s returned to the client. The route code stays the same, but the handler’s output must be customized upstream [reference](https://better-auth.com/docs/integrations/remix). <!-- 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/74b6143f-3da2-4e6d-84c0-866e5de247b3?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/74b6143f-3da2-4e6d-84c0-866e5de247b3?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/74b6143f-3da2-4e6d-84c0-866e5de247b3?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/74b6143f-3da2-4e6d-84c0-866e5de247b3?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/74b6143f-3da2-4e6d-84c0-866e5de247b3?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/74b6143f-3da2-4e6d-84c0-866e5de247b3?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/74b6143f-3da2-4e6d-84c0-866e5de247b3?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/4101)
Author
Owner

@stefandevo commented on GitHub (Aug 20, 2025):

I don't see a hook where I would be able to send the custom setting field after the login; tried to check the hooks but don't see it appearing. Checked the source and I don't see any option here. So can we have a feature for this?

@stefandevo commented on GitHub (Aug 20, 2025): I don't see a hook where I would be able to send the custom setting field after the login; tried to check the hooks but don't see it appearing. Checked the source and I don't see any option here. So can we have a feature for this?
Author
Owner

@stefandevo commented on GitHub (Aug 25, 2025):

Would be happy to create a PR for this, but if I see the 270 open PR's I am not confident if it will ever be accepted :-)
@dosu what is the reason for so many open PRs?

@stefandevo commented on GitHub (Aug 25, 2025): Would be happy to create a PR for this, but if I see the 270 open PR's I am not confident if it will ever be accepted :-) @dosu what is the reason for so many open PRs?
Author
Owner

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

There isn’t an official explanation from the maintainers about the high number of open PRs in better-auth. From what’s visible, many PRs are marked as “PROPOSED CHANGES ONLY” and remain open for extended periods, including both recent and older contributions. This pattern suggests that PRs may be awaiting review, further changes, or maintainer action, but there’s no public info about how PRs are prioritized or managed (example PR).

In open source projects, large PR backlogs often result from limited maintainer bandwidth, prioritization challenges, or process bottlenecks. If you do submit a PR, making sure it’s well-documented, clearly scoped, and addresses a specific need can help maximize its chances of review. It’s a good idea to watch for any future updates from maintainers about project activity or PR management.

To reply, just mention @dosu.


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

@dosubot[bot] commented on GitHub (Aug 25, 2025): <!-- Answer --> There isn’t an official explanation from the maintainers about the high number of open PRs in better-auth. From what’s visible, many PRs are marked as “PROPOSED CHANGES ONLY” and remain open for extended periods, including both recent and older contributions. This pattern suggests that PRs may be awaiting review, further changes, or maintainer action, but there’s no public info about how PRs are prioritized or managed ([example PR](https://github.com/better-auth/better-auth/pull/3694)). In open source projects, large PR backlogs often result from limited maintainer bandwidth, prioritization challenges, or process bottlenecks. If you do submit a PR, making sure it’s well-documented, clearly scoped, and addresses a specific need can help maximize its chances of review. It’s a good idea to watch for any future updates from maintainers about project activity or PR management. <!-- 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/499f9a78-85b1-4d7a-be25-bcb2ddc9e969?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/499f9a78-85b1-4d7a-be25-bcb2ddc9e969?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/499f9a78-85b1-4d7a-be25-bcb2ddc9e969?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/499f9a78-85b1-4d7a-be25-bcb2ddc9e969?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/499f9a78-85b1-4d7a-be25-bcb2ddc9e969?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/499f9a78-85b1-4d7a-be25-bcb2ddc9e969?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/499f9a78-85b1-4d7a-be25-bcb2ddc9e969?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/4101)
Author
Owner

@pauldmps commented on GitHub (Oct 9, 2025):

@dosu I am using NestJs with @thallesp/nestjs-better-auth, I am facing similar problem. I want to show the last 4 digits of user's phone number where the OTP is being sent to. How do I achieve this? I obviously don't want to expose the entire phone number before the user is logged in.

@pauldmps commented on GitHub (Oct 9, 2025): @dosu I am using NestJs with @thallesp/nestjs-better-auth, I am facing similar problem. I want to show the last 4 digits of user's phone number where the OTP is being sent to. How do I achieve this? I obviously don't want to expose the entire phone number before the user is logged in.
Author
Owner

@boardy commented on GitHub (Nov 6, 2025):

I feel this is a bit of an oversight for the library. I've been migrating my projects from Next Auth over to Better Auth and it takes a lot of the burden away from the developer by doing a lot of the requests and lookups itself and returning responses back to the developer to perform a particular action, unlike Next auth when you have to do alot yourself. It seems very strange, that the 2FA plugin doesn't provide any way to tell what 2FA method was used and need to implement this manually yourself. Be great if something could be added in a future release.

@boardy commented on GitHub (Nov 6, 2025): I feel this is a bit of an oversight for the library. I've been migrating my projects from Next Auth over to Better Auth and it takes a lot of the burden away from the developer by doing a lot of the requests and lookups itself and returning responses back to the developer to perform a particular action, unlike Next auth when you have to do alot yourself. It seems very strange, that the 2FA plugin doesn't provide any way to tell what 2FA method was used and need to implement this manually yourself. Be great if something could be added in a future release.
Author
Owner

@dosubot[bot] commented on GitHub (Feb 5, 2026):

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

Issue Summary:

  • You raised a concern about the twoFactorRedirect flag not indicating whether TOTP or OTP (SMS/Email) is required, making it unclear how to detect the user's preferred 2FA method after login.
  • The current design requires managing 2FA preferences in the user model and customizing the login response handler to expose this information.
  • You requested guidance on implementing this with Tanstack Start integration and were advised to modify the sign-in handler logic.
  • You also requested a native feature or hook in Better Auth to support this functionality, which community members noted as a notable gap compared to other auth libraries.
  • The issue remains unresolved with no native support added yet.

Next Steps:

  • Please let me know if this issue is still relevant with the latest version of Better Auth by commenting here to keep the discussion open.
  • Otherwise, this issue will be automatically closed in 7 days.

Thank you for your understanding and contribution!

@dosubot[bot] commented on GitHub (Feb 5, 2026): Hi, @stefandevo. 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 raised a concern about the `twoFactorRedirect` flag not indicating whether TOTP or OTP (SMS/Email) is required, making it unclear how to detect the user's preferred 2FA method after login. - The current design requires managing 2FA preferences in the user model and customizing the login response handler to expose this information. - You requested guidance on implementing this with Tanstack Start integration and were advised to modify the sign-in handler logic. - You also requested a native feature or hook in Better Auth to support this functionality, which community members noted as a notable gap compared to other auth libraries. - The issue remains unresolved with no native support added yet. **Next Steps:** - Please let me know if this issue is still relevant with the latest version of Better Auth by commenting here to keep the discussion open. - Otherwise, this issue will be automatically closed in 7 days. Thank you for your understanding and contribution!
Author
Owner

@kvanbere commented on GitHub (Mar 5, 2026):

Yeah this is a big issue. It's unreasonably difficult to figure out which OTP method was used and therefore know which UX to show the user during login.

@kvanbere commented on GitHub (Mar 5, 2026): Yeah this is a big issue. It's [unreasonably difficult](https://github.com/better-auth/better-auth/discussions/8411) to figure out which OTP method was used and therefore know which UX to show the user during login.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#1742