Troubleshooting
Common MagicAuth failure modes and how to fix them.
Sign-in errors
"That sign-in link has expired or already been used"
Most common cause: the link is past its TTL (default 10 minutes), or it has been clicked more times than Max link uses (default 2).
What to do:
- Request a new email from the sign-in form.
- If a working link is being broken before the user clicks, check whether your inbox provider runs URL-prefetching for security scanning. The default
max_link_uses = 2is designed to absorb one prefetch. If your provider prefetches more, raise it in Settings → MagicAuth → General.
"That code is invalid or has expired"
The code path is single-use and harder than the link path:
- Codes burn on first successful submission, and burn after 5 wrong attempts.
- Codes are case-insensitive but treat
Oas0andI/Las1(Crockford normalisation), so misreads of similar glyphs still work. - The session that holds the email-to-code mapping expires after 30 minutes. After that, the user has to start over from state A.
Code typed correctly but bounced back to email-entry step
Symptom: the user types the right code, sees a moment of "loading", then ends up back on state A as if nothing happened. The token row is consumed in the database.
Cause (resolved in v1.0.3): the magicauth_session cookie was being stripped by a CDN, cache layer, or COOKIEPATH mismatch on subfolder installs. MagicAuth now also propagates the session id via URL (?magicauth_sid=…) and a hidden form field, so the cookie is not load-bearing.
If you're seeing this on v1.0.3 or later, file a bug at github.com/nolderoos/magicauth/issues with your hosting setup (CDN, page-cache plugin, custom COOKIEPATH).
Email not arriving
MagicAuth uses wp_mail, so deliverability follows your WordPress mail setup.
Diagnostic checklist
- Test it. Settings → MagicAuth → Diagnostics & Recovery → Send test email sends a sample to the logged-in admin without issuing a real token.
- Check spam folders. Magic-link emails contain a single big button and a short code, which is high signal for over-tuned spam filters. SPF, DKIM, and DMARC for your sending domain make a big difference.
- Use a real SMTP service. PHP
mail()from an unknown server is a common reason inboxes drop the email. WP Mail SMTP, Postmark, SendGrid, and similar services handle this well. - Check the WP error log. When
WP_DEBUG_LOGis on, MagicAuth logswp_mail returned false for {user_login}ifwp_mailrejected the send.
Routing through a transactional ESP
For per-recipient ESP integrations, the magicauth_email_send filter lets you short-circuit wp_mail and route through your own provider. See Email customisation / Route through a transactional ESP.
Throttle blocks
The visitor sees an amber toast naming the reason. Each throttle has a different remediation:
| Toast | Cause | Fix |
|---|---|---|
| "Please wait N seconds…" | Per-email cooldown (default 60s, configurable in Configuration). | Wait. The cooldown does not extend on retry. |
| "Too many sign-in requests from your network…" | Per-IP link cap (default 10/hour). | Wait the window out, or raise the cap. Shared NAT (offices, ISPs) is the common cause. |
| "Too many wrong codes from your network…" | Per-IP code cap (default 20/hour). | Same. |
| Password screen blocked | Per-IP password cap (5 / 15 min) or password-reset cap (5 / 60 min). | Wait or use a different IP. |
To clear all throttle counters site-wide as an admin: Settings → MagicAuth → Diagnostics & Recovery → Reset throttle counters. Works correctly under external object caches (Redis, Memcached, Object Cache Pro).
Lockout recovery
If you are locked out as an admin, work through these in order. Each requires less of MagicAuth than the last.
1. The visible password link
Every sign-in card includes a Sign in with password link unless explicitly turned off in settings. That link reveals an inline password field in the same shell. Sign in with your normal WordPress password.
2. ?magicauth=off
Append ?magicauth=off to your wp-login.php URL:
https://example.com/wp-login.php?magicauth=offThis sets a cookie scoped to /wp-login.php that disables the branded login replacement for your browser only. The default WordPress login form appears in its place. Other users continue to see the MagicAuth screen.
3. MAGICAUTH_DISABLE constant
Add this to wp-config.php above the /* That's all, stop editing! */ line:
define( 'MAGICAUTH_DISABLE', true );The plugin skips its Plugin::boot() entirely. The default WordPress login screen returns. Remove the line once you're back in.
Configuration issues
"Replace WordPress login screen" is greyed out
Cause: the safety check found placeholder salts in wp-config.php.
Fix:
- Visit api.wordpress.org/secret-key.
- Copy the eight
define()lines. - Paste them into
wp-config.php, replacing the existingAUTH_KEY,SECURE_AUTH_KEY,LOGGED_IN_KEY, andNONCE_KEYlines (and their salt counterparts). - Reload Settings → MagicAuth. The lock disappears.
The salt change invalidates existing user sessions. Everyone signs in again.
Branded login screen renders an empty card
Cause (resolved in v1.0.1): an overzealous CSS rule hid every <form> and <p> on body.login. Update to v1.0.1 or later.
Sign-in works but redirects to the wrong place
By default, admins go to wp-admin and other roles go to the homepage. To override:
- Site-wide: Settings → MagicAuth → General → After sign-in, send users to.
- Per-request or programmatic: hook the
magicauth_redirect_tofilter.
If a sign-in is silently redirecting to wp-login.php and then back to the form, you're hitting the post-1.0.2 guard that rejects wp-login.php as a destination, so the configured default fires instead. Adjust your redirect target.
Plugin conflicts
Caching plugins or CDN
Set-Cookie headers from wp-login.php are sometimes stripped by aggressive page caches. MagicAuth's session-id-via-URL fallback (v1.0.3+) handles the most common variant. If you still see issues, exclude these paths from your page cache:
wp-login.phpwp-admin/*- Any page that contains the
[magicauth_login]shortcode - The
?magicauth=verifyquery (if you serve from non-wp-login.phpURLs)
Security plugins (Wordfence, Limit Login Attempts)
These plugins generally hook wp_login_failed and wp_login. MagicAuth fires both, so they continue to count attempts and block bad actors. No special configuration is needed.
If you see double-counting (each magic-link sign-in counted as a "login"), that's the security plugin reacting to MagicAuth's wp_login action. Expected behaviour.
Still stuck?
File an issue at github.com/nolderoos/magicauth/issues with:
- Your WordPress version, PHP version, MagicAuth version.
- Whether you've enabled the
wp-login.phpreplacement. - Any caching, CDN, or object-cache setup.
- The exact toast text or error you're seeing.
- Anything in the WP error log when
WP_DEBUG_LOGis enabled.