diff --git a/packages/better-auth/src/plugins/two-factor/index.ts b/packages/better-auth/src/plugins/two-factor/index.ts index f77eb29412..d79bb73164 100644 --- a/packages/better-auth/src/plugins/two-factor/index.ts +++ b/packages/better-auth/src/plugins/two-factor/index.ts @@ -441,7 +441,15 @@ export const twoFactor = (options?: O) => { }, ], }, - schema: mergeSchema(schema, options?.schema), + schema: mergeSchema(schema, { + ...options?.schema, + twoFactor: { + ...options?.schema?.twoFactor, + ...(options?.twoFactorTable + ? { modelName: options.twoFactorTable } + : {}), + }, + }), rateLimit: [ { pathMatcher(path) { diff --git a/packages/better-auth/src/plugins/two-factor/two-factor.test.ts b/packages/better-auth/src/plugins/two-factor/two-factor.test.ts index 5a5845eb25..dbc4963890 100644 --- a/packages/better-auth/src/plugins/two-factor/two-factor.test.ts +++ b/packages/better-auth/src/plugins/two-factor/two-factor.test.ts @@ -1394,6 +1394,45 @@ describe("twoFactorCookieMaxAge", async () => { }); }); +/** + * @see https://github.com/better-auth/better-auth/issues/8424 + */ +describe("twoFactorTable option", async () => { + const { auth, signInWithTestUser, testUser, db } = await getTestInstance({ + secret: DEFAULT_SECRET, + plugins: [ + twoFactor({ + twoFactorTable: "custom_two_factor", + skipVerificationOnEnable: true, + }), + ], + }); + + let { headers } = await signInWithTestUser(); + + it("should use custom table name for two factor data", async () => { + const enableRes = await auth.api.enableTwoFactor({ + body: { password: testUser.password }, + headers, + asResponse: true, + }); + expect(enableRes.status).toBe(200); + headers = convertSetCookieToCookie(enableRes.headers); + + const twoFactorRecord = await db.findOne({ + model: "twoFactor", + where: [ + { + field: "userId", + value: (await auth.api.getSession({ headers }))?.user.id as string, + }, + ], + }); + expect(twoFactorRecord).toBeDefined(); + expect(twoFactorRecord?.secret).toBeDefined(); + }); +}); + describe("OTP storage modes", async () => { describe("hashed OTP storage", async () => { let OTP = ""; diff --git a/packages/better-auth/src/plugins/two-factor/types.ts b/packages/better-auth/src/plugins/two-factor/types.ts index 2937a641a8..0d6d238710 100644 --- a/packages/better-auth/src/plugins/two-factor/types.ts +++ b/packages/better-auth/src/plugins/two-factor/types.ts @@ -10,6 +10,13 @@ export interface TwoFactorOptions { * Application Name */ issuer?: string | undefined; + /** + * The name of the table that stores the two factor + * authentication data. + * + * @default "twoFactor" + */ + twoFactorTable?: string | undefined; /** * TOTP OPtions */