Problem
When the rate limiter blocks a POST submission, login_html() re-renders the 2FA form by calling authentication_page(). The email provider's authentication_page() always renders the "Resend Code" submit button (providers/class-two-factor-email.php line 374–376), so the button is visible and clickable even while the user is locked out.
The user sees:
- An error: "Too many invalid verification codes, try again in X minutes"
- A prompt: "A verification code has been sent to your email"
- A "Resend Code" button that appears functional
Clicking "Resend Code" while rate-limited produces the same rate-limit error again (since PR #917 moves the gate before pre_process_authentication()). No new email is sent, but the user has no way to know that — the form just reloads with the same error. A user who sees a "Resend Code" button will naturally try it when they think they didn't receive their code or their code expired, and hitting the same wall repeatedly with no explanation is confusing.
Expected behaviour
While the user is rate-limited, the "Resend Code" button should either:
- Not be rendered —
authentication_page() could receive or check the rate-limited state and omit the resend UI, or
- Be rendered as disabled — visible but clearly unavailable, ideally with a label indicating when it will become active again
Notes
authentication_page() currently has no awareness of rate-limit state; adding a check for Two_Factor_Core::is_user_rate_limited() inside the provider would couple it to core, which may not be desirable
- An alternative is to pass a flag through
login_html() → authentication_page() indicating that the form is in a locked state
- The "A verification code has been sent" prompt (line 360) is also shown unconditionally and may be misleading in this state
Related
Problem
When the rate limiter blocks a POST submission,
login_html()re-renders the 2FA form by callingauthentication_page(). The email provider'sauthentication_page()always renders the "Resend Code" submit button (providers/class-two-factor-email.phpline 374–376), so the button is visible and clickable even while the user is locked out.The user sees:
Clicking "Resend Code" while rate-limited produces the same rate-limit error again (since PR #917 moves the gate before
pre_process_authentication()). No new email is sent, but the user has no way to know that — the form just reloads with the same error. A user who sees a "Resend Code" button will naturally try it when they think they didn't receive their code or their code expired, and hitting the same wall repeatedly with no explanation is confusing.Expected behaviour
While the user is rate-limited, the "Resend Code" button should either:
authentication_page()could receive or check the rate-limited state and omit the resend UI, orNotes
authentication_page()currently has no awareness of rate-limit state; adding a check forTwo_Factor_Core::is_user_rate_limited()inside the provider would couple it to core, which may not be desirablelogin_html()→authentication_page()indicating that the form is in a locked stateRelated