figma guide
Designing two-factor authentication and security settings UI in Figma: MFA setup, backup codes, and trusted devices
Design 2FA and security settings UI in Figma with authenticator setup, SMS backup, recovery codes, trusted devices, password change, and Dev Mode specs for account security.
- Published
- Updated
- Jul 05, 2026
- Read time
- 8 min
- Level
- Beginner
Quick answer
Security settings let users change passwords, enable two-factor authentication (2FA), manage backup codes, and review active sessions—usually under Account → Security. Design enable flows for authenticator app (QR + manual key + verify code), optional SMS backup, and recovery codes shown once at setup. Include disable-2FA with re-auth, a trusted devices list, and password change with current-password verification. Challenge screens during login reuse the same code-entry component. Start from the Figma guides hub and pair with login, email verification / OTP, and account dashboard guides.
Who this is for
- Product designers building account security pages and login MFA challenges.
- Design system teams standardizing OTP inputs and security banners across web and mobile.
- Engineers implementing TOTP, SMS fallback, session revocation, and rate limiting.
Security settings surface comparison
| Surface | When to use | Trade-off |
|---|---|---|
| Account security page | Password, 2FA, sessions | Canonical settings hub |
| Login MFA challenge | Step after password success | Reuse OtpCodeInput component |
| Forced enrollment prompt | High-risk accounts or admin policy | Modal after login—easy to dismiss |
| Checkout re-auth | Change payment on file | Short password or OTP only |
| Support-assisted reset | User lost device | Out of band—not designed in Figma file |
Verdict: one SecuritySettingsPanel on the account route plus shared MfaChallengeForm and OtpCodeInput used at login and during enable/disable flows.
SecuritySettingsPanel anatomy
| Part | Spec | Notes |
|---|---|---|
| Page title | ”Security” or “Sign-in & security” | Under account nav |
| Password row | ”Change password” link or inline form | Requires current password |
| 2FA status row | Enabled / Not enabled badge + CTA | Primary security action |
| Recovery codes row | View/regenerate (when 2FA on) | Shown only when enabled |
| Trusted devices | Session list with revoke | Last active, location approx |
| Sign out everywhere | Secondary destructive | Revokes all sessions |
| Recent activity | Optional login log | IP, device, timestamp |
SecuritySettingsPanel
├── Variant: mfaEnabled=false | true
├── Variant: state=default | editingPassword
└── Layers:
├── PageHeader
├── PasswordSection
├── TwoFactorSection
│ ├── MfaStatusBadge
│ ├── EnableMfaButton | ManageMfaButton
│ └── RecoveryCodesRow
├── TrustedDevicesSection
│ └── DeviceRow (repeat)
├── SignOutAllButton
└── ActivityLog (optional)
Cross-link privacy settings when delete-account and export require re-auth here.
Enable 2FA flow (authenticator app)
| Step | UI | Notes |
|---|---|---|
| 1. Intro | Benefits copy + “Set up authenticator” | Mention Google Authenticator, 1Password, etc. |
| 2. QR code | Large QR + “Can’t scan?” expand | Manual secret key with copy button |
| 3. Verify | 6-digit OTP input | Auto-advance per digit |
| 4. Recovery codes | Grid of 8–10 codes + download/print | One-time display warning |
| 5. Success | Banner on security page | ”Two-factor authentication is on” |
| 6. SMS backup | Optional add phone step | Verify phone with SMS code |
EnableMfaFlow
├── Variant: step=intro | scanQr | verifyCode | showRecoveryCodes | success
├── Variant: method=authenticator | sms
└── Layers:
├── QrCodePanel
├── ManualSecretKey
├── OtpCodeInput
├── RecoveryCodesGrid
├── DownloadCodesButton
└── SmsBackupStep (optional)
Verdict: never let users skip recovery codes without explicit “I saved these” checkbox—support volume spikes when they lose phones.
OtpCodeInput component
Reuse across login challenge, enable verify, SMS verify, and disable confirm.
| Property | Spec |
|---|---|
| Digits | 6 (TOTP) or 4–8 configurable |
| Input mode | numeric keyboard on mobile |
| Auto-focus | First empty cell |
| Paste | Full code from clipboard |
| Error | Shake + “Invalid code” |
| Resend | SMS only—60s cooldown timer |
| Backup link | ”Use a recovery code instead” |
OtpCodeInput
├── Variant: digits=6 | 8
├── Variant: state=default | error | disabled
└── Layers:
├── DigitCell (repeat)
├── ErrorMessage
├── ResendTimer (sms only)
└── UseRecoveryCodeLink
Match spacing and focus rings from form input states.
Recovery codes UI
| State | UI |
|---|---|
| First setup | Full grid + “Copy all” + “Download .txt” |
| Regenerate | Warning: invalidates old codes |
| Enter at login | Single text field or 8-char input |
| Low codes left | Banner when ≤2 remain |
| Used code | Error at login |
Store codes as hashed server-side—design should never show them again after first setup except regenerate flow.
Disable 2FA flow
| Step | UI |
|---|---|
| 1. Entry | ”Turn off” from security page |
| 2. Warning | Reduced account security copy |
| 3. Re-auth | Password + current TOTP or recovery code |
| 4. Confirm | Destructive button “Turn off two-factor authentication” |
| 5. Success | Email notification “2FA disabled on your account” |
Require stronger verification than enable—password alone is not enough if 2FA is active.
Trusted devices and sessions
| Element | Spec |
|---|---|
| Device row | Icon + “Chrome on MacOS” + “Current session” badge |
| Meta | Last active, approximate location |
| Revoke | Per-row “Sign out” |
| Sign out everywhere | Separate button below list |
| Empty | N/A—always at least current |
TrustedDevicesList
├── Variant: state=default | revoking
└── Layers:
├── DeviceRow (repeat)
│ ├── DeviceIcon
│ ├── DeviceLabel
│ ├── LastActiveMeta
│ ├── CurrentBadge (conditional)
│ └── RevokeButton
└── SignOutAllButton
Pair with notification preferences for security alert emails when new device signs in.
Change password form
| Field | Validation UI |
|---|---|
| Current password | Required; wrong password inline error |
| New password | Strength meter; policy rules listed |
| Confirm new | Match error |
| Submit | ”Update password” |
ChangePasswordForm
├── Variant: state=default | success | error
└── Layers:
├── CurrentPasswordField
├── NewPasswordField
├── StrengthMeter
├── ConfirmPasswordField
├── LogoutOtherSessionsCheckbox
└── SubmitButton
After success, show toast and optionally redirect to dashboard.
Login MFA challenge (reuse)
When password succeeds but 2FA is enabled, swap AuthForm to challenge mode—see login guide for mode=mfaChallenge.
| State | UI |
|---|---|
| Default | OtpCodeInput + “Trust this device 30 days” checkbox |
| SMS sent | Masked phone + resend timer |
| Recovery mode | Single field for backup code |
| Locked | Too many attempts—15 min cooldown banner |
| Success | Redirect to return URL or dashboard |
Remember device checkbox should explain trade-off: “Don’t ask again on this browser for 30 days.”
Mobile layout
| Pattern | Spec |
|---|---|
| QR setup | Full-width QR; manual key in accordion |
| OTP cells | Larger tap targets—48px min width per cell |
| Recovery codes | 2-column grid; scroll if needed |
| Device list | Revoke as swipe or overflow menu |
| Sticky CTA | ”Verify” fixed bottom during setup |
Test QR scanning UX on real devices—designers often crop QR too small in Figma frames.
Handoff checklist
| Item | Dev Mode annotation |
|---|---|
| TOTP issuer name | Shown in authenticator app (brand string) |
| Recovery code format | XXXX-XXXX × 10; single-use |
| Rate limits | 5 failed OTP → 15 min lock |
| Session revoke API | DELETE /sessions/:id |
| Trust device cookie | TTL 30 days; httpOnly |
| 2FA disable | Requires password + TOTP or recovery |
| Email triggers | enable, disable, new device, password change |
| a11y | OTP cells as grouped input; errors announced |
Document SMS vs authenticator priority—which method is primary at login when both exist.
Common mistakes
| Mistake | Why it hurts | Fix |
|---|---|---|
| Recovery codes shown twice | Security risk | One-time display only |
| Skip verify step after QR | Broken setup | Require 6-digit confirm |
| Disable with password only | Account takeover | Require active 2FA factor |
| Tiny QR in mobile frame | Users can’t scan | Min 200×200px in spec |
| No “trust device” copy | Confusion on checkbox | Explain 30-day behavior |
| Different OTP UI at login vs settings | Inconsistent UX | One OtpCodeInput component |
| No email on security changes | User can’t detect fraud | Notify on enable/disable/password |
| SMS as only 2FA | SIM-swap risk | Prefer authenticator; SMS as backup |
Recommended workflow
- Build
OtpCodeInputwith 6-digit, paste, and error states. - Design
SecuritySettingsPanelwith password + 2FA status rows. - Flow enable MFA: QR → verify → recovery codes → success.
- Design disable + regenerate with re-auth modals.
- Add trusted devices list with revoke and sign-out-all.
- Reuse
MfaChallengeFormon login—link from login post. - Spec email notifications for each security event.
- Prototype full enable flow on 375px mobile frame.
FAQ
Authenticator only or SMS too?
Authenticator first—cheaper and more secure. Offer SMS as optional backup with clear SIM-risk note.
Force 2FA for all users?
Design forced enrollment modal after login for high-risk roles; optional banner for everyone else.
WebAuthn / passkeys?
If your roadmap includes passkeys, add a Passkeys row above 2FA with “Add passkey”—same security page IA.
Show IP addresses in activity log?
City + country is enough for most ecommerce—full IP in support tools only.
Next steps
- Design login, registration, and password recovery UI in Figma — MFA challenge at sign-in
- Design email verification and OTP UI in Figma — shared OTP input patterns
- Design account dashboard and my account UI in Figma — security nav entry
- Design privacy settings and data management UI in Figma — export/delete re-auth
- Design notification preferences and communication settings UI in Figma — security alert emails
§ Keep reading