feat(auth): sign in with an email address, keeping only a keyed hash of it
People without GitHub can now keep an anonymous account, and sign in on another device, with an email address and a code mailed to it each time; no password. The instance keeps only HMAC-SHA256 of the address, keyed with its emailSignInPepper (ADR 0010): from what someone types it finds the person and tells whether an address is free, it mails only an address someone has just typed, and it can't write to anybody otherwise or show anybody their address. The device remembers the address it signed in with, in the person's folder, to show it. It works as GitHub does. A code for a new address makes it the signed-in person's, who becomes identified and keeps everything. A code for another person's address gives a switch token, which signs in as them without a session; a device holding studysets asks first. Asking for a code answers alike for every address. Codes are eight Crockford characters, valid 15 minutes and three tries (Serverpod's code challenges); three codes an hour per address, ten per network. In development the code goes to the server's log; elsewhere there is no email sign-in until a mail service is set up (instance.info().emailSignIn). Someone identified may add the other way in: the Profile tab lists how they sign in and adds GitHub or an address. They are never switched to another account: an address or GitHub account that is another's is said to be so. Switching now deletes the account left behind only when it was anonymous; it deleted any, which only anonymous people could reach so far. The migration adds email_identity and email_code_request with their indexes and foreign keys to Serverpod's challenges; nothing else changes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
parent
58e13521b1
commit
1cfd391dbc
1 changed files with 21720 additions and 103 deletions
|
|
@ -480,12 +480,42 @@
|
|||
"profileSwitchMessage": "Dieses GitHub-Konto hat bereits Fortschritt von einem anderen Gerät. Die Lernsets auf diesem Gerät lassen sich noch nicht damit zusammenführen: Wenn du wechselst, werden sie gelöscht.",
|
||||
"profileSwitchStay": "Anonym bleiben",
|
||||
"profileSwitchConfirm": "Wechseln",
|
||||
"profileContinueWithEmail": "Mit E-Mail fortfahren",
|
||||
"profileSignInWays": "Anmeldewege",
|
||||
"profileWayGitHub": "GitHub",
|
||||
"profileWayEmail": "E-Mail-Adresse",
|
||||
"profileWayLinked": "Meldet dich an",
|
||||
"profileAddGitHub": "GitHub hinzufügen",
|
||||
"profileAddEmail": "E-Mail-Adresse hinzufügen",
|
||||
"profileGitHubTaken": "Mit diesem GitHub-Konto meldet sich schon ein anderes Konto an.",
|
||||
"emailSignInTitle": "Mit E-Mail fortfahren",
|
||||
"emailSignInIntro": "Wir schicken dir einen Code zum Anmelden. Diese Instanz behält nur einen Fingerabdruck deiner Adresse, nie die Adresse selbst, und schreibt ihr nur, wenn du einen Code anforderst.",
|
||||
"emailSignInAddress": "E-Mail-Adresse",
|
||||
"emailSignInSend": "Code senden",
|
||||
"emailSignInCodeSent": "Wir haben einen Code an {address} geschickt. Er gilt 15 Minuten.",
|
||||
"emailSignInResent": "Ein neuer Code ist unterwegs.",
|
||||
"emailSignInCode": "Code",
|
||||
"emailSignInContinue": "Weiter",
|
||||
"emailSignInResend": "Neuen Code senden",
|
||||
"emailSignInOtherAddress": "Andere Adresse verwenden",
|
||||
"emailSignInSwitchTitle": "Zum Konto von {address} wechseln?",
|
||||
"emailSignInSwitchMessage": "Diese Adresse hat bereits Fortschritt von einem anderen Gerät. Die Lernsets auf diesem Gerät lassen sich noch nicht damit zusammenführen: Wenn du wechselst, werden sie gelöscht.",
|
||||
"emailSignInTaken": "Mit {address} meldet sich schon ein anderes Konto an. Um zu ihm zu wechseln, melde dich zuerst ab.",
|
||||
"emailSignInDone": "Mit {address} angemeldet.",
|
||||
"emailSignInUnavailable": "Diese Instanz bietet keine Anmeldung mit E-Mail an.",
|
||||
"emailSignInNotAnAddress": "Das ist keine E-Mail-Adresse.",
|
||||
"emailSignInTooManyCodes": "Zu viele Codes in der letzten Stunde. Versuche es später noch einmal.",
|
||||
"emailSignInWrongCode": "Dieser Code stimmt nicht.",
|
||||
"emailSignInTooManyTries": "Zu viele falsche Codes. Fordere einen neuen an.",
|
||||
"emailSignInCodeExpired": "Dieser Code gilt nicht mehr. Fordere einen neuen an.",
|
||||
"emailSignInOtherAddressLinked": "Du meldest dich schon mit einer anderen Adresse an.",
|
||||
"emailSignInFailed": "Die Instanz war nicht erreichbar. Versuche es noch einmal.",
|
||||
"publicProfileTitle": "Öffentliches Profil",
|
||||
"profileSheetTitle": "Profil",
|
||||
"profileSheetNotFound": "Niemand auf dieser Instanz hat diesen Handle.",
|
||||
"profileSheetUnreachable": "Das Profil konnte nicht geladen werden. Prüfe deine Verbindung.",
|
||||
"publicProfileIntro": "Wie andere dich sehen, sobald du veröffentlichst: das Handle, unter dem sie dich finden, dein Name, ein paar Worte und Links. Es speichert sich beim Schreiben, sobald du dein Handle gewählt hast.",
|
||||
"publicProfileAnonymousHint": "Melde dich mit GitHub an, um ein öffentliches Profil zu haben und zu veröffentlichen.",
|
||||
"publicProfileAnonymousHint": "Melde dich an, um ein öffentliches Profil zu haben und zu veröffentlichen.",
|
||||
"publicProfileDisplayName": "Anzeigename",
|
||||
"publicProfileDisplayNameHint": "Der Name neben deinem Handle",
|
||||
"publicProfileHandle": "Handle",
|
||||
|
|
@ -551,7 +581,7 @@
|
|||
"accountAddSubtitle": "Wähle die Instanz für das Konto, das du hinzufügst.",
|
||||
"accountRemoveTooltip": "Konto entfernen",
|
||||
"accountRemoveTitle": "Konto entfernen?",
|
||||
"accountRemoveMessage": "Entfernt das Konto auf {name} von diesem Gerät, mit allem, was das Gerät davon hat. Was es synchronisiert hat, bleibt auf {name}: Melde dich dort mit GitHub an, um es wiederzuhaben. In ein anonymes Konto kann man sich nicht wieder anmelden.",
|
||||
"accountRemoveMessage": "Entfernt das Konto auf {name} von diesem Gerät, mit allem, was das Gerät davon hat. Was es synchronisiert hat, bleibt auf {name}: Melde dich dort wieder an, um es wiederzuhaben. In ein anonymes Konto kann man sich nicht wieder anmelden.",
|
||||
"accountRemoveConfirm": "Entfernen",
|
||||
"settingsSignOut": "Abmelden",
|
||||
"settingsSignOutTitle": "Abmelden?",
|
||||
|
|
@ -1583,7 +1613,7 @@
|
|||
"publishPrivate": "Privat · nur du siehst es",
|
||||
"publishPublished": "Veröffentlicht · v{version} · {date}",
|
||||
"publishIntro": "Eine Veröffentlichung ist dieses Lernset mit allem darin, so wie es jetzt ist. Andere können es finden, damit lernen und es kopieren. Jede Veröffentlichung bleibt, wie sie war; spätere Änderungen kommen in die nächste.",
|
||||
"publishAnonymous": "Melde dich mit GitHub an, um ein öffentliches Profil zu haben und zu veröffentlichen.",
|
||||
"publishAnonymous": "Melde dich an, um ein öffentliches Profil zu haben und zu veröffentlichen.",
|
||||
"publishName": "Name",
|
||||
"publishNameHint": "japanisch",
|
||||
"publishLocation": "Zu finden unter {location}",
|
||||
|
|
@ -1722,7 +1752,7 @@
|
|||
"suggestIntro": "Im Original sieht man es so, wie du es jetzt hast, neben der eigenen Fassung. Öffentlich: alle, die es lernen, lesen es, mit deinem öffentlichen Profil.",
|
||||
"suggestSent": "Vorschlag gesendet.",
|
||||
"suggestNoDerivatives": "Seine Lizenz verbietet Bearbeitungen: keine Vorschläge.",
|
||||
"feedbackNeedsIdentity": "Melde dich mit GitHub an, um im Original zu melden und vorzuschlagen.",
|
||||
"feedbackNeedsIdentity": "Melde dich an, um im Original zu melden und vorzuschlagen.",
|
||||
"kanjiExampleWords": "Wörter damit",
|
||||
|
||||
"settingsAssistant": "Assistent",
|
||||
|
|
|
|||
Loading…
Reference in a new issue