Description
🇫🇷 Fully translated into French. Interface et documentation intégralement disponibles en français.
Thirteen security modules. One lightweight plugin. No premium tier.
Login Armor protects WordPress login, accounts and administration with thirteen independent modules. It is built for agencies, freelancers and site owners who want practical security, clear evidence and safe defaults without a remote dashboard, bundled telemetry or upsells.
Why Login Armor
- Complete and free: every module is included under the GPL.
- Lightweight: modules load only when needed and normal login checks add less than 2 ms on a typical setup.
- Private by default: data stays on your site. Optional external calls are disabled until you enable the related feature.
- Ready for real sites: multisite support, reverse-proxy controls, WP-CLI commands and production-safe defaults.
Thirteen security modules
- Hide Login: replace
wp-login.phpwith a private slug and return a 404 or redirect blocked visitors to a chosen URL. - Brute Force Protection: escalating lockouts, subnet blocking, trusted proxy headers and coverage for login, password recovery, registration, XML-RPC and REST users.
- Hardening: sixteen controls for XML-RPC, pingbacks, file editing, version exposure, application passwords, author enumeration, reserved usernames, honeypots, new-admin alerts and forcing HTTPS.
- Two-Factor Authentication: TOTP, email codes, backup codes, trusted devices, per-role enforcement, grace periods and recovery.
- Detection and Incidents: group raw events into attack patterns with severity, timelines, source IPs, targeted users and one-click actions.
- Activity Log: tamper-evident admin audit trail with filters, CSV export, retention controls and optional signed SIEM forwarding.
- Security Headers: CSP, X-Frame-Options, Permissions-Policy, Referrer-Policy and X-Content-Type-Options for login and lockout pages, with optional site-wide baseline headers.
- Breach Check: privacy-preserving Have I Been Pwned password checks and an optional XposedOrNot email check.
- Password Policy: length and character rules, username exclusion, breached-password rejection and optional non-locking expiration reminders.
- Session Management: idle timeout, maximum lifetime, optional single-device access and one-click revocation of other sessions.
- IP Geolocation: cached country lookup for IPs shown in Incidents and Events, with private ranges excluded.
- Request Firewall: optional, monitor-first filtering of malicious paths, query strings and HTTP methods, with administrator exclusions and IP/path allowlists.
- Bot Challenge: an invisible proof-of-work the browser solves before the login form is accepted, an alternative to CAPTCHAs with no external service; monitor-first, then enforce.
Additional tools
Login Armor also includes guided onboarding, a 0-100 security score, conflict detection, email/Slack/Discord/webhook notifications, an optional weekly or monthly security digest, eight Tools > Site Health tests with a support panel, a dashboard widget and a complete WP-CLI suite. A safe mode constant in wp-config.php stands down every protection that could lock an administrator out, without changing a single setting.
The guided safe baseline turns on brute-force protection, attack detection, login-page security headers, the activity log, the seven safest hardening toggles, and the request firewall and bot challenge in monitor mode, where they record without blocking anything. Hide Login and two-factor stay off so you enable them deliberately. After seven days of monitoring, Login Armor reads your own traffic and tells you whether the firewall and the bot challenge can safely start blocking.
The optional AI Security Briefing uses your own WordPress AI connector to explain a thirty-day security snapshot or a single incident. It always starts with deterministic facts, works without AI and sends nothing until an administrator explicitly requests an analysis.
GPL forever. PHP 8.1+. WordPress 6.8+. Zero dependencies.
Treize modules de sécurité. Une seule extension légère. Aucune version premium.
Login Armor protège la connexion, les comptes et l’administration de WordPress grâce à treize modules indépendants. L’extension s’adresse aux agences, freelances et propriétaires de sites qui veulent une sécurité concrète, des preuves lisibles et des réglages sûrs, sans tableau de bord distant, télémétrie imposée ni upsell.
Pourquoi Login Armor
- Complet et gratuit : tous les modules sont inclus sous licence GPL.
- Léger : les modules se chargent uniquement lorsque nécessaire et les contrôles ajoutent moins de 2 ms sur une connexion normale.
- Privé par défaut : les données restent sur votre site. Les appels externes optionnels sont désactivés tant que vous n’activez pas la fonction concernée.
- Prêt pour la production : multisite, reverse proxies, commandes WP-CLI et réglages par défaut sécurisés.
Treize modules de sécurité
- Masquer la connexion : remplace
wp-login.phppar un slug privé et renvoie une 404 ou redirige les visiteurs bloqués vers l’URL choisie. - Protection contre la force brute : verrouillages progressifs, blocage de sous-réseaux, proxies de confiance et protection de la connexion, récupération, inscription, XML-RPC et REST users.
- Renforcement : quinze contrôles pour XML-RPC, les pingbacks, l’éditeur de fichiers, la version, les mots de passe applicatifs, l’énumération d’auteurs, les identifiants réservés, le pot de miel et les alertes nouvel administrateur.
- Authentification à deux facteurs : TOTP, codes par e-mail, codes de secours, appareils de confiance, application par rôle, période de grâce et récupération.
- Détection et incidents : regroupe les événements en scénarios d’attaque avec sévérité, chronologie, IP sources, comptes ciblés et actions immédiates.
- Journal d’activité : piste d’audit admin infalsifiable avec filtres, export CSV, rétention et transfert SIEM signé optionnel.
- En-têtes de sécurité : CSP, X-Frame-Options, Permissions-Policy, Referrer-Policy et X-Content-Type-Options pour les pages de connexion et de verrouillage, avec en-têtes de base optionnels sur tout le site.
- Détection de fuites : vérification confidentielle des mots de passe via Have I Been Pwned et contrôle optionnel des e-mails via XposedOrNot.
- Politique de mot de passe : longueur, classes de caractères, exclusion de l’identifiant, rejet des mots de passe compromis et rappels d’expiration non bloquants.
- Gestion des sessions : délai d’inactivité, durée maximale, accès limité à un appareil et révocation des autres sessions.
- Géolocalisation IP : pays des IP affichées dans Incidents et Événements, avec cache et exclusion des plages privées.
- Pare-feu de requêtes : filtrage optionnel, d’abord en surveillance, des chemins, requêtes et méthodes HTTP malveillants, avec exclusion des administrateurs et listes d’autorisation IP/chemins.
- Défi anti-bot : une preuve de calcul invisible résolue par le navigateur avant validation du formulaire de connexion, alternative aux CAPTCHA sans service externe ; d’abord en surveillance, puis en blocage.
Outils complémentaires
Login Armor inclut aussi un assistant de configuration, un score de sécurité de 0 à 100, la détection de conflits, les notifications par e-mail, Slack, Discord ou webhook, un widget de tableau de bord et une suite WP-CLI complète.
La base sûre guidée active la protection contre la force brute, la détection d’attaques, les en-têtes de sécurité de la page de connexion, le journal d’activité, les sept réglages de renforcement les plus sûrs, ainsi que le pare-feu de requêtes et le défi anti-bot en mode surveillance, où ils enregistrent sans rien bloquer. Hide Login et la double authentification restent désactivés pour que vous les activiez délibérément. Au bout de sept jours de surveillance, Login Armor lit votre trafic réel et vous dit si le pare-feu et le défi anti-bot peuvent passer au blocage sans risque.
Le briefing de sécurité IA optionnel utilise votre propre connecteur IA WordPress pour expliquer les trente derniers jours ou un incident précis. Il commence toujours par des faits déterministes, fonctionne sans IA et n’envoie rien tant qu’un administrateur ne demande pas explicitement une analyse.
Conçu par
Login Armor est conçu et maintenu par Fabrice Ducarme de WPFormation. Nous l’utilisons sur chaque site que nous livrons.
- Présentation et fonctionnement de Login Armor
- Guides de sécurité WordPress sur WPFormation
- Veille des vulnérabilités WordPress sur WPFormation
GPL pour toujours. PHP 8.1+. WordPress 6.8+. Zéro dépendance.
External Services
Login Armor has no telemetry and requires no Login Armor account. The following services are contacted only when WordPress itself or an administrator enables the related feature.
WordPress AI connector (optional)
The AI Security Briefing sends a security prompt through the administrator’s own WordPress AI connector only after they click an analysis button. Minimised mode sends counts, categories, severities and role buckets without clear IP addresses or usernames. Explicit deep mode also sends IP addresses and event details. Login Armor stores no provider API key. The selected AI provider’s terms and privacy policy apply.
Slack, Discord or custom webhook (optional)
When an administrator enables an incident notification channel, Login Armor sends the incident type, severity, IP address, target username, event count and site URL to the configured endpoint. The separate signed Activity Log forwarding option sends the event, object, user ID/login/role, IP address, description, integrity hashes, site URL and plugin version to the administrator’s SIEM or custom webhook.
- Slack: Terms | Privacy
- Discord: Terms | Privacy
- Custom webhook: terms and privacy are controlled by the administrator’s chosen endpoint.
Gravatar
The Activity Log uses WordPress core’s get_avatar(). If avatars are enabled in WordPress, a hashed email address may be sent to Gravatar to retrieve the image.
Have I Been Pwned (optional)
Breach Check and the optional compromised-password policy send only the first 5 characters of a password’s SHA-1 hash to the Pwned Passwords API. The password and full hash never leave the site. Checks fail soft if the service is unavailable. Public registration and password-reset validation do not call the service; authenticated checks remain active.
- Have I Been Pwned: Privacy | Acceptable Use
XposedOrNot (optional)
The separate Email check, disabled by default, sends the user’s email address and a plugin-identifying User-Agent to XposedOrNot when a user is created or changes email.
ipwho.is (optional)
IP Geolocation sends public IP addresses recorded in the login log or in an incident to ipwho.is, in a background task: at most 20 addresses every five minutes, and no request is made while an admin page is being rendered. There is no request at all for five minutes after an API failure, and the free tier of the API allows 1000 requests a day per site, after which it asks for a pause that the plugin honours. Results are cached for 30 days, and so is an answer that carries no country. Private and reserved ranges are never sent, and developers can replace the lookup through the login_armor_geoip_lookup filter. The compromise: the background task is a WordPress scheduled event, so on a site where WP-Cron is disabled and no system cron calls wp-cron.php, the country badges stay empty.
- ipwho.is: Service | Documentation
Screenshots











