major
#30041
Self-Service-Konten: Einladungen verfallen und ihre Annahme wird protokolliert; Einladungen können in der React-Benutzeroberfläche angenommen und verwaltet werden; lokalisierte E-Mail-Vorlagen
Siehe auch: #29092 (Mehrfaktor-Authentifizierung und Self-Service), #30039 (Fehler bei der Anmeldung und beim Zurücksetzen des Passworts), #29961 (Aufteilung von „tl-security-selfservice-core“, vor diesem Ticket zusammengeführt).
Hintergrund
Das Modul „tl-security-selfservice“ ermöglicht es einem Administrator, eine Person per E-Mail einzuladen (tl.security.selfservice:Invitation, TL-Script sendInvitation); die eingeladene Person öffnet den Link, bestätigt einen per E-Mail gesendeten Code und legt das Konto an. Ein Benutzer kann außerdem das Passwort oder den zweiten Authentifizierungsfaktor mit einem per E-Mail gesendeten Code zurücksetzen. Die React-View-Schicht (com.top_logic.layout.view.selfservice) bot lediglich die Passwortzurücksetzung an.
Eine Einladung lief nie ab, es wurde weder erfasst, wer sie gesendet hatte, noch wann, und sie wurde gelöscht, sobald sie angenommen wurde, sodass die Administration nicht zwischen offenen, abgelaufenen und verwendeten Einladungen unterscheiden konnte. Ihr Link-Token hatte eine Länge von 128 Bit. Eine Anwendung mit der React-Benutzeroberfläche konnte Einladungen weder annehmen noch verwalten.
Verhalten
Lebenszyklus einer Einladung
- Eine Einladung hat einen Status – offen, abgelaufen oder angenommen – und zeigt an, wann und von wem sie erstellt wurde (entnommen aus dem Erstellungs-Commit, also auch bei bestehenden Einladungen), bis wann sie gültig ist und – sobald sie angenommen wurde – wann sie angenommen wurde und welches Konto daraus erstellt wurde. Angenommene Einladungen werden als Datensatz aufbewahrt, anstatt gelöscht zu werden.
- Die Gültigkeitsdauer wird im „InvitationModule“ konfiguriert (Option „invitation-validity“, Standardwert 7 Tage) und beginnt ab dem Zeitpunkt, zu dem die Einladung gespeichert wird. Eine abgelaufene Einladung kann nicht mehr angenommen werden; durch erneutes Versenden erhält sie einen neuen Link und eine neue Gültigkeitsdauer. Eine angenommene Einladung kann weder erneut versendet noch widerrufen werden.
- Nur offene Einladungen werden bei der Überprüfung berücksichtigt, ob eine Adresse nur einmal eingeladen wurde.
- Das Link-Token besteht aus 32 zufälligen Bytes (256 Bit).
- Das Authentifizierungsgerät, auf dem eine akzeptierte Einladung das Konto erstellt, wird im InvitationModule konfiguriert (Option „authentication-device“, Standardwert „dbSecurity“).
- Der Link führt zu der im InvitationModule konfigurierten Seite (Option invitation-link); ihr Host ist die konfigurierte öffentliche Adresse der Anwendung (tl_host) oder, falls keine vorhanden ist, der Host der aktuellen Anfrage.
- Ein Verifizierungscode wird nach drei falschen Eingaben ungültig; wiederholte Codeanfragen werden gedrosselt. Ohne konfigurierte E-Mail-Adresse wird kein Code versendet (und auch keiner ins Protokoll geschrieben); die Anfrage wird mit einer Meldung abgelehnt.
React-Benutzeroberfläche
- Der Einladungslink einer Anwendung mit tl-layout-view-selfservice führt zur React-Seite „accept-invitation.view.xml“ (ein anonymer Einstiegspunkt): Dort wird der Grund für eine unbekannte, abgelaufene oder bereits angenommene Einladung angegeben; bei einer offenen Einladung fordert die eingeladene Person den E-Mail-Code an, gibt ihn ein und gibt anschließend Name und Passwort ein. Das neue Konto durchläuft die Anmeldeschritte des React-Logins (z. B. Einrichtung einer erforderlichen zweiten Authentifizierungsstufe) und wird angemeldet.
- Die React-Administration verfügt über die Registerkarte „Einladungen“ (Administration -> Zugriffskontrolle): alle Einladungen mit Status, Gültigkeit, Erstellungsdatum, Annahme und Konto; einladen (erstellen und versenden), erneut versenden, widerrufen.
- tl-demo-react enthält den React-Self-Service.
Klassische Benutzeroberfläche
- Die klassischen Dialoge akzeptieren Einladungen über dieselben Vorgänge; unbekannte, abgelaufene und akzeptierte Links zeigen den Grund dafür an. Der Dialog „Einladungen“ (früher „Offene Einladungen“) listet alle Einladungen mit ihrem Status auf und versendet sie erneut oder widerruft sie.
E-Mail-Vorlagen
- Die E-Mail-Vorlagen (Einladungs-E-Mail, Bestätigungs-E-Mail, Passwort-Zurücksetzen-E-Mail, MFA-Zurücksetzen-E-Mail) sind lokalisiert (Betreff und Text auf Deutsch und Englisch, in der Sprache des aktuellen Benutzers oder der Standardsprache der Anwendung) und werden als HTML versendet; der Tippfehler „Verficationcode“ wurde korrigiert.
- Die Bestätigungs-E-Mail einer Einladung erreicht die eingeladene Adresse: Das Skript wird ohne Zugriffsprüfung ausgeführt, da zum Zeitpunkt des Versands niemand angemeldet ist (zuvor wurde sie an eine leere Adresse gesendet).
Kleine Korrekturen
- „CreateLoginHoook“ wurde in „CreateLoginHook“ umbenannt.
- Die JavaDoc von MfaRequirement.DISABLED besagt, dass das Konto keinen zweiten Faktor verwenden darf und keinen aktivieren kann.
- Migrationsskripte: Ein in <dropped-dependencies> (#30065) aufgeführtes Modul wird nicht mehr durch frühere Migrationen des Moduls als Abhängigkeit hinzugefügt – weder als transitive Abhängigkeit noch als anfängliche, wenn das Modul in der Anwendung vorhanden ist. Zuvor hatte <dropped-dependencies> keine Wirkung, sobald eine frühere Migration des Moduls von dem entfernten Modul abhängig war.
Technische Hinweise
- InvitationModule (in tl-security-selfservice-core) bietet die UI-unabhängigen Operationen createInvitation, findInvitation / findOpenInvitation / refusal, acceptInvitation (Gültigkeitsprüfung, Konto auf dem konfigurierten Gerät mit dessen Passwortrichtlinie, createCallback, als angenommen markieren – in einer Transaktion), renewInvitation, resendInvitation, invitationLink, sendInvitation, sendVerificationMail. TL-Script: sendInvitation (in das Kernmodul verschoben), invitationRenew, invitationResend, invitationRefusal.
- „VerificationCode“ (Kern) generiert und überprüft die Codes der Einladung sowie der klassischen und der React-Passwortzurücksetzung.
- Der Standardwert für „expires“ wird in der Erstellungstransaktion berechnet (isComputedInTransaction), sodass ein durch einen Dialog erstellter Entwurf sein Ablaufdatum erhält, sobald er gespeichert wird.
- LoginFlow.LANDING_PAGE (tl-layout-view): Ein Login-Eintrag gibt die Seite an, die das Fenster nach der Anmeldung lädt; die Einladungsseite nutzt diesen Eintrag, sodass der neue Benutzer nicht zum Einladungslink zurückgeleitet wird.
- Datenmigration Ticket_30041_invitation_lifecycle: Erweitert die Spalte für das Token und weist bestehenden Einladungen ein Ablaufdatum zu (Zeitpunkt der Aktualisierung plus Gültigkeitsdauer der Einladung).
- Der Entwicklerartikel „Authentifizierung/Self-Service“ beschreibt den Lebenszyklus, die Optionen und beide Benutzeroberflächen.
Außerhalb des Geltungsbereichs
- Das Zurücksetzen des zweiten Authentifizierungsfaktors per Self-Service in der React-Benutzeroberfläche hängt von #30039 Punkt 2 ab (eine Passwortzurücksetzung darf den zweiten Authentifizierungsfaktor nicht umgehen) und ist Teil von #30039 (Punkt 8).
- Für den Self-Service geplante und beschlossene Funktionen: E-Mail-Code als Anmeldefaktor (#30182) und offene Selbstregistrierung (#30183) sind erwünscht und haben eigene Tickets. Nicht gewünscht: eine Passwortzurücksetzung, bei der das Konto anhand der E-Mail-Adresse gesucht wird (bei der Zurücksetzung wird das Konto anhand des Benutzernamens identifiziert), sowie Einladungen zum Hinzufügen zu einem bestehenden Konto (eine Adresse, die bereits ein Konto hat, kann nicht eingeladen werden).
- Ein Konto mit einem optionalen zweiten Authentifizierungsfaktor wird nach dem Annehmen einer Einladung in der React-Benutzeroberfläche nicht zur Einrichtung angeboten, wie dies beispielsweise nach jeder Passwortanmeldung in React der Fall ist.
- Die React-Registrierungsansicht „mfa-enroll.view.xml“ zeigt bereits das Geheimnis zur manuellen Eingabe an.
Test
- TestInvitationLifecycle (tl-security-selfservice-core): Das Annehmen einer abgelaufenen oder bereits angenommenen Einladung wird abgelehnt und führt nicht zur Erstellung eines Kontos; das Annehmen einer gültigen Einladung erstellt das Konto auf dem konfigurierten Gerät, markiert die Einladung als angenommen und registriert das Konto; erneuern und erneut senden; das Token umfasst 32 Byte; die Eindeutigkeitsprüfung ignoriert abgelaufene und akzeptierte Einladungen; der Link mit und ohne öffentliche Adresse; die Gültigkeitsdauer beginnt mit dem Speichern eines Entwurfs. TestMigrationUtil (com.top_logic): Abhängigkeiten wurden entfernt, auch wenn das Modul vorhanden ist.
- tl-demo-react (E-Mail an einen lokalen SMTP-Sink): Administration -> Zugriffskontrolle -> Einladungen: einladen, E-Mail mit dem Link zur React-Seite versenden, Annahme im abgemeldeten Zustand (Code, Konto, Anmeldung; bei erforderlichem zweiten Faktor dessen Einrichtung), die Einladung wird dann als angenommen angezeigt; zweite Einladung und Einladung eines bestehenden Kontos abgelehnt; abgelaufene Einladung erneut versenden; widerrufen. tl-demo: dasselbe in der klassischen Benutzeroberfläche (Verwaltung -> Berechtigungen -> Benutzerverwaltung, „Nutzer einladen“, „Einladungen“).
Migration
- Die Login-Hook-Klasse `com.top_logic.security.selfservice.invitation.CreateLoginHook ` wird in ` CreateLoginHook` umbenannt. Das Modul konfiguriert sich selbst; eine Anwendung, die in ihrer eigenen Konfiguration (z. B. in <login-hooks> von MainLayout$GlobalConfig) oder im Code auf die Klasse verweist, muss den neuen Namen verwenden.
- Code, der ` CreateAccountDialog ` erstellt, übergibt keinen Fortsetzungsbefehl mehr.
- Die Ressourcenschlüssel ERROR_NO_INVITATION__ID, UPDATED_INVITATION_CODE und DELETED_INVITATION von com.top_logic.security.selfservice.invitation.I18NConstants wurden entfernt; eine Anwendung, die diese überschreibt, muss sie entfernen.
- Eine Anwendung, die die klassischen Layouts „admin/security/accounts/existingInvitations/*“ oder „admin/security/accounts/inviteUsers/dialog.layout.xml“ im Layout-Editor geändert hat, behält ihre gespeicherte Kopie bei und wendet die neuen Spalten und Befehle darauf erneut an.
- Code, der sendInvitation für eine nicht geöffnete Einladung aufruft, löst einen Fehler aus; eine abgelaufene Einladung wird mit invitationResend erneut versendet.
- Bestehende Einladungen erhalten automatisch ein Ablaufdatum (Zeitpunkt der Aktualisierung plus Gültigkeitsdauer der Einladung).