[GH-ISSUE #8424] twoFactor plugin - "twoFactorTable" option to rename table does not work #28411

Closed
opened 2026-04-17 19:52:10 -05:00 by GiteaMirror · 1 comment
Owner

Originally created by @benlavalley on GitHub (Mar 5, 2026).
Original GitHub issue: https://github.com/better-auth/better-auth/issues/8424

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

  1. Setup better-auth to enable totp
  2. Register as a user with TOTP
  3. Login with that user with TOTP
  4. Update better-auth twoFactor plugin to specify the twoFactorTable as a different table name:
    twoFactor({ twoFactorTable: 'two_factor', ....
  5. Rename that table / collection in your db to the new name
  6. Restart better-auth
  7. Try to login with the user you created
  8. Observe you get an error 'TOTP not enabled'

Current vs. Expected behavior

Specifying the "twoFactorTable" option for the twoFactor plugin does not work for better-auth 1.5.1 - also appears would not work on current Canary either as of 3/5/26.

The documentation mentions it is how you should change the two factor table name here: "https://better-auth.com/docs/plugins/2fa" (see section 'twoFactorTable: The name of the table that stores the two factor authentication data. Default: twoFactor.').

Discovered this after trying to login with a user that had TOTP enabled and got an error that it was not enabled - I found that better-auth simply wasn't recognizing my newly designated table name (or in my case, Mongo collection).

Specifically the issues are:

  ```                                                                 
  1. packages/better-auth/src/plugins/two-factor/index.ts (line 62-64) — opts.twoFactorTable is hardcoded to "twoFactor" and never reads from options
  2. packages/better-auth/src/plugins/two-factor/totp/index.ts (line 80) — independent hardcoded const twoFactorTable = "twoFactor"
  3. packages/better-auth/src/plugins/two-factor/backup-codes/index.ts (line 172) — same independent hardcoded const twoFactorTable = "twoFactor"

It also seems that this option isnt present in the TwoFactorOptions type in packages/better-auth/src/plugins/two-factor/types.ts


### What version of Better Auth are you using?

1.5.1

### System info

```bash
{
  "system": {
    "platform": "darwin",
    "arch": "arm64",
    "version": "Darwin Kernel Version 25.3.0: Wed Jan 28 20:48:41 PST 2026; root:xnu-12377.81.4~5/RELEASE_ARM64_T6041",
    "release": "25.3.0",
    "cpuCount": 14,
    "cpuModel": "Apple M4 Max",
    "totalMemory": "36.00 GB",
    "freeMemory": "0.36 GB"
  },
  "node": {
    "version": "v22.22.0",
    "env": "development"
  },
  "packageManager": {
    "name": "npm",
    "version": "11.11.0"
  },
  "frameworks": [
    {
      "name": "vue",
      "version": "^3.5.29"
    },
    {
      "name": "nuxt",
      "version": "^4.3.1"
    }
  ],
  "databases": [
    {
      "name": "mongodb",
      "version": "^7.1.0"
    }
  ],
  "betterAuth": {
    "version": "^1.5.1",
    "config": null
  }
}

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

Documentation, Backend

Auth config (if applicable)

import { betterAuth } from "better-auth"
export const auth = betterAuth({
plugins: [
		twoFactor({
			twoFactorTable: 'two_factor',
		}),
	],
});

Additional context

Specifying the schema options for the twoFactor plugin does appear to allow you to remap the twoFactor table but I have not tested this extensively:

twoFactor({ schema: { twoFactor: { modelName: 'two_factor', }, },

Originally created by @benlavalley on GitHub (Mar 5, 2026). Original GitHub issue: https://github.com/better-auth/better-auth/issues/8424 ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce 1) Setup better-auth to enable totp 2) Register as a user with TOTP 3) Login with that user with TOTP 4) Update better-auth twoFactor plugin to specify the twoFactorTable as a different table name: ` twoFactor({ twoFactorTable: 'two_factor', ....` 5) Rename that table / collection in your db to the new name 6) Restart better-auth 7) Try to login with the user you created 8) Observe you get an error 'TOTP not enabled' ### Current vs. Expected behavior Specifying the "twoFactorTable" option for the twoFactor plugin does not work for better-auth 1.5.1 - also appears would not work on current Canary either as of 3/5/26. The documentation mentions it is how you should change the two factor table name here: "https://better-auth.com/docs/plugins/2fa" (see section 'twoFactorTable: The name of the table that stores the two factor authentication data. Default: twoFactor.'). Discovered this after trying to login with a user that had TOTP enabled and got an error that it was not enabled - I found that better-auth simply wasn't recognizing my newly designated table name (or in my case, Mongo collection). Specifically the issues are: ``` 1. packages/better-auth/src/plugins/two-factor/index.ts (line 62-64) — opts.twoFactorTable is hardcoded to "twoFactor" and never reads from options 2. packages/better-auth/src/plugins/two-factor/totp/index.ts (line 80) — independent hardcoded const twoFactorTable = "twoFactor" 3. packages/better-auth/src/plugins/two-factor/backup-codes/index.ts (line 172) — same independent hardcoded const twoFactorTable = "twoFactor" It also seems that this option isnt present in the TwoFactorOptions type in packages/better-auth/src/plugins/two-factor/types.ts ``` ### What version of Better Auth are you using? 1.5.1 ### System info ```bash { "system": { "platform": "darwin", "arch": "arm64", "version": "Darwin Kernel Version 25.3.0: Wed Jan 28 20:48:41 PST 2026; root:xnu-12377.81.4~5/RELEASE_ARM64_T6041", "release": "25.3.0", "cpuCount": 14, "cpuModel": "Apple M4 Max", "totalMemory": "36.00 GB", "freeMemory": "0.36 GB" }, "node": { "version": "v22.22.0", "env": "development" }, "packageManager": { "name": "npm", "version": "11.11.0" }, "frameworks": [ { "name": "vue", "version": "^3.5.29" }, { "name": "nuxt", "version": "^4.3.1" } ], "databases": [ { "name": "mongodb", "version": "^7.1.0" } ], "betterAuth": { "version": "^1.5.1", "config": null } } ``` ### Which area(s) are affected? (Select all that apply) Documentation, Backend ### Auth config (if applicable) ```typescript import { betterAuth } from "better-auth" export const auth = betterAuth({ plugins: [ twoFactor({ twoFactorTable: 'two_factor', }), ], }); ``` ### Additional context Specifying the schema options for the twoFactor plugin does appear to allow you to remap the twoFactor table but I have not tested this extensively: ` twoFactor({ schema: { twoFactor: { modelName: 'two_factor', }, },`
GiteaMirror added the lockedbug labels 2026-04-17 19:52:10 -05:00
Author
Owner

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

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

Your analysis is correct. The twoFactorTable option is indeed broken due to hardcoded values in multiple files:

  1. index.ts (lines 62-64) - The opts object hardcodes "twoFactor" and never reads from options?.twoFactorTable
  2. totp/index.ts (line 80) - Hardcoded const twoFactorTable = "twoFactor"
  3. backup-codes/index.ts (line 172) - Same hardcoded constant

Additionally, the TwoFactorOptions interface doesn't even define a twoFactorTable property, confirming this feature was never fully implemented.

This is part of a broader systemic issue with hardcoded table names across Better Auth that's being fixed incrementally.

Your workaround using schema.twoFactor.modelName is currently the only viable approach:

twoFactor({
  schema: {
    twoFactor: {
      modelName: 'two_factor',
    },
  },
})

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other

Chat with Dosu Open in Cursor Join Discord Share on X

<!-- gh-comment-id:4006926381 --> @dosubot[bot] commented on GitHub (Mar 5, 2026): <!-- Greeting --> Hi @benlavalley! I'm [Dosu](https://go.dosu.dev/dosubot) and I’m helping the better-auth team. <!-- Answer --> Your analysis is correct. The `twoFactorTable` option is indeed broken due to hardcoded values in multiple files: 1. **[index.ts (lines 62-64)](https://github.com/better-auth/better-auth/blob/c15f6d9c0addd4218077f38c13be51cc17b69b42/packages/better-auth/src/plugins/two-factor/index.ts#L62-L64)** - The `opts` object hardcodes `"twoFactor"` and never reads from `options?.twoFactorTable` 2. **[totp/index.ts (line 80)](https://github.com/better-auth/better-auth/blob/c15f6d9c0addd4218077f38c13be51cc17b69b42/packages/better-auth/src/plugins/two-factor/totp/index.ts#L80)** - Hardcoded `const twoFactorTable = "twoFactor"` 3. **[backup-codes/index.ts (line 172)](https://github.com/better-auth/better-auth/blob/c15f6d9c0addd4218077f38c13be51cc17b69b42/packages/better-auth/src/plugins/two-factor/backup-codes/index.ts#L172)** - Same hardcoded constant Additionally, the [TwoFactorOptions interface](https://github.com/better-auth/better-auth/blob/c15f6d9c0addd4218077f38c13be51cc17b69b42/packages/better-auth/src/plugins/two-factor/types.ts#L8-L50) doesn't even define a `twoFactorTable` property, confirming this feature was never fully implemented. This is part of a [broader systemic issue with hardcoded table names](https://github.com/better-auth/better-auth/issues/3774) across Better Auth that's being fixed incrementally. Your workaround using `schema.twoFactor.modelName` is currently the only viable approach: ```typescript twoFactor({ schema: { twoFactor: { modelName: 'two_factor', }, }, }) ``` <!-- 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/9788935a-6a0e-4480-9faa-73184a1c718e?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/9788935a-6a0e-4480-9faa-73184a1c718e?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/9788935a-6a0e-4480-9faa-73184a1c718e?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/9788935a-6a0e-4480-9faa-73184a1c718e?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/9788935a-6a0e-4480-9faa-73184a1c718e?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/9788935a-6a0e-4480-9faa-73184a1c718e?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/9788935a-6a0e-4480-9faa-73184a1c718e?feedback_type=other)</sup> [![Chat with Dosu](https://dosu.dev/dosu-chat-badge.svg)](https://app.dosu.dev/cdda13d9-dd27-4d31-b09a-5d8bec92de21/ask?utm_source=github)&nbsp;[![Open in Cursor](https://dosu.dev/dosu-in-cursor.svg)](https://cursor.com/link/prompt?text=Your%20analysis%20is%20correct.%20The%20%60twoFactorTable%60%20option%20is%20indeed%20broken%20due%20to%20hardcoded%20values%20in%20multiple%20files%3A%0A%0A1.%20%2A%2A%5Bindex.ts%20%28lines%2062-64%29%5D%28https%3A//github.com/better-auth/better-auth/blob/c15f6d9c0addd4218077f38c13be51cc17b69b42/packages/better-auth/src/plugins/two-factor/index.ts%23L62-L64%29%2A%2A%20-%20The%20%60opts%60%20object%20hardcodes%20%60%22twoFactor%22%60%20and%20never%20reads%20from%20%60options%3F.twoFactorTable%60%0A2.%20%2A%2A%5Btotp/index.ts%20%28line%2080%29%5D%28https%3A//github.com/better-auth/better-auth/blob/c15f6d9c0addd4218077f38c13be51cc17b69b42/packages/better-auth/src/plugins/two-factor/totp/index.ts%23L80%29%2A%2A%20-%20Hardcoded%20%60const%20twoFactorTable%20%3D%20%22twoFactor%22%60%0A3.%20%2A%2A%5Bbackup-codes/index.ts%20%28line%20172%29%5D%28https%3A//github.com/better-auth/better-auth/blob/c15f6d9c0addd4218077f38c13be51cc17b69b42/packages/better-auth/src/plugins/two-factor/backup-codes/index.ts%23L172%29%2A%2A%20-%20Same%20hardcoded%20constant%0A%0AAdditionally%2C%20the%20%5BTwoFactorOptions%20interface%5D%28https%3A//github.com/better-auth/better-auth/blob/c15f6d9c0addd4218077f38c13be51cc17b69b42/packages/better-auth/src/plugins/two-factor/types.ts%23L8-L50%29%20doesn%27t%20even%20define%20a%20%60twoFactorTable%60%20property%2C%20confirming%20this%20feature%20was%20never%20fully%20implemented.%0A%0AThis%20is%20part%20of%20a%20%5Bbroader%20systemic%20issue%20with%20hardcoded%20table%20names%5D%28https%3A//github.com/better-auth/better-auth/issues/3774%29%20across%20Better%20Auth%20that%27s%20being%20fixed%20incrementally.%0A%0AYour%20workaround%20using%20%60schema.twoFactor.modelName%60%20is%20currently%20the%20only%20viable%20approach%3A%0A%60%60%60typescript%0AtwoFactor%28%7B%0A%20%20schema%3A%20%7B%0A%20%20%20%20twoFactor%3A%20%7B%0A%20%20%20%20%20%20modelName%3A%20%27two_factor%27%2C%0A%20%20%20%20%7D%2C%0A%20%20%7D%2C%0A%7D%29%0A%60%60%60)&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/8424)
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#28411