Zum Hauptinhalt springen

Steam OAuth und Telegram OAuth mit Casdoor: Hinzufügen von Non-Standard-Social-Logins über OIDC

· 10 Minuten Lektüre
Yang Luo
Casdoor Maintainer

Es gibt kein "Steam OAuth": Steam authentifiziert Benutzer mit OpenID 2.0 und liefert Ihnen eine 64-Bit-SteamID, sonst nichts. Das klassische Login Widget von Telegram ist auch kein OAuth: Es übergibt Ihrer Seite eine Reihe von Benutzerfeldern plus einen HMAC-SHA256-Hash, den Sie mit Ihrem Bot-Token überprüfen. Telegram betreibt jetzt auch einen echten OpenID Connect Provider unter oauth.telegram.org. Wenn Sie Casdoor zwischen Ihre App und diese Anbieter schalten, führt Casdoor die protokollspezifischen Prüfungen durch, und Ihre App spricht nur noch OpenID Connect mit Casdoor, genau wie sie es bei Google oder GitHub tun würde.

Die Anbieter im Überblick​

AnbieterProtokollWas identifiziert den BenutzerE-Mail verfügbar?Casdoor-Anbietertyp
SteamOpenID 2.0 unter https://steamcommunity.com/openid/login, plus die Steam Web API für das ProfilSteamID64, extrahiert aus der Claimed ID https://steamcommunity.com/openid/id/<steamid>NeinSteam
Telegram (Login Widget)Signierte Widget-Daten, HMAC-SHA256 mit dem SHA-256-Hash des Bot-Tokens als SchlüsselTelegram-Benutzer-idNeinTelegram
Telegram (OpenID Connect)OIDC Authorization Code Flow mit PKCE unter https://oauth.telegram.orgsub-Claim des ID-TokensKein E-Mail-Claim; Telefon mit dem phone ScopeCustom
X (Twitter)OAuth 2.0 Authorization Code mit PKCEX-Benutzer-ID von /2/users/meNicht mit Casdoors Standard-ScopesTwitter
FacebookOAuth 2.0 Authorization CodeApp-scoped Benutzer-IDNur wenn das Profil eine gültige primäre E-Mail hatFacebook

Der Rest dieses Beitrags erläutert, was jedes Protokoll tatsächlich zurückgibt und was Casdoor damit macht.

Steam: OpenID 2.0, kein OAuth​

Steams Entwicklerseiten beschreiben Steam als OpenID-Provider: Ihre Website sendet den Benutzer an Steam, und Steam sendet eine Claimed ID der Form https://steamcommunity.com/openid/id/<steamid> zurück. Die Zahl am Ende ist die 64-Bit-SteamID des Benutzers. Es gibt keinen Authorization Code, kein Access Token, keine Scopes und keine E-Mail: Weder die OpenID-Antwort noch das Web-API-Profil enthalten eine.

Deshalb führen Suchen nach "steam oauth" nirgendwohin Nützliches: Das Protokoll ist OpenID 2.0, der Vorläufer von OpenID Connect, sodass eine OAuth 2.0- oder OIDC-Client-Bibliothek nicht direkt mit Steam sprechen kann.

Was Casdoor bei einem Steam-Login tut:

  1. Die Casdoor-Anmeldeseite erstellt eine OpenID 2.0 checkid_setup-Anfrage an https://steamcommunity.com/openid/login, wobei openid.realm auf die Casdoor-Origin und openid.return_to auf Casdoors /callback-Seite gesetzt wird.
  2. Wenn Steam zurückleitet, postet Casdoor die signierten Felder mit openid.mode=check_authentication zurück an Steam. Nur wenn Steam is_valid:true antwortet, geht es weiter. Es prüft auch, ob openid.claimed_id dem Muster steamcommunity.com/openid/id/<digits> entspricht, und extrahiert die SteamID daraus.
  3. Mit dem Steam Web API Key, den Sie als Client secret des Anbieters eingeben, ruft Casdoor ISteamUser/GetPlayerSummaries auf, um den Persona-Namen und den Avatar zu erhalten.

Der resultierende Casdoor-Benutzer hat die SteamID64 als Benutzernamen, den Steam-Persona-Namen als Anzeigenamen und den Steam-Avatar. Das E-Mail-Feld bleibt leer. Casdoor verwirft bewusst den Platzhaltertext, den die zugrunde liegende Bibliothek dort einfügt. Wenn Ihre App eine E-Mail-Adresse benötigt, erfassen Sie diese nach der Registrierung.

Die Einrichtung dauert zwei Minuten: Registrieren Sie einen Web-API-Schlüssel für Ihre Casdoor-Domain auf der Schlüssel-Seite von Steam, erstellen Sie einen Provider vom Typ Steam und fügen Sie den Schlüssel als Client Secret ein. Die Steam-Provider-Anleitung enthält die Schritte.

