renatio / twofactorauth-plugin
Two-Factor Authentication for October CMS backend with recovery codes and trusted devices.
Package info
github.com/mplodowski/twofactorauth-plugin
Type:october-plugin
pkg:composer/renatio/twofactorauth-plugin
Requires
- php: ^8.4
- composer/installers: ^1.0|^2.0
- endroid/qr-code: ^5.1
- october/rain: ^4.0
- pragmarx/google2fa: ^8.0
README
Demo URL: https://october-demo.renatio.com/backend/backend/auth/signin
Login: twofactorauth
Password: twofactorauth
Plugin adds Time-based One-Time Password (TOTP) two-factor authentication to the OctoberCMS backend. Protect administrator accounts with authenticator apps, single-use recovery codes, and trusted devices.
Features
- Backend 2FA powered by TOTP (RFC 6238) — compatible with Google Authenticator, Microsoft Authenticator, 1Password, Bitwarden, Aegis, Ente Auth, Raivo OTP and any standard authenticator app
- QR code setup with a configurable color (falls back to the backend brand primary color)
- Encrypted secret storage (Laravel
Crypt) and hashed, single-use recovery codes - Trusted devices — let users skip 2FA on recognized browsers for a configurable number of days
- Per-user and per-IP rate limiting of verification attempts to prevent brute-force
- Force-enable 2FA for super users or for every backend user on next login
- Admin override — super users can disable 2FA for any account when a user loses access
- My Account integration — enable, disable, rotate recovery codes from the user profile
- Recovery codes download as a
.txtfile - Multilingual: English, Polish, German, French, Spanish, Brazilian Portuguese, Italian, Russian, Dutch and Czech translations included — more available on request
Why is this a paid plugin?
Something that is free has little or no perceived value. Users do not commit to free products and only use them until something else that looks nice and free comes along. When I invest my time in the development of a new plugin I commit to supporting and maintaining it. I ask my customers to do the same. I do not make money from this plugin by advertisements, upgrades or additional services like hosting or setup.
Did you know that 30% of your purchase or donation goes to help fund the October Project?
My plugins take many hours to develop (40-120+) and even more hours to document and maintain. My paid plugins have to pay for both this time, and the time I am spending on free plugins and less successful paid plugins. This means that it will take even a successful plugin years to become profitable. Please consider buying an extended license if you want me to continue to maintain these plugins for the very small fee I ask in return or hire me for adding functionality that you feel is missing but valuable.
Like this plugin?
If you like this plugin, give this plugin a Like or Make donation with PayPal.
My other plugins
Please check my other plugins.
Support
Please use GitHub Issues Page to report any issues with plugin.
Reviews should not be used for getting support, if you need support please use the Plugin support link.
Icon made by Darius Dan from www.flaticon.com.
Documentation
Usage
After installation plugin will register its settings page under Settings → System → Two-Factor Authentication and add a new Two-Factor Authentication tab to every backend user profile.
To enable 2FA for your own account:
- Go to Settings → Administrators and open your profile (My Account).
- Switch to the Two-Factor Authentication tab and click Set up two-factor authentication.
- Scan the QR code with your authenticator app (or paste the secret key manually).
- Enter the 6-digit code shown in the app to confirm.
- Save the recovery codes shown on screen — they will not be displayed again. Download them as a
.txtfile and confirm with I have saved my recovery codes.
From the next login, after entering your password you will be redirected to the verification screen and prompted for the current 6-digit code from your authenticator app. If enforcement is enabled and the user has no 2FA configured, the same flow walks them through enrolment (enable → codes → sign in) before granting access.
Supported authenticator apps
Any TOTP-compatible app works. Recommended:
- Google Authenticator
- Microsoft Authenticator
- 1Password
- Bitwarden
- Ente Auth
- Aegis Authenticator (Android, open source)
- Raivo OTP (iOS, open source)
Settings
Plugin settings are available at Settings → System → Two-Factor Authentication and grouped in five tabs. Every option ships with a sensible default pulled from the config file; once you save the settings page, the saved values take over.
General
- Issuer name — label shown in authenticator apps next to the account. Leave empty to use the site host name.
- QR code color — foreground color of the generated QR code. Leave empty to fall back to the current backend brand primary color.
Enforcement
- Require 2FA for super users — forces every super user to set up 2FA on next login.
- Require 2FA for all users — forces every backend user to set up 2FA on next login.
- Pending login TTL (seconds) — how long a user has to complete the verification step after entering their
password. Default:
600(10 minutes).
When enforcement is enabled, users without 2FA configured are walked through enrolment after entering their password and cannot reach the backend until setup is complete. Closing the browser mid-enrolment does not bypass the check — the next login redirects them through the same flow. Enrolment is only considered done once the user acknowledges their recovery codes on the final screen, which is also when their first backend session is opened.
Trusted devices
- Allow trusted devices — let users skip 2FA on devices they mark as trusted.
- Trusted device lifetime (days) — how long a trusted device is remembered. Default:
30. - Trusted device cookie name — cookie name used to remember trusted devices. Default:
oc_tfa_trust.
When a user checks Trust this device on the verification screen, a signed cookie is issued. On subsequent logins from the same browser the 2FA prompt is skipped until the cookie expires or the user disables 2FA. Each trusted device is also recorded in the database and can be reviewed or revoked individually from My Account → Two-Factor Authentication.
Recovery codes
- Number of recovery codes — how many single-use recovery codes are generated per user. Default:
10. - Recovery code length — total number of characters in each code, split across two chunks. Default:
10(rendered asXXXXX-XXXXX).
Rate limiting
- Max attempts per IP — failed verifications allowed per IP before a temporary lockout. Default:
5. - IP lockout window (seconds) — how long the IP counter is remembered. Default:
300. - Max attempts per user — failed verifications allowed per user across all IPs. Default:
20. - User lockout window (seconds) — how long the per-user counter is remembered. Default:
3600.
Recovery codes
Recovery codes are single-use fallback codes shown once during 2FA setup. They are stored hashed and let a user sign in if their authenticator device is unavailable.
Codes are rendered as two chunks separated by a dash (e.g. XXXXX-XXXXX) and can be regenerated from
My Account → Two-Factor Authentication → Manage recovery codes. Regenerating invalidates all previous codes and the
freshly generated set is shown in place inside the popup, with a .txt download button — they will not be displayed
again.
On the verification screen the Don't have your phone? link leads to the recovery code form. Submitting a valid recovery code signs the user in and removes that code from the remaining pool.
Admin override
Super users can force-disable 2FA for another user from that user's profile. This is useful when a user loses access to their authenticator device and has no recovery codes left. The override:
- Clears the encrypted TOTP secret.
- Deletes all recovery codes.
- Forgets every trusted device for the user.
The user will be prompted to configure 2FA again on next login if enforcement is enabled.
Rate limiting
Verification attempts (both TOTP codes and recovery codes) are rate-limited per IP and per user to prevent brute-force once a password is known. Two counters run independently:
- Per-IP:
5attempts within300seconds by default - Per-user:
20attempts within3600seconds by default
A successful verification resets both counters. All four values are configurable in Settings → Rate limiting.
Configuration
Runtime options are read from the Settings model (Settings → System → Two-Factor Authentication). Until the page
is saved, the Settings model falls back to the defaults defined in the plugin's config/config.php. You can override
the defaults at the application level by publishing a config/renatio/twofactorauth.php:
return [ 'enforce_super_users' => false, 'enforce_all_users' => false, 'pending_ttl' => 600, 'trust_devices' => true, 'trust_ttl_days' => 30, 'trust_cookie' => 'oc_tfa_trust', 'recovery_code_count' => 10, 'recovery_code_length' => 10, 'throttle_max_attempts' => 5, 'throttle_decay_seconds' => 300, 'throttle_user_max_attempts' => 20, 'throttle_user_decay_seconds' => 3600, 'issuer' => null, 'qr_color' => null, ];
Once an administrator saves the Settings page, the saved values take precedence over config defaults.
Permissions
Plugin registers a single permission:
- renatio.twofactorauth.access_settings — required to manage the plugin's settings page.
Events
The plugin hooks into standard October backend events:
backend.page.beforeDisplay— intercepts the sign-in form to route users through 2FA when required.backend.form.extendFields— adds the Two-Factor Authentication tab to backend user profiles.
No custom events are fired at this time.