=== LoginArmor - Email 2FA === Contributors: gotechark, yogid Tags: two-factor authentication, 2fa, email otp, login security, recovery codes Tested up to: 7.0 Stable tag: 1.2 Requires PHP: 7.4 License: GPLv3 or later License URI: http://www.gnu.org/licenses/gpl-3.0.html Add secure email-based 2FA authentication to WordPress logins with OTP verification, recovery codes, a grace period, and flexible user targeting. == Description == LoginArmor adds an extra layer of protection to WordPress logins by requiring a one-time verification code after a valid username and password are entered. = Key features = * Email-based one-time passcodes for WordPress logins * Apply 2FA to selected user roles * Apply 2FA to specific users * Optional grace period before activation is enforced * Recovery codes for backup access * Customizable email subject and login code email template * Optional debug logging to `wp-content/uploads/loginarmor-email-2fa/loginarmor-debug.log` * Automatic log rotation to prevent unbounded log file growth * Compatible with WordPress application passwords and REST API clients * Dedicated settings screen inside the WordPress admin = How it works = 1. A user enters a valid username and password. 2. LoginArmor sends a one-time code to the user’s email address. 3. The user enters the code to complete login. 4. If needed, the user can use a recovery code instead. = Recovery codes = The plugin includes recovery codes as a backup login option. Codes are stored securely as hashes in user meta. Plaintext codes are shown only temporarily so users can save or download them once. = Grace period = You can optionally set a grace period in days. During the grace period, eligible users can continue signing in while they complete activation. After the grace period ends, 2FA is enforced. = No external service required = LoginArmor uses WordPress email delivery and does not require a third-party 2FA service. = Developer notes = The plugin exposes a filter for sites running behind a reverse proxy (Cloudflare, load balancers, etc.) that need to supply the real visitor IP: add_filter( 'la2fa_get_client_ip', function( $ip ) { return $_SERVER['HTTP_CF_CONNECTING_IP'] ?? $_SERVER['REMOTE_ADDR'] ?? 'unknown'; } ); Without this filter the plugin behaves exactly as before — it reads `REMOTE_ADDR` by default. == Installation == 1. Upload the plugin files to the `/wp-content/plugins/loginarmor-email-2fa/` directory, or install the plugin through the WordPress plugins screen. 2. Activate the plugin through the **Plugins** screen in WordPress. 3. Go to **LoginArmor** in the WordPress admin menu. 4. Enable two-factor authentication. 5. Choose the user roles and/or specific users who should use 2FA. 6. Configure the grace period if needed. 7. Customize the email subject and email template if desired. 8. Save your settings. == Frequently Asked Questions == = Can I apply 2FA to only some users? = Yes. You can apply 2FA by user role, by specific users, or both. = What happens if a user cannot access their email? = They can use a recovery code if one has been generated and saved. = Can I customize the email content? = Yes. You can customize the sender email address, subject line, and login code email template from the plugin settings. = Does the plugin require a third-party account? = No. It works with your WordPress site and its email sending setup. = Where are recovery codes managed? = Recovery codes are available from the user profile area and are intended to be saved by the user for emergency access. = Does 2FA affect REST API access or application passwords? = No. WordPress application passwords used for REST API access bypass the OTP flow by design. 2FA applies only to interactive browser-based logins via wp-login.php. = Does 2FA work with XML-RPC? = XML-RPC logins for accounts that have 2FA enabled will be blocked with a clear error message. This is intentional — XML-RPC cannot complete an OTP challenge. If you rely on XML-RPC for a specific integration, either exclude that user from 2FA targeting or switch to application passwords, which are fully supported. = My site is behind Cloudflare or a load balancer — will rate limiting work correctly? = By default the plugin reads `REMOTE_ADDR` for IP-based rate limiting, which may be the proxy's IP rather than the real visitor's. Use the `la2fa_get_client_ip` filter (see Developer notes in the Description tab) to supply the correct IP for your hosting environment. == Privacy == LoginArmor does not connect to an external third-party verification service. The plugin may process and store the following data on your WordPress site: * Email-based one-time passcodes for login verification * Recovery code hashes stored in user meta * Optional debug log entries in `wp-content/uploads/loginarmor-email-2fa/loginarmor-debug.log` * Temporary transients used for login, cooldown, and verification flow This data stays on your site unless your own email delivery system or hosting stack routes it elsewhere. == Screenshots == 1. Configure 2FA Setting 2. Configure Email Template == Changelog == = 1.2 = * Security: 2FA OTP challenge is now correctly skipped for REST API requests authenticated via WordPress application passwords, preventing broken API integrations. * Security: XML-RPC login attempts for 2FA-protected accounts now return a clear WP_Error instead of issuing a silent broken redirect. * Fix: Recovery code setup redirect now correctly passes the user to their original destination after saving codes ("Continue" button works as expected). * Improvement: Debug log file is now automatically rotated when it exceeds 5 MB, preventing unbounded disk usage on busy sites. * Improvement: Added `la2fa_get_client_ip` filter to allow sites behind reverse proxies (Cloudflare, load balancers) to supply the correct visitor IP for rate limiting. = 1.1 = * Minor code optimizations. = 1.0 = * Initial release * Improved settings handling and login flow stability * Refined admin UI and general plugin behavior == Upgrade Notice == = 1.2 = Recommended update. Fixes a silent breakage affecting REST API / application password users, fixes the recovery code "Continue" redirect, and improves log file handling. No settings changes required — upgrade and activate. = 1.1 = Code & performance optimizations = 1.0 = This version standardizes the plugin as email-only 2FA for the first public release and updates older saved settings accordingly.