Eine neue 'verwaltete' Authentifizierungsmethode zu Discourse hinzufügen

\nFortgesetzt von Future Social Authentication Improvements…\n\nWir sind nun dabei, alle Informationen zu „verknüpften Konten“ in einer einzigen Datenbanktabelle zusammenzuführen. Dies wird dazu beitragen, doppelte Logik erheblich zu reduzieren und zukünftig eine schnellere Entwicklung zu ermöglichen. Beispielsweise reduzierte die Migration unserer Kern-Twitter-Logik auf das neue System die Anzahl der Codezeilen von 136 auf nur 24 :tada:.\n\nDieser Beitrag ist nicht als Schritt-für-Schritt-Anleitung zum Hinzufügen eines neuen Authentifizierungsanbieters gedacht, sondern soll einen Überblick geben und bei Bedarf auf den relevanten Quellcode verweisen.\n\n## Einen Authenticator implementieren\n\nJeder Authenticator muss eine Unterklasse von Auth::Authenticator implementieren. Um die neue gemeinsame Logik zu nutzen, kann der Authenticator stattdessen von Auth::ManagedAuthenticator erben. Ein Beispiel für eine einfache Implementierung finden Sie im zentralen Facebook-Authenticator:\n\nhttps://github.com/discourse/discourse/blob/main/lib/auth/facebook_authenticator.rb\n\n`name`, enabled? und register_middleware müssen von implementierenden Klassen überschrieben werden.\n\n> :information_source: Nebenbemerkung: Für die Multisite-Kompatibilität ist es wichtig, dass alle sitespezifischen Informationen über eine setup-Lambda an Omniauth übergeben werden, anstatt zum Zeitpunkt der Definition festgelegt zu werden. Siehe alle Kern-Authenticators für Beispiele hierzu.\n\nDie gesamte Logik zum Verknüpfen externer Konten mit Discourse-Konten wird von Auth::ManagedAuthenticator gehandhabt. Dies setzt voraus, dass der Omniauth-Anbieter Daten im Format liefert, das in dessen Dokumentation definiert ist. Wenn eine Manipulation dieser Daten erforderlich ist, können Authenticator die Methode after_authenticate überschreiben und das auth_token nach Bedarf bearbeiten. Der zentrale Twitter-Authenticator entfernt beispielsweise alle extra-Informationen aus dem Token:\n\ndiscourse/lib/auth/twitter_authenticator.rb at b46b6e72d1906ca31e29855bda71f3498c8e203f · discourse/discourse · GitHub werden in der Datenbanktabelle user_associated_accounts gespeichert. provider_uid, info, credentials und extra werden direkt aus den von Omniauth zurückgegebenen Daten übernommen.\n\ndiscourse/app/models/user_associated_account.rb at b46b6e72d1906ca31e29855bda71f3498c8e203f · discourse/discourse · GitHub eine Authenticator-Klasse definiert wurde, muss sie registriert werden. Dies muss früh im Lebenszyklus der Anwendung geschehen und darf nicht innerhalb der after_initialize-Methode eines Plugins erfolgen. Die minimale Registrierung kann lediglich einen Verweis auf den Authenticator enthalten. In einem Plugin kann die Registrierung mit der Funktion auth_provider erfolgen. Zum Beispiel:\n\nrb\nauth_provider authenticator: OpenIDConnectAuthenticator.new()\n\n\nIm Kern erfolgt die Registrierung in discourse.rb. Eine vollständige Liste der möglichen AuthProvider-Optionen finden Sie hier. Inhaltlicher Text kann mit diesen Optionen definiert werden, aber es ist besser, lokalisierbare Zeichenketten in client.en.yml gemäß den Standard-Schlüsseln bereitzustellen. Zum Beispiel:\n\ndiscourse-openid-connect/config/locales/client.en.yml at 88fdf7b5ab624aba7c207e403665e0393334794a · discourse/discourse-openid-connect · GitHub[details=Zusätzliche Hinweise zu ManagedAuthenticator von @fantasticfears]\n\n## ManagedAuthenticator im Detail\n\nSie müssen möglicherweise an etwas Besonderem für die Authentifizierung arbeiten. Und Sie möchten mehr über ManagedAuthenticator erfahren. Im Grunde hat es mehrere Operationen, Optionen und steuert, wie die Daten verwendet werden.\n\nDiscourse verwaltet Benutzerinformationen mit zwei Controllern. Users::OmniauthCallbacksController verwaltet die Nutzlast, sobald die OAuth2-Authentifizierung abgeschlossen ist. after_authenticate wird hier aufgerufen. can_connect_existing_user? wird hier ebenfalls verwendet.\nEs gibt einige private Methoden, die Sie lesen können, um zu verstehen, wie verschiedene Datenfelder funktionieren.\n\nrb\nif authenticator.can_connect_existing_user? && current_user\n @auth_result = authenticator.after_authenticate(auth, existing_account: current_user)\nelse\n @auth_result = authenticator.after_authenticate(auth)\nend\n\n\nUsersController hat revoke_account, das can_revoke? und revoke verwendet. Aber damit die revoke-Methode remote funktioniert, müssen Sie Ihre eigene Implementierung erstellen.\n\nUserAuthenticator ist eine Service-Klasse, die hilft, Benutzer zu authentifizieren (E-Mail-Bestätigung oder OAuth2-Pfad überprüfen).\nafter_create_account wird hier aufgerufen.\n\nDie Kernlogik bleibt bei after_authenticate mit der Datenklasse Auth::Result. Wir folgen der Datenstruktur hier. extra_data wird an after_create_account übergeben, um zugehörige Datensätze zu erstellen.\n\nrb\nresult.extra_data = {\n provider: auth_token[:provider],\n uid: auth_token[:uid],\n info: auth_token[:info],\n extra: auth_token[:extra],\n credentials: auth_token[:credentials]\n}\n\n\nEs wird versuchen, ein bestehendes Konto abzugleichen und damit zu verknüpfen.\n\nSie fragen sich vielleicht, warum eine automatische Kontoerstellung möglich ist, es aber kein User.create gibt. Dies geschieht in UsersController#create.\n\nrb\nauthentication = UserAuthenticator.new(user, session)\n\n\nDer Benutzer ist eine frische Instanz, die mit Sitzungsdaten gefüllt wird, die vom Auth-Anbieter vorbereitet wurden. Glauben Sie mir, es ist reine Magie.\n[/details]\n\n—\n\n### Migration zum neuen System\n\nUm einen nahtlosen Übergang zum neuen System zu gewährleisten, sollten Daten aus dem alten Speicherort migriert werden. Bei zentralen Authentifizierungsanbietern können dies dedizierte Tabellen sein. Bei Plugins kann dies plugin_store_rows oder oauth2_user_infos sein. Die Mindestdaten, die in einem user_associated_accounts-Datensatz erforderlich sind, sind provider_name, provider_uid und user_id. Ein Beispiel für eine Migration finden Sie hier:\n\nhttps://github.com/discourse/discourse/blob/main/db/migrate/20181207141900_migrate_twitter_user_info.rb\n\nSobald das ManagedAuthenticator-System mit Version v2.2.0 auf den stabilen Branch veröffentlicht wurde, werden wir mit der Migration der offiziellen Authentifizierungs-Plugins beginnen. Zu diesem Zeitpunkt wird hier ein Beispiel für eine plugin_store_row-Migration hinzugefügt.\n\n\n—\n\n\u003csmall\u003eDieses Dokument wird versioniert – schlagen Sie Änderungen auf github vor.\u003c/small\u003e

23 „Gefällt mir“

@david Die hier geleistete Arbeit ist super cool. Ich schätze sie sehr. Ich hatte auch die Gelegenheit, mit GitHub - discourse/discourse-development-auth: A discourse plugin which adds a fake authentication provider. For development purposes only. zu spielen, was sehr praktisch ist.

Nur eine Einschränkung: Die Funktion funktioniert nicht gut (öffnet nicht das Anmelde-Popup) mit dem Ember CLI lokal. Ich habe mir den Kopf zerbrochen, als ich ein Plugin zum Hinzufügen eines Authentifizierungsanbieters schrieb, und plötzlich fiel mir ein, NO_EMBER_CLI=1 zu verwenden, und alles funktionierte.

7 „Gefällt mir“

Ich würde gerne erfahren, ob die Implementierung eines Authentifikators der richtige Weg ist, um

Verstehe ich richtig, dass alle registrierten Authentifikatoren früh in der App aufgerufen werden, sodass ich dort testen könnte, ob ein Benutzername und ein Hinweis zur E-Mail-Authentifizierung in der URL enthalten sind und als Antwort ein Formular “Senden Sie mir einen Login-Link” rendern könnte?