fix(gallery): block password form in Instagram in-app browser and unmask login errors (#863)
* fix(gallery): block password form in Instagram in-app browser (#654) Field reports show gallery password login still failing inside Instagram's IAB after the #656 input-attribute/trim defenses. Three changes: - Replace the advisory amber banner with a red blocking state: the password form is hidden in the Instagram IAB and replaced with platform-specific "open in external browser" instructions plus a copy-link button (clipboard API with execCommand fallback). A "try anyway" link restores the form as an escape hatch. - Stop masking non-password failures as "incorrect password": a request that never got a response (offline, webview killed it) now reports a connection error, and a reCAPTCHA 400 reports a verification failure — both previously fell through to the wrong-password message and sent guests chasing the wrong cause. - Strip invisible Unicode (zero-width chars, word joiner, BOM, soft hyphen) from the submitted password in addition to trimming — these ride along when the password is copy-pasted out of a chat app and fail byte-exact bcrypt compare server-side. * fix(gallery): retry login with typed password + honor execCommand result (#654) Codex review round 1: - Stored passwords can legitimately contain the invisible code points the sanitizer strips (e.g. ZWJ emoji sequences) — creation paths don't normalize. On a 401 where the sanitized form differs from the typed (trimmed) input, retry once with the typed value. Skipped when a reCAPTCHA token is in play (single-use). - document.execCommand('copy') signals failure via its return value, not by throwing — only show "Link copied" when it returns true. * fix(gallery): move invisible-char password fallback server-side (#654) Codex review round 2: the client-side retry either burned the single-use reCAPTCHA token (making exotic-but-valid passwords impossible to enter with reCAPTCHA on) or burned failed-attempt lockout quota on every rescued login. Doing the fallback as a second bcrypt compare inside the same gallery/verify request eliminates both: exact bytes are compared first (stored passwords containing e.g. ZWJ emoji keep working), the sanitized form only on mismatch, and trackFailedAttempt only fires when both fail. Frontend goes back to plain trim-on-submit; the client-side sanitizer util and retry are removed. 7 integration tests pin the contract. --------- Co-authored-by: Paul Nothaft <[email protected]>
This commit is contained in:
co-authored by
Paul Nothaft
parent
9ac23e5fe1
commit
323dcae917
@@ -804,11 +804,16 @@
|
||||
"tooManyAttempts": "Zu viele fehlgeschlagene Anmeldeversuche. Bitte versuchen Sie es später erneut.",
|
||||
"pleaseEnterPassword": "Bitte geben Sie ein Passwort ein",
|
||||
"passwordHint": "Das Passwort wurde vom Veranstalter bereitgestellt. Kontaktieren Sie ihn, wenn Sie es nicht haben.",
|
||||
"networkError": "Verbindung fehlgeschlagen. Bitte prüfen Sie Ihre Internetverbindung und versuchen Sie es erneut.",
|
||||
"recaptchaFailed": "Sicherheitsprüfung fehlgeschlagen. Bitte laden Sie die Seite neu und versuchen Sie es erneut.",
|
||||
"iab": {
|
||||
"instagram": {
|
||||
"title": "Diesen Link im Browser öffnen",
|
||||
"ios": "Der eingebaute Browser von Instagram blockiert das Passwort-Login manchmal. Oben rechts auf das ⋯-Menü tippen und „Im externen Browser öffnen“ wählen (oder den Link kopieren und in Safari einfügen).",
|
||||
"android": "Der eingebaute Browser von Instagram blockiert das Passwort-Login manchmal. Oben rechts auf das ⋮-Menü tippen und „Im externen Browser öffnen“ wählen (oder den Link kopieren und in Chrome einfügen)."
|
||||
"blockedTitle": "Der Instagram-Browser kann diese Galerie nicht öffnen",
|
||||
"blockedIos": "Das Passwort-Login funktioniert im eingebauten Browser von Instagram nicht zuverlässig. Oben rechts auf das ⋯-Menü tippen und „Im externen Browser öffnen“ wählen — oder den Link kopieren und in Safari einfügen.",
|
||||
"blockedAndroid": "Das Passwort-Login funktioniert im eingebauten Browser von Instagram nicht zuverlässig. Oben rechts auf das ⋮-Menü tippen und „Im externen Browser öffnen“ wählen — oder den Link kopieren und in Chrome einfügen.",
|
||||
"copyLink": "Link kopieren",
|
||||
"linkCopied": "Link kopiert",
|
||||
"tryAnyway": "Passwort trotzdem hier eingeben"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -351,11 +351,16 @@
|
||||
"tooManyAttempts": "Too many failed login attempts. Please try again later.",
|
||||
"pleaseEnterPassword": "Please enter a password",
|
||||
"passwordHint": "The password was provided by the event organizer. Contact them if you don't have it.",
|
||||
"networkError": "Connection failed. Please check your internet connection and try again.",
|
||||
"recaptchaFailed": "Security verification failed. Please reload the page and try again.",
|
||||
"iab": {
|
||||
"instagram": {
|
||||
"title": "Open this link in your browser",
|
||||
"ios": "Instagram's built-in browser sometimes blocks the password login. Tap the ⋯ menu in the top right, then \"Open in external browser\" (or copy the link and paste into Safari).",
|
||||
"android": "Instagram's built-in browser sometimes blocks the password login. Tap the ⋮ menu in the top right, then \"Open in external browser\" (or copy the link and paste into Chrome)."
|
||||
"blockedTitle": "Instagram's browser can't open this gallery",
|
||||
"blockedIos": "Password login does not work reliably in Instagram's built-in browser. Tap the ⋯ menu in the top right and choose \"Open in external browser\", or copy the link and paste it into Safari.",
|
||||
"blockedAndroid": "Password login does not work reliably in Instagram's built-in browser. Tap the ⋮ menu in the top right and choose \"Open in external browser\", or copy the link and paste it into Chrome.",
|
||||
"copyLink": "Copy link",
|
||||
"linkCopied": "Link copied",
|
||||
"tryAnyway": "Try entering the password here anyway"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user