fix: friendly message for expired/used magic-link errors - #57
Merged
Conversation
Better Auth redirects magic-link verify failures with a raw code (INVALID_TOKEN) in the error query param, overwriting the message we set in errorCallbackURL. Map known codes to human-friendly text at render time on the login pages.
Better Auth overwrites the error param with its own code, so the embedded message never reached the user. Keep the /login destination.
mroderick
marked this pull request as ready for review
August 6, 2026 09:32
Collaborator
|
Did we actually have a message before? IMO then code needs to be deleted too somewhere as the claim is "better-auth" is overwriting it. |
Collaborator
Author
Yes, it was in the url as |
Collaborator
Author
|
till
approved these changes
Aug 6, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Reusing an already-used magic link (or clicking an expired one) showed the raw error
INVALID_TOKENon the login page — not user-friendly.Root cause
The raw code isn't from our code. Better Auth's magic-link plugin consumes (deletes) the token on verification; for a reused/expired link the token is already gone, so it calls
redirectWithError("INVALID_TOKEN")(better-auth source). That helper doeserrorCallbackURL.searchParams.set("error", "INVALID_TOKEN"), overwriting whatever message we previously embedded inerrorCallbackURL. So our wording never reached the user.Fix
Map Better Auth error codes to human-friendly text at render time, independent of what code Better Auth sends:
src/app/utils/friendly-error.js— newfriendlyError(code)mappingINVALID_TOKEN(and a few siblings) to plain sentences; unknown codes pass through unchanged.src/app/routes/auth.js— apply the mapping inshowLoginandshowMagicLinkForm, and drop the now-dead embedded message fromerrorCallbackURL(its/logindestination is still required).INVALID_TOKENnow renders as: "This sign-in link has expired or already been used. Please request a new one."Tests
test/unit/friendly-error.test.js: mapping covers known codes, passes through unknown./login?error=INVALID_TOKENrenders the friendly sentence and not the raw code.