Telegram: Das Login Widget und seine HMAC-Prüfung​

Der klassische Telegram-Login ist ein JavaScript-Widget. Sie erstellen einen Bot mit @BotFather, verknüpfen Ihre Domain damit über /setdomain und betten das Widget ein. Wenn der Benutzer in Telegram bestätigt, leitet das Widget entweder zur URL in data-auth-url weiter oder ruft eine JavaScript-Funktion auf und übergibt id, first_name, last_name, username, photo_url, auth_date und hash.

Nichts in dieser Nutzlast ist ein Token. Jeder kann diese Felder in eine URL eingeben, daher muss der Server den hash überprüfen. Die dokumentierte Prüfung von Telegram funktioniert wie folgt:

data_check_string = all received fields except hash,
as key=value, sorted by key, joined with "\n"
secret_key = SHA256(bot_token)
valid = hex(HMAC_SHA256(data_check_string, secret_key)) == hash

Telegram weist Sie auch an, auth_date zu überprüfen, damit alte Daten nicht erneut abgespielt werden können, lässt aber das Zeitfenster Ihnen überlassen.

In Casdoor nimmt der Provider-Typ Telegram den Bot-Benutzernamen (ohne @) als Client ID und den Bot-Token als Client secret. Wenn ein Benutzer auf die Telegram-Schaltfläche klickt, öffnet Casdoor seine eigene Seite /telegram-login, die telegram-widget.js von telegram.org mit Ihrem Bot-Benutzernamen lädt und data-auth-url auf Casdoors /callback zeigt. Der Callback sammelt die Felder, und das Casdoor-Backend führt dann Folgendes aus:

  • Erstellt die Datenprüfzeichenkette aus allen Feldern außer hash neu, sortiert sie und vergleicht den HMAC-SHA256 gegen hash unter Verwendung von SHA256(bot token) als Schlüssel;
  • Verwirft die Daten, wenn auth_date älter als 24 Stunden ist;
  • Verwendet die numerische Telegram-id als Identität, den username als Benutzernamen, den Vor- und Nachnamen als Anzeigenamen und photo_url als Avatar.

Telegram-Benutzernamen sind optional. Wenn ein Benutzer keinen hat, generiert Casdoor telegram_<id>, was sich bei jeder Anmeldung gleich bleibt. Das Widget sendet nie eine E-Mail-Adresse oder Telefonnummer, daher hat ein Telegram-only-Benutzer in Casdoor weder noch etwas davon. Siehe die Telegram-Provider-Anleitung für die BotFather-Schritte.

Telegram bietet jetzt auch OpenID Connect an​

Die Seite "Log In With Telegram" von Telegram dokumentiert jetzt einen Standard-OpenID-Connect-Flow, und die Dokumentation des alten iframe-Widgets wurde auf eine Archivseite verschoben. Die Fakten aus den Telegram-Dokumenten:

  • Discovery-Dokument: https://oauth.telegram.org/.well-known/openid-configuration. Autorisierungsendpunkt https://oauth.telegram.org/auth, Token-Endpunkt https://oauth.telegram.org/token, Schlüssel unter https://oauth.telegram.org/.well-known/jwks.json.
  • In @BotFather öffnen Sie die Einstellungen für das Login Widget Ihres Bots, registrieren die erlaubten URLs (Origins und exakte Redirect URIs) und erhalten eine Client ID und ein Client Secret.
  • Authorization Code Flow, PKCE mit S256 empfohlen. Die Token-Anfrage verwendet HTTP Basic Authentication mit Client ID und Secret.
  • Scopes: openid ist erforderlich; profile fügt den Namen, preferred_username und picture hinzu; phone fügt phone_number mit Zustimmung des Benutzers hinzu. Es gibt keinen E-Mail-Anspruch (claim).
  • Es gibt keinen UserInfo-Endpunkt. Alle Benutzerdaten befinden sich im ID-Token, dessen iss https://oauth.telegram.org ist und dessen aud Ihre Bot-ID ist.

Sie können diesen Flow mit einem Casdoor Custom OAuth Provider verbinden. Setzen Sie die Auth URL und Token URL auf die oben genannten Endpunkte, setzen Sie Scope auf openid profile (fügen Sie phone hinzu, wenn Sie es benötigen), aktivieren Sie Enable PKCE und lassen Sie UserInfo URL leer. Registrieren Sie Casdoors https://<your-casdoor-host>/callback als erlaubte URL in BotFather. Ohne UserInfo URL nimmt Casdoor den Benutzer aus dem ID-Token in der Token-Antwort: Es erfordert sub, lehnt ein abgelaufenes Token ab und prüft, ob aud die Client ID enthält. Ohne Benutzer-Mapping wird sub zur Benutzer-ID, preferred_username zum Benutzernamen, name zum Anzeigenamen und picture zum Avatar, und phone_number füllt das Telefonfeld. Die Casdoor-Anmeldeseite erkennt einen Custom Provider, dessen Auth URL auf oauth.telegram.org zeigt, und hält den OAuth state dafür kurz.

