Skip to content

Email provider "Resend Code" button remains visible and interactive while user is rate-limited #920

Description

@dknauss

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:

  1. Not be renderedauthentication_page() could receive or check the rate-limited state and omit the resend UI, or
  2. 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

  • Issue #918 — rate-limit error message wording
  • PR #917 — rate-limit gate ordering fix

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    Status
    In progress

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions