Skip to content

fix(identity): find the pending 2fa cookie by better-auth's own cookie name - #404

Merged
okapitula merged 1 commit into
devfrom
fix/two-factor-pending-cookie-name
Nov 6, 2026
Merged

okapitula merged 1 commit into
devfrom
fix/two-factor-pending-cookie-name

Conversation

@okapitula

Copy link
Copy Markdown
Collaborator

Summary

  • 2FA verify and code resend find the pending-challenge cookie by the name better-auth gives it, so sign-in with a second factor works over HTTPS.

Why

The lookup matched better-auth.two_factor exactly. Over HTTPS better-auth sets the cookie as __Secure-better-auth.two_factor, so the lookup found nothing: POST /identity/2fa/verify answered 401 Invalid two-factor challenge after better-auth had already accepted the code, the failed-attempt lockout was never counted, and every pending verify shared the verify2fa:anonymous rate-limit bucket. Tests run over plain HTTP, so they never saw the prefixed name.

The name now comes from createAuthCookie('two_factor') on the auth context, which applies the configured cookie prefix and the __Secure- prefix the same way the two-factor plugin does when it sets the cookie. The exact-name match stays, so a look-alike *.two_factor cookie still cannot change the challenge identity or the rate-limit key.

Alternatives considered

  • Matching both better-auth.two_factor and __Secure-better-auth.two_factor: still breaks under a custom cookiePrefix or a per-cookie name override.
  • Going back to a .two_factor suffix match: reopens the junk-cookie rate-limit churn the exact match closed.

Risks

None. Plain-HTTP deployments resolve the same name as before.

…e name

Over HTTPS better-auth names the pending challenge cookie
`__Secure-better-auth.two_factor`, which the exact match on
`better-auth.two_factor` never found. Verify then rejected a code better-auth
had already accepted, skipped the lockout count, and keyed every pending
attempt on the shared anonymous rate-limit bucket.

Derive the name from `createAuthCookie('two_factor')` on the auth context so
the cookie prefix and secure prefix match what the two-factor plugin sets,
keeping the exact-name match against look-alike cookies.

@jakubfilinger-b jakubfilinger-b left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The cookie lookup now follows Better Auth’s configured cookie name, including the HTTPS prefix. The regression tests cover verification and rate limiting.

@okapitula
okapitula added this pull request to the merge queue Nov 6, 2026
Merged via the queue into dev with commit f2398e9 Nov 6, 2026
7 checks passed
@okapitula
okapitula deleted the fix/two-factor-pending-cookie-name branch November 6, 2026 10:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants