Setting Up Login Security
Members log in with a password today. That breaks when someone reuses it on another site, forgets it, or falls for a phishing link. Torii gives you two ways to protect accounts without turning your login page into a technical manual: TOTP codes and passkeys. Members pick what they want. A third option replaces the password entirely: Single Sign-On moves authentication to an identity provider your members already have, and can require it for specific populations.
TOTP is the familiar six-digit code from an authenticator app. Passkeys are passwordless logins using Face ID, Touch ID, or a hardware key. A verified passkey counts as two-factor on its own, so members who adopt it skip TOTP entirely. The site owner enables both; the member chooses. When choice is not enough, two switches tighten the screws: 2FA Enforcement requires a second factor for the roles you pick, and passkey-only sign-in takes passwords away from passkey-holding members of the roles you pick.
What each method does
TOTP. Members scan a QR code once with Google Authenticator, 1Password, or any authenticator app. From then on, every login asks for their password plus a rotating six-digit code that changes every thirty seconds. If they lose their phone, they use a one-time recovery code you generated at setup.
Passkeys. Members register a passkey from their device: Face ID on an iPhone, Windows Hello on a laptop, or a YubiKey hardware key. The login form shows a "Sign in with passkey" button. They tap it, authenticate with biometrics or a PIN, and they're in. There is no code to type and no password reset email three days later. A passkey can't be phished or reused from another site because there is no secret stored anywhere an attacker can reach.
How they work together
They run on the same login form:
- The member enters their password (or clicks "Sign in with passkey").
- If they've enrolled TOTP and haven't used a passkey, the system shows a verification code screen after the password checks out.
- A verified passkey bypasses that second step entirely. It is itself the two-factor proof.
A member who has both enabled will use whichever path is faster on any given day: passkey from their phone, password plus code from their laptop. You don't configure which one they get to use; the system picks the simplest path that works.
Setting up TOTP
Go to Membership → Settings → TOTP 2FA in the WordPress admin. The settings page has three controls:
- Issuer Name. What your site is called inside members' authenticator apps. Leave it blank and the system uses your WordPress site name.
- Time Window. How much clock drift to tolerate between the member's phone and the server. One step (±30 seconds) is fine for nearly everyone. Only increase this if you hear from members whose phones have badly wrong clocks.
- Recovery Code Count. How many one-time recovery codes to generate when a member enrolls. Eight is standard; each code can be used once and then disappears.
The same screen carries an Enforcement card for requiring two-factor by role, with a grace period for each member. It stays out of the way until you fill it in; see 2FA Enforcement.
The encryption status card at the top tells you whether TOTP secrets are encrypted at rest. If it shows a warning, define WPAL_TORII_ENCRYPTION_KEY in your wp-config.php. Without it, TOTP cannot be used securely.
Setting up passkeys
Go to Membership → Settings → Passkey Settings. Two editable fields:
- Relying Party Name. What the browser shows in the passkey prompt. Leave it blank and the system uses your WordPress site name. This is the label members see when they first register a passkey: "Save this to your Apple ID for torii.example.com" or similar.
- Passkey-Only Roles. Members of the selected roles who have registered a passkey lose password sign-in entirely. This is the lockdown switch for administrator and editor accounts; the details are in Passkey-only sign-in.
The Relying Party ID and Origin fields are read-only. They're derived automatically from your site URL and change when you move domains. You don't need to touch them.
Passkeys require HTTPS. The system won't let members register a passkey on an HTTP connection, and the browser will refuse to show the biometric prompt without it. If you're testing locally, use https://localhost or a tunneling tool that provides TLS.
What members see
The login form shows both paths at once. Members who have TOTP enrolled see their usual password field followed by a verification code screen after they authenticate. Members who have registered a passkey see an additional "Sign in with passkey" button below the submit button. They can use either path.
Members manage their own setup from their profile:
[memb_totp_setup]: scan the QR code and confirm the first code[memb_totp_manage]: disable TOTP, regenerate recovery codes[memb_passkeys_setup]: register a new passkey from the current device[memb_passkeys_manage]: list enrolled passkeys, rename them, delete a lost device
You can place these shortcodes on any page. A "Security Settings" page is common: members find it in their profile menu, or you link to it from the welcome email.
Recovery and support
Members lose phones. Passkeys live on devices, so a lost phone means a lost passkey. They can log in with their password plus TOTP code if they still have that enrolled, or request a fresh magic link if passwordless login is how they got in originally. Once back in, they register the new device from [memb_passkeys_setup].
Recovery codes are the fallback for TOTP. They're generated at enrollment time, displayed once, and stored hashed on your site. A member who loses their phone uses one to get in, then generates a fresh set. If you need to help a member recover, go to Users → Profile → TOTP Two-Factor Authentication and click "Delete TOTP Setup." They'll need to re-enroll from scratch.
You can also see enrollment status at a glance: the Users list table has a 2FA column showing green or red icons for each user. The Member Profile screen has a dedicated section under each user that shows their TOTP status, last-used date, and remaining recovery codes.
What to enable on day one
Enable both modules. Let members adopt whatever works for them. Members who already use an authenticator app for their bank will switch over in minutes. Others keep using passwords until you introduce them to passkeys.
The only configuration worth thinking about before launch is the issuer name (for TOTP) and relying party name (for passkeys). They should match what members know your site as, not your internal project codename or development domain. Everything else ships with sensible defaults.
Tightening later
Adoption first, requirements second. The order that works:
- Week one. Both modules on, enrollment open, no policy. Mention passkeys in your welcome email; watch the 2FA column in the Users list fill in.
- When your team is ready. Turn on 2FA Enforcement for Administrator and Editor with the default seven-day grace. Each staff member's clock starts at their next login, the dashboard nudges them, and after the deadline their password alone stops working.
- Once staff are enrolled. Shorten the grace period for new hires, widen the role list to moderators or shop managers, and flip on Passkey-Only Roles for the accounts that matter most. From that moment a stolen or guessed password buys an attacker nothing.
Every tightening is reversible. Remove a role from either list, or defer a single member's deadline from their profile, and the pressure eases without touching anyone's enrollment.
Next: Single Sign-On to hand authentication to an identity provider, Magic Links for passwordless first-time access, or Hardening to lock down the rest of your site's attack surface.