fix(auth): en afvist passkey sagde "forkert e-mail eller adgangskode"
Release / Build and publish image (push) Failing after 10m0s

Der er hverken en e-mail eller en adgangskode i et passkey-login. Loginet er
discoverable — enheden ved selv, hvilken konto nøglen hører til, og der bliver
ikke tastet noget. Alligevel fik en afvisning fladens generiske 401-tekst, og den
nævner begge dele.

Det sendte en person ud at lede efter en tastefejl i sin konto, der aldrig havde
været der. Det, der faktisk var sket, var at instansen var flyttet fra http til
https: en passkey hører til præcis den adresse, den blev lavet på — `RPOrigins`
bygges af `VERDANDE_BASE_URL` med skema og alt — så et login på det ene skema mod
en server, der venter det andet, kan ikke verificeres.

Beskeden siger nu det, og siger også hvor man skal kigge. Serveren har hele tiden
svaret "that key was not accepted"; det var oversættelsen i fladen, der gjorde
den til noget andet.

Aflysning bliver behandlet som før — den er ikke en fejl, og en fejl for den ville
læse som om nøglen blev afvist.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Kristian Wind
2026-08-20 15:59:34 +02:00
co-authored by Claude Opus 5
parent ce1d27f8ca
commit b87c9ea6e2
4 changed files with 106 additions and 1 deletions
+11 -1
View File
@@ -59,7 +59,17 @@
} catch (e) {
// A cancelled prompt is not a failure. Somebody changed their mind, and
// an error for that reads as though the key was rejected.
if (e?.name !== 'NotAllowedError' && e?.message !== 'cancelled') {
if (e?.name === 'NotAllowedError' || e?.message === 'cancelled') {
// nothing to say
} else if (e?.code === 'unauthorized') {
// Not "wrong email or password". There is no email here and no
// password — the device signed, and the signature was refused. The
// generic 401 text sent somebody looking through their account for a
// typo that was never there; what had actually happened was that the
// site had moved from http to https, and a passkey is bound to the
// origin it was made on, scheme included.
error = t('passkey.notAccepted');
} else {
error = humanMessage(e);
}
} finally {
+2
View File
@@ -814,6 +814,8 @@ export const da = {
'passkey.hint':
'En nøgle på en enhed i stedet for en hemmelighed i et hoved. Den private halvdel forlader aldrig enheden, og signaturen er bundet til adressen — så en overbevisende kopi af login-siden et andet sted får ingenting.',
'passkey.unsupported': 'Denne browser understøtter ikke passkeys.',
'passkey.notAccepted':
'Nøglen blev ikke godtaget. Sker det for en nøgle, der virkede før, er adressen typisk skiftet — en passkey hører til præcis den adresse, den blev lavet på, skema og alt.',
'passkey.none': 'Ingen nøgler endnu.',
'passkey.name': 'Navn på nøglen',
'passkey.namePlaceholder': 'fx min bærbare',
+2
View File
@@ -807,6 +807,8 @@ export const en = {
'passkey.hint':
'A key on a device instead of a secret in a head. The private half never leaves the device, and the signature is bound to the address that asked for it — so a convincing copy of the sign-in page somewhere else gets nothing.',
'passkey.unsupported': 'This browser does not support passkeys.',
'passkey.notAccepted':
'That key was not accepted. If it worked before, the address has usually changed — a passkey belongs to the exact address it was made on, scheme and all.',
'passkey.none': 'No keys yet.',
'passkey.name': 'Name for the key',
'passkey.namePlaceholder': 'e.g. my laptop',