Login Alerts
Emails a user when their account is signed in to from a device WordPress has not seen before, and shows the sessions WordPress already records so a single one can be ended.
by George Vasiliades · github.com/poseidonas/login-alerts · website
Install
The author publishes release zips, so WP-CLI can install straight from GitHub:
wp plugin install https://github.com/poseidonas/login-alerts/releases/download/v1.0.0/login-alerts.zipDeclares an update source (https://github.com/Poseidonas/login-alerts), so updates arrive through the plugin's own updater.
Readme
Login Alerts
Emails a user when their account is signed in to from a device WordPress has not seen before, and shows the sessions WordPress already records so a single one can be ended.
- Author: George Vasiliades - https://github.com/Poseidonas
- License: GPL-2.0-or-later
- Requires WordPress 6.7+ and PHP 8.0+
What it does
WordPress already stores, for every session it opens, the IP address, the browser, the moment of signing in and the moment the session expires. It has stored them since version 4.0. It never shows them anywhere. The only control it offers is a single button, Log Out Everywhere Else, which ends every other session at once and tells you nothing about what those sessions were.
WordPress also never tells anyone that their account has been signed in to.
This plugin closes both gaps and nothing else:
- An alert when an account is signed in to from a device that account has not used before.
- A list of sessions on the profile screen, with the ability to end one specific session.
It notifies, it does not block. It is not a firewall, it is not a login limiter and it is not a replacement for a strong password or two factor authentication. It tells you that something happened.
What counts as a new device
Alerting on every new IP address is useless: a phone changes address several times a day and the owner would learn to ignore the messages. Alerting only on a new browser is worse, because an attacker using the same browser would never trigger anything.
A device is therefore identified by a salted hash of two things together:
- the network the request came from, meaning the first three parts of an IPv4 address (a
/24) or the first 48 bits of an IPv6 address (a/48); - the browser string the request sent.
A different address inside the same network does not alert. A different network, a different provider, a different country or a different browser does. Only the hash is stored, never the address it was made from.
What is stored, and for how long
Nothing is stored for accounts whose role is not in the alert list. For the rest, per account:
- The hash described above.
- The address with its last part removed, for example
203.0.113.x, so the message can say something useful. - A short description of the browser, for example
Chrome on Windows. - The moment the device was first seen and the moment it was last seen.
Up to 20 devices are kept per account by default, oldest dropped first, and any device unused for 180 days is forgotten. Both numbers are settings.
The plugin registers itself with the WordPress personal data exporter and eraser, so a privacy request made through Tools, Export Personal Data or Erase Personal Data includes and removes this information automatically.
Settings
Settings > Login Alerts.
Alerts
| Setting | Effect | Default |
|---|---|---|
| Alert on a new device | The main switch for sign-in alerts | On |
| Roles that are alerted | Only accounts holding one of these roles are alerted, and only for them is anything stored | Administrator, Editor |
| Copy the site address for administrator sign-ins | Sends the same message to the site administration address when the account is an administrator | Off |
| Quiet period per account | Minutes. At most one alert per account in this period, between 1 and 1440 | 15 |
On a shop with thousands of customer accounts, adding Customer to the role list turns a few messages a month into a few thousand. The setting says so on the page.
Failed attempts
| Setting | Effect | Default |
|---|---|---|
| Alert on repeated failed attempts | One message to the site administration address. Nothing is blocked, no account is locked | Off |
| Attempts before alerting | Failures for the same user name, between 3 and 100 | 10 |
| Within this many minutes | The counter resets after this long, and after an alert is sent. Between 1 and 1440 | 15 |
This is off by default because a site on the open internet sees failed attempts constantly. The counter lives in a transient keyed by a hash of the user name, so nothing is written to the database permanently, and the message never reveals whether the account exists.
Addresses and retention
| Setting | Effect | Default |
|---|---|---|
| Trust a proxy header | None, X-Forwarded-For, CF-Connecting-IP, X-Real-IP, True-Client-IP or X-Cluster-Client-IP |
None |
| Devices remembered per account | Between 1 and 100 | 20 |
| Forget a device after | Days without use, between 1 and 3650 | 180 |
Behind Cloudflare or an nginx proxy, the address WordPress sees belongs to the proxy, so every visitor looks the same and no device ever looks new. The fix is to read the header the proxy sets. Trusting a header that no proxy sets is a security hole, because anyone can send it and claim any address, which is why the default is to trust none.
The settings page prints three rows so the choice can be verified: the address used for alerts, the address the web server reports, and the network being compared. Compare the first with your own address.
Sessions
| Setting | Effect | Default |
|---|---|---|
| Show sessions on the profile screen | Lists the sessions WordPress records and allows one to be ended | On |
The table shows the browser, the address without its last part, when the session started and when it expires. The session you are using is marked and cannot be ended from there, since that is what the Log Out link is for. Anyone who can edit a user sees that user's table on their profile screen as well, gated on the edit_user capability, and every action carries a nonce. A session token itself is never displayed; only the SHA-256 verifier WordPress stores is used, and it is validated against ^[a-f0-9]{64}$ before anything happens.
Ending a single session requires reading the session_tokens user meta directly, because WP_Session_Tokens::get_all() discards the keys that identify each session and the public API only offers destroy-all or destroy-others. If another plugin replaces the session manager through the session_token_manager filter, the table says so and does nothing rather than touching storage it does not understand.
Filters
icxcnika_login_settings- all settings before they are applied.icxcnika_login_should_alert- receives a boolean and theWP_User, and decides whether that sign-in is alerted.icxcnika_login_alert_body- receives the message body, theWP_User, the address and the browser string.icxcnika_login_registry_payload- data sent to the installation registry.
Data stored
- Option
icxcnika_login_settings(the settings). - Option
icxcnika_login_registry_key(random installation key of 48 characters, created only if installation reporting is active). - User meta
icxcnika_login_devices(the known devices for that account). - User meta
icxcnika_login_last_alert(the moment of the last alert, for the quiet period). - Transients
icxcnika_login_fail_*(failed attempt counters, only while the failed attempt alert is on). - Transient
icxcnika_login_release(cached GitHub release lookup, 12 hours). - Cron event
icxcnika_login_registry_ping(weekly, only if installation reporting is active).
The message is composed in the language of the account it is sent to, not the language of the site.
Installation reporting
On activation, on deactivation and once a week the plugin sends a small JSON message to the author's installation registry: plugin slug, plugin version, home URL, site URL, WordPress version, WooCommerce version if present, PHP version, locale and whether the site is a multisite. Each report carries a random installation key generated locally on first use. The reporting address is empty by default, which means nothing is sent at all. No addresses, no user names, no content and no personal data are ever sent to the author. Add define( 'ICXCNIKA_REGISTRY_DISABLE', true ); to wp-config.php to turn the reporting off, or define( 'ICXCNIKA_REGISTRY_URL', '...' ); to point it elsewhere.
Updates
Updates are delivered from GitHub Releases of this repository. WordPress shows them on the Plugins screen like any other update, together with the details view and the automatic updates link.
Uninstall
Deleting the plugin removes both options, both user meta keys from every account, the release transient and any failed attempt counters, and clears the cron event. The sessions WordPress itself records are left exactly as they are, because they belong to WordPress and not to this plugin.
Login Alerts (Ελληνικά)
Στέλνει email στον χρήστη όταν γίνει σύνδεση στον λογαριασμό του από συσκευή που δεν έχει ξαναδεί το WordPress, και εμφανίζει τις συνεδρίες που ήδη καταγράφει το WordPress ώστε να μπορεί να τερματιστεί μία συγκεκριμένη.
- Δημιουργός: George Vasiliades - https://github.com/Poseidonas
- Άδεια: GPL-2.0-or-later
- Απαιτεί WordPress 6.7+ και PHP 8.0+
Τι κάνει
Το WordPress αποθηκεύει ήδη, για κάθε συνεδρία που ανοίγει, τη διεύθυνση IP, τον browser, τη στιγμή της σύνδεσης και τη στιγμή που λήγει η συνεδρία. Τα αποθηκεύει από την έκδοση 4.0. Δεν τα εμφανίζει πουθενά. Ο μόνος έλεγχος που προσφέρει είναι ένα κουμπί, Log Out Everywhere Else, που τερματίζει όλες τις άλλες συνεδρίες μαζί και δεν σας λέει τίποτα για το τι ήταν αυτές.
Το WordPress επίσης δεν ενημερώνει ποτέ κανέναν ότι έγινε σύνδεση στον λογαριασμό του.
Αυτό το πρόσθετο καλύπτει αυτά τα δύο κενά και τίποτα άλλο:
- Ειδοποίηση όταν γίνεται σύνδεση σε λογαριασμό από συσκευή που δεν έχει ξαναχρησιμοποιηθεί.
- Λίστα συνεδριών στην οθόνη προφίλ, με δυνατότητα τερματισμού μιας συγκεκριμένης.
Ειδοποιεί, δεν εμποδίζει. Δεν είναι firewall, δεν περιορίζει προσπάθειες σύνδεσης και δεν αντικαθιστά έναν ισχυρό κωδικό ή την ταυτοποίηση δύο παραγόντων. Σας λέει ότι κάτι συνέβη.
Τι θεωρείται νέα συσκευή
Η ειδοποίηση σε κάθε νέα IP είναι άχρηστη: ένα κινητό αλλάζει διεύθυνση αρκετές φορές την ημέρα και ο κάτοχος θα μάθαινε να αγνοεί τα μηνύματα. Η ειδοποίηση μόνο σε νέο browser είναι χειρότερη, επειδή ένας επιτιθέμενος με τον ίδιο browser δεν θα πυροδοτούσε ποτέ τίποτα.
Μια συσκευή αναγνωρίζεται λοιπόν από ένα hash με salt δύο στοιχείων μαζί:
- το δίκτυο από το οποίο ήρθε το αίτημα, δηλαδή τα τρία πρώτα μέρη μιας διεύθυνσης IPv4 (ένα
/24) ή τα πρώτα 48 bit μιας IPv6 (ένα/48)· - τη συμβολοσειρά του browser που έστειλε το αίτημα.
Διαφορετική διεύθυνση μέσα στο ίδιο δίκτυο δεν ειδοποιεί. Διαφορετικό δίκτυο, διαφορετικός πάροχος, διαφορετική χώρα ή διαφορετικός browser ειδοποιεί. Αποθηκεύεται μόνο το hash, ποτέ η διεύθυνση από την οποία φτιάχτηκε.
Τι αποθηκεύεται και για πόσο
Δεν αποθηκεύεται τίποτα για λογαριασμούς των οποίων ο ρόλος δεν είναι στη λίστα ειδοποιήσεων. Για τους υπόλοιπους, ανά λογαριασμό:
- Το hash που περιγράφηκε παραπάνω.
- Η διεύθυνση χωρίς το τελευταίο της τμήμα, για παράδειγμα
203.0.113.x, ώστε το μήνυμα να λέει κάτι χρήσιμο. - Μια σύντομη περιγραφή του browser, για παράδειγμα
Chrome σε Windows. - Η στιγμή που πρωτοεμφανίστηκε η συσκευή και η στιγμή που εμφανίστηκε τελευταία φορά.
Διατηρούνται έως 20 συσκευές ανά λογαριασμό από προεπιλογή, με τις παλαιότερες να αφαιρούνται πρώτες, και κάθε συσκευή που δεν έχει χρησιμοποιηθεί για 180 ημέρες ξεχνιέται. Και οι δύο αριθμοί είναι ρυθμίσεις.
Το πρόσθετο δηλώνεται στον εξαγωγέα και τον διαγραφέα προσωπικών δεδομένων του WordPress, οπότε ένα αίτημα μέσω Εργαλεία, Εξαγωγή Προσωπικών Δεδομένων ή Διαγραφή Προσωπικών Δεδομένων περιλαμβάνει και αφαιρεί αυτές τις πληροφορίες αυτόματα.
Ρυθμίσεις
Ρυθμίσεις > Login Alerts.
Ειδοποιήσεις
| Ρύθμιση | Ενέργεια | Προεπιλογή |
|---|---|---|
| Ειδοποίηση σε νέα συσκευή | Ο κύριος διακόπτης των ειδοποιήσεων σύνδεσης | Ενεργό |
| Ρόλοι που ειδοποιούνται | Ειδοποιούνται μόνο λογαριασμοί με έναν από αυτούς τους ρόλους, και μόνο για αυτούς αποθηκεύεται οτιδήποτε | Διαχειριστής, Αρχισυντάκτης |
| Αντίγραφο στη διεύθυνση του site για συνδέσεις διαχειριστή | Στέλνει το ίδιο μήνυμα και στη διεύθυνση διαχείρισης όταν ο λογαριασμός είναι διαχειριστής | Ανενεργό |
| Περίοδος ησυχίας ανά λογαριασμό | Λεπτά. Το πολύ μία ειδοποίηση ανά λογαριασμό σε αυτό το διάστημα, από 1 έως 1440 | 15 |
Σε ένα eshop με χιλιάδες λογαριασμούς πελατών, η προσθήκη του ρόλου Πελάτης μετατρέπει λίγα μηνύματα τον μήνα σε μερικές χιλιάδες. Η ρύθμιση το δηλώνει στη σελίδα.
Αποτυχημένες προσπάθειες
| Ρύθμιση | Ενέργεια | Προεπιλογή |
|---|---|---|
| Ειδοποίηση σε επανειλημμένες αποτυχίες | Ένα μήνυμα στη διεύθυνση διαχείρισης. Δεν μπλοκάρεται τίποτα, δεν κλειδώνεται λογαριασμός | Ανενεργό |
| Προσπάθειες πριν την ειδοποίηση | Αποτυχίες για το ίδιο όνομα χρήστη, από 3 έως 100 | 10 |
| Μέσα σε τόσα λεπτά | Ο μετρητής μηδενίζεται μετά από αυτό το διάστημα και μετά την αποστολή ειδοποίησης. Από 1 έως 1440 | 15 |
Είναι ανενεργό από προεπιλογή επειδή ένα site στο ανοιχτό διαδίκτυο βλέπει αποτυχημένες προσπάθειες συνεχώς. Ο μετρητής ζει σε transient με κλειδί ένα hash του ονόματος χρήστη, οπότε δεν γράφεται τίποτα μόνιμα στη βάση, και το μήνυμα δεν αποκαλύπτει ποτέ αν ο λογαριασμός υπάρχει.
Read the full README on GitHub →
Releases
| Tag | Published | Asset | Downloads |
|---|---|---|---|
| v1.0.0 | Aug 19, 2026 | login-alerts.zip | 1 |