fix(auth): scanner-proof password reset with button-gated verify and OTP-code fallback (#1100)
Corporate mail scanners (Microsoft Defender SafeLinks) follow links in auth emails and burn the one-shot recovery token before the user sees the mail (#1099, first hit: Deepgrid 2026-07-21, verify from an Azure IP 23s after send). /reset-password now has three entry modes: - set-password: recovery session exists (legacy /auth/callback links keep working unchanged) - confirm-link: the email link carries ?token_hash= and verification runs ONLY on an explicit button click; scanners render pages but do not click buttons, so the token survives scanning - enter-code: email + 6-digit {{ .Token }} code typed manually, the fallback when no link works at all The Supabase recovery email template switches to {{ .SiteURL }}/reset-password?token_hash={{ .TokenHash }} + {{ .Token }} AFTER this deploys (template content in the PR); the link then never touches gotrue's GET /verify endpoint, leaving nothing to detonate. Fixes #1099. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
335d908614
commit
3cb5ae7716
+15
-1
@@ -850,7 +850,21 @@
|
||||
"mismatch_title": "Passwords don't match",
|
||||
"mismatch_description": "Make sure you entered the same password in both fields.",
|
||||
"save_failed_title": "Could not save password",
|
||||
"save_failed_description": "Please try again."
|
||||
"save_failed_description": "Please try again.",
|
||||
"confirm_subtitle": "Confirm to continue to the password reset.",
|
||||
"confirm_button": "Continue",
|
||||
"confirm_verifying": "Verifying...",
|
||||
"confirm_hint": "For security, the link is only used when you click the button.",
|
||||
"code_subtitle": "Enter your email and the one-time code from the email.",
|
||||
"email_label": "Email address",
|
||||
"code_label": "One-time code",
|
||||
"code_placeholder": "6-digit code",
|
||||
"code_button": "Verify code",
|
||||
"code_verifying": "Verifying...",
|
||||
"code_hint": "The code is in the password reset email. If no email arrived, request a new reset from the login page.",
|
||||
"verify_failed_title": "Verification failed",
|
||||
"link_invalid_description": "The link is invalid or has already been used. Enter the one-time code from the email instead, or request a new reset.",
|
||||
"code_invalid_description": "The code is invalid or has expired. Check the code or request a new reset from the login page."
|
||||
},
|
||||
"customer_detail": {
|
||||
"back": "Back to customers",
|
||||
|
||||
+15
-1
@@ -850,7 +850,21 @@
|
||||
"mismatch_title": "Lösenorden matchar inte",
|
||||
"mismatch_description": "Kontrollera att du skrev samma lösenord i båda fälten.",
|
||||
"save_failed_title": "Kunde inte spara lösenordet",
|
||||
"save_failed_description": "Försök igen."
|
||||
"save_failed_description": "Försök igen.",
|
||||
"confirm_subtitle": "Bekräfta för att fortsätta till lösenordsåterställningen.",
|
||||
"confirm_button": "Fortsätt",
|
||||
"confirm_verifying": "Verifierar...",
|
||||
"confirm_hint": "Av säkerhetsskäl används länken först när du klickar på knappen.",
|
||||
"code_subtitle": "Ange din e-post och engångskoden från mailet.",
|
||||
"email_label": "E-postadress",
|
||||
"code_label": "Engångskod",
|
||||
"code_placeholder": "6-siffrig kod",
|
||||
"code_button": "Verifiera kod",
|
||||
"code_verifying": "Verifierar...",
|
||||
"code_hint": "Koden finns i mailet om lösenordsåterställning. Hittar du inget mail kan du begära en ny återställning från inloggningssidan.",
|
||||
"verify_failed_title": "Verifieringen misslyckades",
|
||||
"link_invalid_description": "Länken är ogiltig eller har redan använts. Ange engångskoden från mailet i stället, eller begär en ny återställning.",
|
||||
"code_invalid_description": "Koden är ogiltig eller har gått ut. Kontrollera koden eller begär en ny återställning från inloggningssidan."
|
||||
},
|
||||
"customer_detail": {
|
||||
"back": "Tillbaka till kunder",
|
||||
|
||||
Reference in New Issue
Block a user