Installation
- Upload the
login-armordirectory to/wp-content/plugins/ - Activate the plugin through the ‘Plugins’ menu in WordPress
- Go to LoginArmor in the admin menu to configure
For multisite: Network Activate the plugin to apply it across all sites.
Setting up Hide Login
- Go to LoginArmor > Settings > Hide Login section
- Enter your desired login slug (e.g.,
my-login) - Save settings
- Bookmark your new login URL: you will need it to access your admin
Recovering access
If you forget your custom login URL:
- Use the recovery email feature (configurable in settings)
- Connect to your database and delete the
login_armor_hide_slugrow from thewp_optionstable - Use WP-CLI:
wp option delete login_armor_hide_slug - Run
wp login-armor rescuefrom your server shell: it lists every way back in, and changes nothing until you add--yes - Last resort, safe mode: add
define( 'LOGIN_ARMOR_SAFE_MODE', true );towp-config.php.wp-login.phpis served again, two-factor is not required, the request firewall and the bot challenge only log, single-session enforcement pauses, and Force HTTPS enforces nothing. Your settings are untouched, brute-force lockouts stay active, and everything comes back the moment you delete the line.
If Force HTTPS was switched on by mistake and the site cannot answer over TLS:
- Use WP-CLI:
wp option patch update login_armor_hardening force_https false(writefalseor0, nothing else: WordPress readsoffandnoas ON) - Or, if you cannot reach a shell, stand it down without changing the setting: add
define( 'LOGIN_ARMOR_SAFE_MODE', true );towp-config.php. All four effects stop at once, the toggle keeps saying what you chose, and enforcement comes back on the first request after you delete the line.
Turning Force HTTPS off: what changes
If the proxy in front of your site starts reporting HTTPS from an address that is not in your Trusted proxy IPs, Force HTTPS stands down entirely: no redirect, no admin over SSL, no Secure cookies, nothing enforced at all, until you declare that proxy. That is deliberate. On a site whose proxy cannot be verified, each one of those three is a way to lock you out: the redirect loops, WordPress’s own admin redirect loops, and the authentication cookie gets written under a name WordPress will not read back, so nobody can stay signed in. The plugin says so in the admin while it lasts, and everything comes back by itself on the first request after you declare the proxy.
That notice shows you the address it saw, and it is an observation, not an instruction. Any visitor can make it appear by sending one header, so never add an address to Trusted proxy IPs because it appeared there: ask your host or your CDN which address their terminator uses, and add only that one. An address on that list is believed when it tells Login Armor who your visitors are, which is what every lockout and ban depends on. If the notice says several different addresses have sent that header, that is forgery rather than a proxy you forgot to declare.
Switching Force HTTPS on or off changes whether WordPress reads your session from its secure cookie or its ordinary one, so you may be asked to sign in again right after the change. That is normal, and it is the same thing WordPress does on its own when you move your site address to https.
Turning the toggle off removes exactly what Login Armor added: its HTTP to HTTPS redirect, its call to force_ssl_admin(), the Secure flag it put on the two authentication cookies, and the fact that a request forwarded by one of your declared proxies counted as HTTPS for the length of that request. It changes nothing else.
Two things it cannot take back, because they were never a setting of this plugin. If your site sends a Strict-Transport-Security header, this option is what made that header effective behind a proxy, and every browser that already received it keeps the pin for the header’s own duration, with the option on or off. And the redirect itself is sent with no-cache headers so that a CDN or a page cache does not keep serving it, but a cache that ignores those headers may still need to be purged. Your site address, your .htaccess, the FORCE_SSL_ADMIN constant in wp-config.php and any Strict-Transport-Security header stay exactly as they were. So if WordPress still sends the admin to https after you switch the toggle off, it is because the site address is already an https:// one or because FORCE_SSL_ADMIN is defined in wp-config.php, and neither of those belongs to this plugin.
FAQ
-
Will it lock me out of my own site?
-
Hide Login cannot: it always sends a one-time recovery URL to the admin email, so if you lose the slug, check your inbox. The plugin also honors
wp-cliso you can reset any of it from SSH, andwp login-armor rescueprints every way back in without changing anything.One option can, and it says so on its own row: Force HTTPS. It is off by default, it is never switched on by the safe baseline, and the plugin refuses to switch it on from a connection that is not already HTTPS. It also stands down by itself, and tells you so in the admin, if the proxy in front of your site starts reporting HTTPS from an address you have not listed in Trusted proxy IPs, which is what happens when a CDN or a load balancer changes address. If you still end up locked out, one command puts it back:
wp option patch update login_armor_hardening force_https false.If you cannot reach a shell either, there is a break-glass switch: add
define( 'LOGIN_ARMOR_SAFE_MODE', true );towp-config.php.wp-login.phpanswers again, the second factor is not demanded, the request firewall and the bot challenge drop back to logging only, and Force HTTPS stops enforcing all four of its effects, without any setting being rewritten. It is a constant and not an option, so it cannot be flipped from the database, and it is read once, while the plugin file loads: only code that runs before that can arm it, which meanswp-config.php, a must-use plugin, or a plugin that loads earlier. A theme, or anything running on a WordPress hook, cannot, because by then the answer is already fixed. Brute-force lockouts are deliberately left running: clear your own address from the admin notice, or withwp login-armor rescue --ip=<your ip> --yes. Delete the line to restore full protection. -
Does it slow my site down?
-
No. Everything is lazy-loaded and indexed. On a normal login flow the extra SQL cost is under 2 ms.
-
Is it compatible with Cloudflare / reverse proxies?
-
Yes. Choose the proxy header in Settings and list the exact IP addresses or CIDR ranges of the proxies that are allowed to supply it. Forwarding headers are ignored when the immediate network peer is not explicitly trusted.
-
Does it work with multisite?
-
Yes, subdomain and subfolder. Each site has its own modules, logs, and thresholds.
-
Can I use LoginArmor alongside Wordfence / iThemes Security / Solid Security?
-
Yes, but disable overlapping modules on one side to avoid double lockouts.
-
Where is the data stored?
-
Three custom tables in your own database: events, incidents, activity. Nothing leaves your server.
-
How do I copy my configuration to another site?
-
Settings > Export downloads every setting as a JSON file (webhook URLs only if you tick the box; the SIEM signing secret and users’ two-factor enrolments never leave the site). On the other site, Settings > Import shows you every change first and applies nothing until you confirm. From the command line:
wp login-armor settings export --file=model.json, thenwp login-armor settings import model.json --dry-runand--yes. One invalid value refuses the whole file, and a firewall or bot challenge switched on by import always starts in monitor mode. -
What are the .htaccess.login-armor.bak and .htaccess.login-armor.lock files?
-
They sit next to a
.htaccessfile that Login Armor writes into, inwp-content/uploadsor at the root of the site. The.bakfile is your restore point: a copy of the file as it was, taken once before the very first change and never overwritten afterwards. The.lockfile is empty; it exists only to stop two requests writing the same file at the same moment. Both names start with.ht, so a web server configured for WordPress never serves them to a visitor. Both are deliberately left in place when you uninstall the plugin: a backup that disappears with the plugin is not a backup. -
Is there a pro version?
-
Not currently. LoginArmor is fully free and open source. GPL forever.
-
Where can I report bugs or request features?
-
Support forum: wordpress.org/support/plugin/login-armor/.
Reviews
Contributors & Developers
“Login Armor” is open source software. The following people have contributed to this plugin.
ContributorsTranslate “Login Armor” into your language.
Interested in development?
Browse the code, check out the SVN repository, or subscribe to the development log by RSS.
Changelog
The three most recent releases are summarised here, because wordpress.org shows at most 5000 characters and silently truncates the rest. The complete history, with the reasoning behind each fix, is in CHANGELOG.md in the plugin’s repository.
2.7.7
After 2.7.6, every screen was measured again, down to each line of text: a box that clips what is too wide for it hides the defect from a test that only asks whether the page scrolls sideways. Stylesheets only, no setting and no behaviour changes.
- Fixed – Events and Activity: the two log tables now follow their own width instead of the window’s. On a phone the Events table cut off everything after the address, the account included. From 1101 to 1220 pixels of window the account, the browser and the age were printed over one another and the headings stood over the wrong columns. The Activity table lost its address column on most widths between 783 and 1220 pixels. Both now go down to fewer columns, then to one block per entry, and hide nothing a wide screen shows. The timeline of an incident gets the same treatment.
- Fixed – A long account name (an e-mail address), file name or IPv6 address now wraps inside its cell instead of running over the next one. In the Activity table that happened at every window width.
- Fixed – Incidents, Events, Activity: the guide panel no longer stays behind while the sponsored block slides over it; it scrolls with the page. The sponsored “Crash-Test” card no longer cuts its own text.
- Fixed – Firewall: the “Recent blocks” list printed stray indentation and blank lines between its entries, at every width.
- Fixed – Activity: the sentence of the log integrity bar now wraps; between 601 and 783 pixels its ellipsis hid when the log was last verified.
- Fixed – Keyboard: a switch reached with Tab is now brought fully clear of the save bar.
- Fixed – On a phone: the Overview status card, the facts panel, the Settings score card and the breach list no longer cut their text; a module’s name in Settings is no longer squeezed beside its button (48 pixels wide at 320); the incident detail, the import preview, the Hide Login activation dialog and the guided start no longer scroll sideways; the dashboard box no longer truncates “Last event”.
2.7.6
A user reported that the Settings tab could not be scrolled to its end. Measuring that report in a real browser found the same family of defect in several other places: something fixed to the window sitting on the page. Stylesheet only, nothing else changes.
- Fixed – The end of the Settings tab no longer stays under the “Unsaved changes” bar. The bar is fixed to the bottom of the window and 72 pixels high; the page only left it 60. With the bar up, the last 12 pixels could never be scrolled into view, and because the bar is translucent it looked as if the page went on. It only showed with panels open: folded, the page fits the window.
- Fixed – That bar now starts where the WordPress menu ends, at every width. It only knew the menu folded by hand. Under 960 pixels, where WordPress folds the menu itself, it kept a 160-pixel offset, and on a phone its label and buttons spilled out of it.
- Fixed – A notification raised while the bar is up no longer lands on it.
- Fixed – Keyboard: a field reached with Tab is no longer scrolled under the save bar (15 controls out of 80 were), nor under the top bar with Shift+Tab (13 out of 80). A link to a module no longer leaves its row hidden behind the top bar.
- Fixed – On a phone, none of the five tabs scrolls sideways any more: one grid column could not shrink below its content, which made the Settings column 630 pixels wide in a 390-pixel window. Under 720 pixels the live events of the Overview sat one column to the left of their headings. At 600 pixels and under, the top bar no longer hangs 46 pixels below the top of the window.
2.7.5
Removes the dashed segment 2.7.3 added to the activity chart, along with the mistaken reasoning behind it.
- Fixed – The activity chart no longer breaks off near its right-hand edge. 2.7.3 drew the final segment dashed and detached, on the belief that the last bucket was the clock hour in progress and therefore incomplete. That belief was wrong: the chart groups events into rolling sixty-minute windows counted back from the present moment, so every bucket is a whole hour, the last one included. There was nothing to mark, and marking it produced a gap and a floating stub with no legend anywhere to explain either. Readers took it for missing data, which is exactly what it looked like. The curve is now one continuous line across all twenty-four points, and the shaded area is derived from that same line so the two can never disagree again.
