new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

Better Auth · Plugins · all subjects

two-factor plugin

36 notes, read out of this brain and free to use. Each one was extracted from a source and is re-checked against its exam.

Two-factor plugin: two main verification methods

The two-factor plugin offers two main methods for second factor verification: OTP (One-Time Password) — a temporary code sent to email or phone; and TOTP (Time-based One-Time Password) — a code generated by an authenticator app on the user's device.

Two-factor plugin: additional features

The two-factor plugin includes generating backup codes for account recovery, enabling and disabling 2FA, and managing trusted devices.

Two-factor plugin: server installation

To install the two-factor plugin on the server, import twoFactor from 'better-auth/plugins', add it to the plugins array in betterAuth config, and provide an appName which will be used as the TOTP issuer. Then run 'npx auth migrate' or 'npx auth generate' to add the necessary database tables and fields.

Two-factor plugin: client installation

To install the two-factor plugin on the client, import twoFactorClient from 'better-auth/client/plugins' and add it to the plugins array in createAuthClient.

Two-factor enable endpoint: POST /two-factor/enable

The endpoint POST /two-factor/enable accepts the following parameters: password (string, required for email/password accounts), method (string, 'otp' or 'totp', defaults to 'totp'), and issuer (string, custom issuer for TOTP URI, defaults to app name). Requires an active session. When method is 'totp', returns {method: 'totp', totpURI, backupCodes}. When method is 'otp', returns {method: 'otp'}.

Two-factor: TOTP enable defaults to requiring verification

When enabling 2FA with method 'totp', twoFactorEnabled remains false until the user verifies a TOTP code. The server plugin option skipVerificationOnEnable can be set to true to enable TOTP without enrollment-code verification.

Two-factor: OTP enable sets twoFactorEnabled immediately

When enabling 2FA with method 'otp', twoFactorEnabled is set to true immediately. This requires otpOptions.sendOTP to be configured on the server.

Two-factor: password requirement for enabling 2FA

By default, enabling 2FA requires a password. Users who signed up via OAuth, passkeys, magic links, or anonymous auth cannot enable 2FA unless allowPasswordless: true is set in the plugin config. The allowPasswordless option does not change which sign-in methods are challenged for 2FA.

Two-factor: sign-in response with 2FA enabled

When a user with 2FA enabled signs in via email, username, or phone number, the response contains twoFactorRedirect set to true and twoFactorMethods — an array of available 2FA methods for that user (e.g., ['totp'], ['totp', 'otp']).

Two-factor: sign-in endpoints enforcing 2FA

By default, 2FA sign-in enforcement applies to credential-based sign-in endpoints: /sign-in/email, /sign-in/username, and /sign-in/phone-number. Non-credential sign-in methods such as email OTP, magic link, OAuth/social, passkey, anonymous, and similar passwordless flows are not gated by 2FA by default.

Two-factor: sign-in with 2FA nulls out newSession

When a 2FA-enabled user signs in via a credential endpoint, the plugin issues a 2FA challenge instead of completing sign-in. The pending session is discarded and ctx.context.newSession is reset to null — there is no authenticated session until the user verifies the second factor. Server-side hooks reading ctx.context.newSession must null-check it before accessing newSession.user.

Two-factor: handling 2FA redirect with onSuccess callback

When calling authClient.signIn.email with a user who has 2FA enabled, use the onSuccess callback to check context.data.twoFactorRedirect and context.data.twoFactorMethods. If twoFactorRedirect is true, show the appropriate 2FA verification UI based on the available methods.

Two-factor client: twoFactorPage option

The twoFactorClient plugin accepts a twoFactorPage option specifying the page to redirect users to if they need to verify their 2nd factor. Using this option will cause a full page reload when redirecting.

Two-factor: server-side api.signInEmail with 2FA

When calling auth.api.signInEmail on the server and the user has 2FA enabled, the response will have twoFactorRedirect set to true. Check using the 'in' operator to determine if twoFactorRedirect is present. When using auth.api.* calls, pass returnHeaders: true to get response headers, and forward these headers into subsequent auth.api 2FA calls.

Two-factor disable endpoint: POST /two-factor/disable

The endpoint POST /two-factor/disable accepts an optional password parameter (required for credential accounts). Requires an active session. If allowPasswordless is enabled, the password can be omitted for users without a credential account.

TOTP algorithm and defaults in Better Auth

TOTP (Time-Based One-Time Password) is an algorithm that generates a unique password for each login attempt using time as a counter. Better Auth defaults to generating a new password every 30 seconds. TOTP generates codes offline on an authenticator app, making it secure and convenient.

Two-factor get TOTP URI endpoint: POST /two-factor/get-totp-uri

The endpoint POST /two-factor/get-totp-uri accepts an optional password parameter (required for credential accounts). Requires an active session. Returns the TOTP URI that can be used to generate a QR code for the user to scan with their authenticator app.

Two-factor OTP: configuration required before use

Before using OTP to verify the second factor, you must configure sendOTP in the twoFactor plugin options. This function is responsible for sending the OTP to the user's email, phone, or other method. The function signature is async sendOTP({ user, otp }, ctx).

Two-factor send OTP endpoint: POST /two-factor/send-otp

