Ettic Docs
MagicAuth

Troubleshooting

Common MagicAuth failure modes and how to fix them.

Sign-in errors

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 = 2 is 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 O as 0 and I/L as 1 (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

  1. Test it. Settings → MagicAuth → Diagnostics & Recovery → Send test email sends a sample to the logged-in admin without issuing a real token.
  2. 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.
  3. 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.
  4. Check the WP error log. When WP_DEBUG_LOG is on, MagicAuth logs wp_mail returned false for {user_login} if wp_mail rejected 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:

ToastCauseFix
"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 blockedPer-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.

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=off

This 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:

  1. Visit api.wordpress.org/secret-key.
  2. Copy the eight define() lines.
  3. Paste them into wp-config.php, replacing the existing AUTH_KEY, SECURE_AUTH_KEY, LOGGED_IN_KEY, and NONCE_KEY lines (and their salt counterparts).
  4. 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_to filter.

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.php
  • wp-admin/*
  • Any page that contains the [magicauth_login] shortcode
  • The ?magicauth=verify query (if you serve from non-wp-login.php URLs)

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.php replacement.
  • 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_LOG is enabled.

On this page