Skills Plugins MCP Prompt Model 博客 我的中心
Lifestyle & Tools #security #email #ai

two-factor-authentication-best-practices

Configure TOTP authenticator apps, send OTP codes via email/SMS, manage backup codes, handle trusted devices, and implement 2FA sign-in flows using Better Auth's twoFactor plugin. Use when users need MFA, multi-factor authentication, authenticator setup, or login security with Better Auth.

DeepseekModel Curated skill Quality Excellent · 78 v1.0.0

Get

https://deepseekmodel.com/api/download.php?id=better-auth-skills-better-auth-twofactor-skill-md&format=skill
Download .skill Standard format with system_prompt and model_config, ready for any agent framework
The actual content of the system_prompt field in the .skill file.
name two-factor-authentication-best-practices description Configure TOTP authenticator apps, send OTP codes via email/SMS, manage backup codes, handle trusted devices, and implement 2FA sign-in flows using Better Auth's twoFactor plugin. Use when users need MFA, multi-factor authentication, authenticator setup, or login security with Better Auth. Setup Add twoFactor() plugin to server config with issuer Add twoFactorClient() plugin to client config Run npx auth@latest migrate (built-in adapter) or generate + push for Drizzle/Prisma Verify: check that twoFactorSecret column exists on user table import { betterAuth } from "better-auth" ; import { twoFactor } from "better-auth/plugins" ; export const auth = betterAuth ({ appName : "My App" , plugins : [ twoFactor ({ issuer : "My App" , }), ], }); Client-Side Setup import { createAuthClient } from "better-auth/client" ; import { twoFactorClient } from "better-auth/client/plugins" ; export const authClient = createAuthClient ({ plugins : [ twoFactorClient ({ onTwoFactorRedirect ( ) { window . location . href = "/2fa" ; }, }), ], }); Enabling 2FA for Users Requires password verification. Returns TOTP URI (for QR code) and backup codes. const enable2FA = async ( password : string ) => { const { data, error } = await authClient. twoFactor . enable ({ password, }); if (data) { // data.totpURI — generate a QR code from this // data.backupCodes — display to user } }; twoFactorEnabled is not set to true until first TOTP verification succeeds. Override with skipVerificationOnEnable: true (not recommended). TOTP (Authenticator App) Displaying the QR Code import QRCode from "react-qr-code" ; const TotpSetup = ( { totpURI }: { totpURI: string } ) => { return < QRCode value = {totpURI} /> ; }; Verifying TOTP Codes Accepts codes from one period before/after current time: const verifyTotp = async ( code : string ) => { const { data, error } = await authClient. twoFactor . verifyTotp ({ code, trustDevice : true , }); }; TOTP Configuration Options twoFactor ({ totpOptions : { digits : 6 , // 6 or 8 digits (default: 6) period : 30 , // Code validity period in seconds (default: 30) }, }); OTP (Email/SMS) Configuring OTP Delivery import { betterAuth } from "better-auth" ; import { twoFactor } from "better-auth/plugins" ; import { sendEmail } from "./email" ; export const auth = betterAuth ({ plugins : [ twoFactor ({ otpOptions : { sendOTP : async ({ user, otp }, ctx) => { await sendEmail ({ to : user. email , subject : "Your verification code" , text : `Your code is: ${otp} ` , }); }, period : 5 , // Code validity in minutes (default: 3) digits : 6 , // Number of digits (default: 6) allowedAttempts : 5 , // Max verification attempts (default: 5) }, }), ], }); Sending and Verifying OTP Send: authClient.twoFactor.sendOtp() . Verify: authClient.twoFactor.verifyOtp({ code, trustDevice: true }) . OTP Storage Security Configure how OTP codes are stored in the database: twoFactor ({ otpOptions : { storeOTP : "encrypted" , // Options: "plain", "encrypted", "hashed" }, }); For custom encryption: twoFactor ({ otpOptions : { storeOTP : { encrypt : async (token) => myEncrypt (token), decrypt : async (token) => myDecrypt (token), }, }, }); Backup Codes Generated automatically when 2FA is enabled. Each code is single-use. Displaying Backup Codes const BackupCodes = ( { codes }: { codes: string [] } ) => { return ( < div > < p > Save these codes in a secure location: </ p > < ul > {codes.map((code, i) => ( < li key = {i} > {code} </ li > ))} </ ul > </ div > ); }; Regenerating Backup Codes Invalidates all previous codes: const regenerateBackupCodes = async ( password : string ) => { const { data, error } = await authClient. twoFactor . generateBackupCodes ({ password, }); // data.backupCodes contains the new codes }; Using Backup Codes for Recovery const verifyBackupCode = async ( code : string ) => { const { data, error } = await authClient. twoFactor . verifyBackupCode ({ code, trustDevice : true , }); }; Backup Code Configuration twoFactor ({ backupCodeOptions : { amount : 10 , // Number of codes to generate (default: 10) length : 10 , // Length of each code (default: 10) storeBackupCodes : "encrypted" , // Options: "plain", "encrypted" }, }); Handling 2FA During Sign-In Response includes twoFactorRedirect: true when 2FA is required: Sign-In Flow Call signIn.email({ email, password }) Check context.data.twoFactorRedirect in onSuccess If true , redirect to /2fa verification page Verify via TOTP, OTP, or backup code Session cookie is created on successful verification const signIn = async ( email : string , password : string ) => { const { data, error } = await authClient. signIn . email ( { email, password }, { onSuccess ( context ) { if (context. data . twoFactorRedirect ) { window . location . href = "/2fa" ; } }, } ); }; Server-side: check "twoFactorRedirect" in response when using auth.api.signInEmail . Trusted Devices Pass trustDevice: true when verifying. Default trust duration: 30 days ( trustDeviceMaxAge ). Refreshes on each sign-in. Security Considerations Session Management Flow: credentials → session removed → temporary 2FA cookie (10 min default) → verify → session created. twoFactor ({ twoFactorCookieMaxAge : 600 , // 10 minutes in seconds (default) }); Rate Limiting Built-in: 3 requests per 10 seconds for all 2FA endpoints. OTP has additional attempt limiting: twoFactor ({ otpOptions : { allowedAttempts : 5 , // Max attempts per OTP code (default: 5) }, }); Encryption at Rest TOTP secrets: encrypted with auth secret. Backup codes: encrypted by default. OTP: configurable ( "plain" , "encrypted" , "hashed" ). Uses constant-time comparison for verification. 2FA can only be enabled for credential (email/password) accounts. Disabling 2FA Requires password confirmation. Revokes trusted device records: const disable2FA = async ( password : string ) => { const { data, error } = await authClient. twoFactor . disable ({ password, }); }; Complete Configuration Example import { betterAuth } from "better-auth" ; import { twoFactor } from "better-auth/plugins" ; import { sendEmail } from "./email" ; export const auth = betterAuth ({ appName : "My App" , plugins : [ twoFactor ({ // TOTP settings issuer : "My App" , totpOptions : { digits : 6 , period : 30 , }, // OTP settings otpOptions : { sendOTP : async ({ user, otp }) => { await sendEmail ({ to : user. email , subject : "Your verification code" , text : `Your code is: ${otp} ` , }); }, period : 5 , allowedAttempts : 5 , storeOTP : "encrypted" , }, // Backup code settings backupCodeOptions : { amount : 10 , length : 10 , storeBackupCodes : "encrypted" , }, // Session settings twoFactorCookieMaxAge : 600 , // 10 minutes trustDeviceMaxAge : 30 * 24 * 60 * 60 , // 30 days }), ], });
Keywords that activate this skill. Click one to copy it.

This skill does not provide trigger words.

The downloaded .skill package contains the following fields.
Field Description
formatFormat tag (skill/v1)
skill_idUnique skill ID
nameSkill name
versionVersion
descriptionDescription
categoryCategories (array)
trigger_wordsTrigger words
tagsTags
sourceSource
source_urlSource URL (this page)
exported_atExported at (set per download)
system_promptSystem prompt body
model_configModel config: provider / model / temperature / max_tokens / top_p
examplesExamples
install_guideImport guide for Coze / Dify / Claude / custom frameworks
The same skill can be exported in different platform formats.
.skill Standard format with system_prompt and model_config, ready for any agent framework Download
.skillpro Enhanced format with scripts, tools, dependencies and hooks Download
.json Plain JSON export with system_prompt and model parameters only Download
Coze Markdown with frontmatter, for Coze platform import Download
Dify Dify DSL, import directly after creating an app Download

每日精选 Skill 推荐,免费送到你邮箱

输入邮箱,每天接收一个精选 AI Agent 技能推荐。完全免费,持续更新。

验证码 --

提交后我们会发送一封确认邮件,点击邮件里的链接才会开始收信。

完全免费,取消任意时间。我们不会发送垃圾邮件。