The endpoint POST /two-factor/send-otp accepts an optional trustDevice parameter (boolean, defaults to true, marks device as trusted for 30 days). Requires headers to be passed. Calling this function triggers the sendOTP implementation configured in Better Auth.

Two-factor verify OTP endpoint: POST /two-factor/verify-otp

The endpoint POST /two-factor/verify-otp accepts code (string, the OTP code to verify) and trustDevice (boolean, defaults to true, marks device as trusted for 30 days). Requires headers to be passed for Better Auth to read and set 2FA/session cookies.

Two-factor backup codes: purpose and behavior

Backup codes are generated and stored in the database for account recovery if the user loses access to their phone or email. When backup codes are generated, old backup codes are deleted and new ones are generated. Once a backup code is used, it is removed from the database and cannot be used again.

Two-factor generate backup codes endpoint: POST /two-factor/generate-backup-codes

The endpoint POST /two-factor/generate-backup-codes accepts an optional password parameter (required for credential accounts). Requires an active session. Returns backup codes that should be displayed to the user.

Two-factor verify backup code endpoint: POST /two-factor/verify-backup-code

The endpoint POST /two-factor/verify-backup-code accepts code (string, a backup code to verify), disableSession (boolean, defaults to false, prevents setting session cookie if true), and trustDevice (boolean, defaults to true, marks device as trusted for 30 days). Requires headers to be passed.

Two-factor view backup codes endpoint: POST /two-factor/view-backup-codes

The endpoint POST /two-factor/view-backup-codes is server-only and accepts an optional userId parameter (string or null). Returns the backup codes in the response. Should only be called if the user has a fresh session — a session that was just created.

Two-factor trusted devices: mechanism and duration

A device can be marked as trusted by passing trustDevice: true to verifyTotp or verifyOtp. When trusted, the device is remembered for 30 days, and the user won't be prompted for 2FA on subsequent sign-ins from that device. The trust period is refreshed on each successful sign-in within the 30-day window.

Two-factor TOTP issuer configuration

The issuer for TOTP is set to the app name provided in the auth config, or defaults to 'Better Auth' if not provided. The issuer is displayed in authenticator apps and can be overridden by passing issuer to the plugin config.

Two-factor database schema: user table field

The user table requires one additional field: twoFactorEnabled (boolean, optional) — indicates whether two factor authentication is enabled for the user.

Two-factor database schema: twoFactor table

A twoFactor table is required with the following fields: id (string, primary key, the ID of the two factor authentication), userId (string, foreign key referencing user.id), secret (string, the secret used to generate TOTP code), backupCodes (string, the backup codes for account recovery), verified (boolean, whether TOTP secret has been verified during enrollment), failedVerificationCount (number, consecutive failed second-factor verifications for account lockout), and lockedUntil (date, optional, when account lockout expires; null when not locked).

Two-factor plugin server options: basic configuration

Server options for twoFactor plugin include: twoFactorTable (string, name of table storing 2FA data, defaults to 'twoFactor'), issuer (string, custom issuer name for TOTP URI, defaults to appName), skipVerificationOnEnable (boolean, activate TOTP immediately without verifying enrollment code, defaults to false), and allowPasswordless (boolean, allow enabling/managing 2FA without password for users without credential account, defaults to false).

Two-factor TOTP options configuration

TOTP options include: digits (number, the number of digits in the OTP, defaults to 6) and period (number, the period for TOTP in seconds, defaults to 30).

Two-factor OTP options configuration

OTP options include: sendOTP (function, required, sends OTP to user's email or phone, takes parameters user and otp), period (number, the period for OTP in minutes, defaults to 3), and storeOTP (string, how to store OTP value — plain text, encrypted, or hashed, defaults to 'plain').

Two-factor backup code options configuration

Backup code options include: amount (number, number of backup codes to generate, defaults to 10), length (number, length of each backup code, defaults to 10), customBackupCodesGenerate (function, generates custom backup codes, takes no parameters and returns array of strings), and storeBackupCodes (string, how to store backup codes — plain text or encrypted, defaults to 'plain').

Two-factor account lockout options configuration

Account lockout options include: enabled (boolean, whether account-level lockout is enforced, defaults to true), maxFailedAttempts (number, consecutive failed verifications before lockout, defaults to 10), and durationSeconds (number, how long account stays locked in seconds, defaults to 900). The limit applies per account across sign-in challenges and across factors (TOTP, OTP, and backup codes share one counter). Locked attempts return 429 with ACCOUNT_TEMPORARILY_LOCKED error code.

Two-factor client plugin option: onTwoFactorRedirect

The twoFactorClient plugin accepts an onTwoFactorRedirect option, a callback that receives a context object containing twoFactorMethods (array of enabled 2FA methods, e.g., ['totp', 'otp']). This callback is invoked when the user needs to verify their 2FA code and can be used to redirect or handle 2FA verification.

Two-factor twoFactorPage full page reload warning

Using the twoFactorPage option in twoFactorClient will cause a full page reload when redirecting users to the two-factor authentication page. To avoid page reloads, use the onTwoFactorRedirect callback instead to handle the redirect programmatically.

Two-Factor Authentication plugin available

Better Auth includes a Two-Factor Authentication plugin that enhances app security with two-factor authentication.

Give your agent this brain