Beachten Sie, dass ein Telegram-Benutzer, der über das Widget angemeldet ist, und dieselbe Person, die über OIDC angemeldet ist, nicht automatisch derselbe Casdoor-Benutzer sind. Die Widget-Identität ist die numerische id, während die OIDC-Identität sub ist, und Telegrams eigene Beispiele zeigen unterschiedliche Werte für die beiden. Wählen Sie eine Methode pro Anwendung.

X (Twitter) und Facebook​

Diese beiden sind gewöhnliches OAuth 2.0, aber jedes hat ein Detail, das man kennen sollte.

X erfordert einen PKCE-Challenge auf seiner OAuth 2.0 Authorize-URL. Casdoors Twitter-Typ generiert für jede Anmeldung einen neuen Code Verifier, sendet die S256-Challenge und übergibt den Verifier beim Token-Austausch, sodass nichts Konfiguriert werden muss außer Client ID und Secret. Casdoor fordert die Scopes users.read tweet.read an und liest den Benutzer aus /2/users/me, was die Benutzer-ID, den Handle und den Anzeigenamen liefert. Es wird kein E-Mail-Feld angefordert, also planen Sie für X-Benutzer ohne E-Mail-Adresse. Die Twitter-Provider-Anleitung deckt die App-Einstellungen ab.

Facebook gibt eine app-scoped Benutzer-ID zurück: Dieselbe Person hat eine andere ID in jeder Facebook-App, sodass ein Wechsel zu einer neuen Facebook-App bedeutet, dass Ihre Benutzer nicht mit ihren alten Datensätzen übereinstimmen, es sei denn, Sie verknüpfen sie per E-Mail. Casdoor fragt email,public_profile an und liest id, name, picture und email aus der Graph API. Facebook lässt email weg, wenn das Profil keine gültige Adresse hat. Siehe die Facebook-Provider-Anleitung.

Wie Ihre App dies alles sieht: Plain OIDC​

Ihre Anwendung kommuniziert nie direkt mit Steam, Telegram, X oder Facebook. Sie ist ein OIDC-Client von Casdoor und wird einmalig mit dem Casdoor-Issuer konfiguriert: https://<your-casdoor-host>/.well-known/openid-configuration. Sie fügen die Social-Anbieter zur Casdoor-Anwendung im Tab Providers hinzu, und deren Schaltflächen erscheinen auf der Casdoor-Anmeldeseite.

Nach jeder dieser Anmeldungen sucht oder erstellt Casdoor einen Casdoor-Benutzer und schließt den normalen Authorization Code Flow mit Ihrer App ab. Das ID-Token, das Ihre App erhält, ist von Casdoor signiert, und sein sub ist die Casdoor-Benutzer-ID, nicht die SteamID oder die Telegram-ID. Daher benötigt Ihre App keine OpenID 2.0-Bibliothek, keinen HMAC-Code, keine PKCE-Besonderheiten pro Anbieter und keine Sonderbehandlung für Benutzer ohne E-Mail-Adresse. Die ursprüngliche Anbieter-ID wird im Casdoor-Benutzer gespeichert, beispielsweise im Feld steam oder telegram, falls Sie sie jemals benötigen.

Einige Punkte, die Sie einplanen sollten:

  • Kontoverknüpfung. Casdoor verknüpft eine Social-Anmeldung mit einem vorhandenen Benutzer über die verifizierte E-Mail-Adresse, die verifizierte Telefonnummer oder den Benutzernamen, in der Reihenfolge, die durch die Bindungsregeln der Anwendung festgelegt sind. Steam und widget-basierte Telegram-Anbieter stellen weder E-Mail noch Telefon bereit, daher erstellen sie einen separaten Benutzer, es sei denn, der Benutzer verknüpft den Anbieter von einem bereits angemeldeten Konto aus. Siehe wie Casdoor Konten verknüpft.
  • Zusätzliche Profilfelder. Anbieter, die Rohdaten weitergeben, wie der Goth-basierte Steam-Typ und benutzerdefinierte Anbieter, können mehr Benutzerfelder über Benutzer-Mapping füllen.
  • Die Client-Seite. Jede Standardbibliothek funktioniert mit Casdoor. Verbinden eines standardmäßigen OIDC-Clients listet die Endpunkte auf, und der Beitrag Spring Boot SSO mit OIDC zeigt eine vollständige App.

Referenzen​