=== Protect Login ===
Contributors: tidschi, krafit
Tags: login, security, authentication
Requires at least: 5.7
Tested up to: 7.0
Requires PHP: 7.4
Stable tag: 1.5.1
License: GPL-3.0-or-later
License URI: https://www.gnu.org/licenses/gpl-3.0.html

Add an additional layer of protection to your WordPress login and make sure bad actors have a hard time guessing your user's login credentials.

== Description ==

Out of the box, WordPress will happily let anyone try to log in as often as they like. Type the wrong password a thousand times and it just shrugs and shows you the form again – which is exactly what someone running a brute-force script is counting on. _Protect Login_ closes that door. It started life as a fork of [Johan Eenfeldt](https://profiles.wordpress.org/johanee/)'s original _Limit Login Attempts_, a plugin a lot of us leaned on for years, and grew from there.


= It slows brute-force attacks to a crawl =

Protect Login watches failed logins per IP address. After a handful of wrong attempts that visitor has to wait before trying again, and if they keep guessing the wait grows. So a script built to try thousands of passwords ends up sitting on its hands.

= You decide who gets in, and who doesn't =

Protect Login keeps a visible list of every address that's currently locked out, right in the settings, and lets you release any of them with a single click. You can also keep an allowlist of addresses that skip the checks entirely (your office, your VPN's exit node) and a blocklist of addresses that are turned away immediately.

= One login list, shared across all your sites =

If you look after more than one WordPress site – an agency, or just a small pile of your own projects — someone hammering one of them is often about to try the rest. Protect Login can link your sites together over its own Remote API: pick one site as the host, point the others at it with a URL and a key, and the block-, allow- and lockout-lists stay in sync across the lot. Block an address once and it's blocked everywhere.

= And a few more things =

* Gets the real client IP right when your site sits behind a reverse proxy or CDN — direct and proxy modes
* Speaks IPv6, not only IPv4
* Works on Multisite, applying settings and lists across the network.
* Ships WP-CLI commands, so you can manage addresses and settings straight from the terminal.
* Lets developers set everything in code via filters — and locks the matching field in the UI, so nobody ends up fighting their own filter.
* Can enforce a minimum password strength for new passwords

== Installation ==

1. Upload the plugin files to the `/wp-content/plugins/protect-login` directory, or install the plugin through the WordPress plugins screen directly.
1. Activate the plugin through the "Plugins" screen in WordPress.
1. That's it - sensible defaults are applied automatically. To change them, head to **Settings → Protect Login**.

== Frequently Asked Questions ==

= Why did you build this? =

We care about WordPress and about keeping WordPress sites secure. So we took the code of the original Limit Login Attempts plugin and built on top of it. We did it for you: Protect Login is 100% free, with no nasty upsells and no scare marketing. You've got better things to do, haven't you?

= Why don't you reset failed attempts after a successful login? =

That's very much on purpose. If we did, you could brute-force the "admin" password simply by logging in as your own user every fourth attempt — which would defeat the point.

= How do I know if my site is behind a reverse proxy? =

If you're not sure, chances are it isn't. A reverse proxy is a server that sits between your site and the internet – often handling caching or load-balancing – and it makes working out the correct client IP a little trickier. If you do use one, switch on proxy mode under **Settings → Protect Login → Advanced** and add your proxy's IP or CIDR range to the trusted-proxies list, so a forwarded header can't be spoofed.

= Can I put my own IP on an allowlist so I don't get locked out? =

Yes. There's an allowlist tab in Protect Login's settings, and you can add your current address with a click.

= I locked myself out while testing. What now? =

Either wait until your account or IP is released, or — if you have FTP or SSH access — rename the `wp-content/plugins/protect-login` folder to switch the plugin off, log in, and rename it back.

= Do you support IPv6? =

Yes. As long as your web server passes an IPv6 address through to WordPress.

= Where do I report security bugs found in this plugin? =

Please report security bugs found in the source code of the Protect Login plugin through the [Patchstack Vulnerability Disclosure Program](https://patchstack.com/database/vdp/8f993618-835b-4951-ac1b-0efa35062d9b). The Patchstack team will assist you with verification, CVE assignment, and notify the developers of this plugin.

== Changelog ==
= 1.5.1 =
* Bugfix: Typos
* Bugfix: Fixed a fatal error (TypeError) during Remote API list synchronisation.
* Bugfix: Fixed a fatal error that could occur in proxy ("client type") mode when no valid forwarded address was present.
* Bugfix: Fixed an "Array to string conversion" warning on the settings page when the dashboard-counter option had not been saved yet.
* Improvement: Added "Trusted proxies" setting. In proxy mode the client IP is now only used when the request arrives via a configured trusted proxy.

= 1.5.0 =
* Tested with WordPress 7.0
* Bugfix: Removed an empty list item that appeared above the locked-out address counter in the "At a Glance" dashboard widget.
* Bugfix: Locking out an IP address no longer clears all other active lockouts.
* Bugfix: Remote API list synchronisation now runs as intended (the previous check never triggered a sync); local block-/allowlist entries are no longer lost when merging with remote lists.
* Bugfix: Remote API calls now use the correct endpoint paths, so block, allow, release and list operations work against a paired site.
* Bugfix: Lockout times in the settings list and WP-CLI output now use the site's configured time zone instead of always showing UTC.
* Bugfix: Corrected the swapped "your IP has (not) changed" message on the allowlist screen.
* Bugfix: Reverse-proxy ("client type") handling now works as configured, and falls back to the direct connection address when no valid forwarded address is present.
* Bugfix: Hardened against division-by-zero and undefined-value notices when retry/notification thresholds are set to 0 or no attempts have been recorded yet.
* Bugfix: Activation and uninstall routines are now registered against the main plugin file so they run reliably.
* Improvement: The settings override filters now work as documented.
* Improvement: Removed an unnecessary PHP session start on every authentication and a redundant database write on every admin page load.
* Improvement: Added `Text Domain` and `Domain Path` plugin headers and a translation template.
* Development: Codebase migrated to new Coding Standard.

== Upgrade Notice ==
