Customers Can’t Log In
The portal shows WooCommerce’s own login, registration and lost password forms in its design, so WordPress and WooCommerce still check every password. When a customer cannot log in, the cause is usually the credentials, a bot check, a cached page or a security plugin. Start with the message the customer sees.
Messages and what they mean#
| Message | Where | Cause and fix |
|---|---|---|
| WooCommerce’s “unknown email address” or “incorrect password” error | Login page | The email, username or password is wrong. Ask the customer to use Lost your password? |
| The email address or password is incorrect. | Account drawer | Same as above. The drawer uses one message for both so it does not reveal which accounts exist. |
| CAPTCHA verification failed. Please try again. | Login, registration, lost password, drawer | The bot check failed. See CAPTCHA Problems. |
| Please complete the CAPTCHA verification. | Drawer | The customer sent the form before the widget was done. |
| Too many failed sign-in attempts. Please wait a few minutes and try again. | Drawer | The drawer’s limit on failed sign-ins was reached (see below). |
| Security check failed. Please refresh and try again. | Drawer | The drawer’s security token was rejected. Reload the page. If it repeats for everyone, see Caching below. |
| A security plugin’s lockout message | Anywhere | Another plugin (firewall, limit-login plugin) blocked the attempt. Check that plugin’s log. |
| Nothing happens, the login page just reloads | Login page | Usually a cached login page with an expired security token. See Caching below. |
Email-only login#
Email-Only Login (WooCommerce > Account Portal > General, on by default) renames WooCommerce’s “Username or email address” label to “Email address” and rewords the lost password text to match. It only changes the labels: WordPress still accepts a username or an email address. The registration form’s own “Username” field (shown when WooCommerce does not create usernames automatically) keeps its name.
If customers do not know a username, that is expected with this option: they should enter their email address. To have WooCommerce create usernames for new customers automatically, use the account options in WooCommerce > Settings > Accounts & Privacy, as the option’s label suggests.
Resetting a password#
The lost password page uses WooCommerce’s own handler, so every step stays in the portal design: after sending the form the customer sees WooCommerce’s “reset link sent” confirmation, and the link in the email opens the “set a new password” form inside the portal. If the email does not arrive, check that your site sends email (an SMTP plugin helps) and look in the customer’s spam folder.
Caching#
Each WooCommerce login form carries a security token. If the account page is served from a page cache or CDN for too long, the token in it expires, and WooCommerce ignores the login: the page reloads with no error. A cached page can also show the login form to a customer who is already logged in.
Exclude the account page from every cache. See Changes Don’t Show (Caching).
The account drawer fetches a fresh token each time, so it keeps working on cached pages.
Drawer sign-in limits#
The account drawer counts failed sign-ins for 15 minutes: at most 10 per account name and 20 per visitor IP address. After that it shows “Too many failed sign-in attempts.” until the 15 minutes pass. Password resets from the drawer are limited to 3 emails per address and 10 requests per IP address in 15 minutes; over the limit the drawer shows the usual “sent” message, but no email goes out.
Behind Cloudflare or another proxy#
If your server sees the proxy’s address instead of the visitor’s, many customers share one “IP” and reach the per-IP limit together. Ideally your host restores the real visitor IP at server level. Otherwise, return it with the wap_client_ip filter (child theme’s functions.php or a code snippets plugin):
add_filter( 'wap_client_ip', function ( $ip ) {
// Cloudflare sends the visitor's IP in this header.
if ( ! empty( $_SERVER['HTTP_CF_CONNECTING_IP'] ) ) {
$real = filter_var( wp_unslash( $_SERVER['HTTP_CF_CONNECTING_IP'] ), FILTER_VALIDATE_IP );
if ( $real ) {
return $real;
}
}
return $ip;
} ); Only trust this header when all traffic really comes through Cloudflare. Otherwise a visitor could send a fake header to dodge the limit.
You can change the limits with the wap_login_rate_limits filter (per_user, per_ip, window in seconds; 0 turns a limit off) and wap_reset_rate_limits (per_email, per_ip, window):
add_filter( 'wap_login_rate_limits', function ( $limits ) {
$limits['per_ip'] = 50;
return $limits;
} ); These limits apply to the account drawer only. The login page itself relies on WooCommerce, your CAPTCHA and any security plugin.
Nahnu Login Shield#
With Nahnu Login Shield (recommended) chosen as the provider, Login Shield checks the forms and can add two-factor login, passkeys and email login links to the portal. If a customer gets stuck:
- Two-factor code: the customer must enter the code from their authenticator app or email. If the email code does not arrive, check that your site sends email (an SMTP plugin helps).
- Which forms are protected: the Login Shield status list in the CAPTCHA / Spam tab shows whether Login Shield is active, whether its bot check is set up and which My Account forms it protects. A form Login Shield does not protect has no bot check.
- Old version: “Login Shield is too old for the portal. Update to 1.0.10 or later.” means the portal does not use Login Shield until you update it.

Checklist#
- Ask for the exact message, the page (account page or drawer) and the time.
- Try the same login yourself in a private window.
- Reset the customer’s password from Users if needed.
- Temporarily set the CAPTCHA Provider to None (disabled) to rule it out, then turn it back on.
- Check security plugin logs for a block.
- Purge all caches.
Related#
Was this helpful?
Thanks for your feedback!
✓ Feedback received. Thank you!