Device flow: Auth mit Logto
Diese Anleitung setzt voraus, dass du eine Anwendung vom Typ „Native“ mit Device Flow als Autorisierungsflow in der Logto-Konsole erstellt hast.
Einführung
Der OAuth 2.0 Device Authorization Grant (Device Flow) ist für Geräte mit eingeschränkten Eingabemöglichkeiten konzipiert, wie Smart-TVs, Spielkonsolen, CLI-Tools und IoT-Geräte. Er ermöglicht es Benutzern, den Anmeldeprozess auf dem Gerät zu starten, aber die Authentifizierung auf einem separaten Gerät mit Browser, wie einem Telefon oder Laptop, abzuschließen.
Da das Gerät selbst keinen browserbasierten Anmeldeflow durchführen kann, zeigt das Gerät einen kurzen Code und eine URL an. Der Benutzer besucht diese URL auf einem anderen Gerät, gibt den Code ein und meldet sich an. In der Zwischenzeit fragt das ursprüngliche Gerät Logto ab, bis die Autorisierung abgeschlossen ist.
Anwendungs-Credentials abrufen
Navigiere in deiner Logto-Konsole zur Detailseite deiner Anwendung, um die folgenden Zugangsdaten zu erhalten:
- App ID: Die eindeutige Kennung deiner Anwendung (auch bekannt als
client_id). - Logto-Endpunkt: Dein Logto-Autorisierungsserver-Endpunkt. Du findest ihn in der Logto-Konsole unter „Anwendungsdetails“.
Für Logto Cloud lautet der Endpunkt https://{your-tenant-id}.logto.app.
Device Flow Apps sind öffentliche Clients, daher ist kein App Secret erforderlich.
Device Code anfordern
Starte den Device Flow, indem du eine POST-Anfrage an den Device Authorization Endpoint sendest:
curl --request POST 'https://your.logto.endpoint/oidc/device/auth' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=your-application-id' \
--data-urlencode 'scope=openid offline_access profile'
Die Antwort enthält:
| Feld | Beschreibung |
|---|---|
device_code | Ein eindeutiger Code, den deine App beim Polling des Token-Endpunkts verwendet. |
user_code | Ein kurzer Code, der dem Benutzer angezeigt wird, damit er ihn im Browser eingibt. |
verification_uri | Die URL, bei der der Benutzer den user_code eingibt. |
verification_uri_complete | Eine URL mit vorausgefülltem user_code. Benutzer können diese URL direkt besuchen, um die manuelle Codeeingabe zu überspringen — du kannst sie als QR-Code, Link oder anders präsentieren. |
expires_in | Die Lebensdauer in Sekunden von device_code und user_code. Nach Ablauf nicht mehr weiter abfragen. |
Zeige die Verifizierungs-URL dem Benutzer an
Zeige den user_code und die verification_uri auf dem Bildschirm deines Geräts an.
Alternativ kannst du verification_uri_complete verwenden, bei dem der Code bereits vorausgefüllt ist — der Benutzer muss nur noch bestätigen. Wie du es präsentierst, bleibt dir überlassen: QR-Code, klickbarer Link usw.
Abfrage nach Tokens
Während der Benutzer die Authentifizierung im Browser abschließt, sollte dein Gerät den Token-Endpunkt abfragen. Deine App sollte mindestens 5 Sekunden zwischen den Abfragen warten:
curl --request POST 'https://your.logto.endpoint/oidc/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=your-application-id' \
--data-urlencode 'grant_type=urn:ietf:params:oauth:grant-type:device_code' \
--data-urlencode 'device_code=DEVICE_CODE'
Ersetze DEVICE_CODE durch den Wert device_code aus der Device Authorization Antwort.
Beende das Polling, wenn:
- Du eine erfolgreiche Token-Antwort erhältst.
- Die
expires_in-Zeit aus der Device Code Antwort abgelaufen ist. - Du einen nicht wiederholbaren Fehler wie
expired_tokenoderaccess_deniederhältst.
Token-Antwort
Nachdem der Benutzer zugestimmt hat, enthält die Antwort:
| Feld | Beschreibung |
|---|---|
access_token | Das Zugangstoken (Access token). Dies ist standardmäßig eine opake Zeichenkette; wenn ein resource angefordert wird, ist es ein JWT mit aud auf die Ressourcen-URI gesetzt. |
id_token | Das ID-Token (ID token) mit Benutzeridentitätsansprüchen. Nur vorhanden, wenn der openid Scope angefordert wurde. |
refresh_token | Wird verwendet, um neue Tokens ohne erneute Authentifizierung zu erhalten. Nur vorhanden, wenn der offline_access Scope angefordert wurde. |
token_type | Immer Bearer. |
expires_in | Lebensdauer des Tokens in Sekunden. |
scope | Die vom Autorisierungsserver gewährten Berechtigungen (Scopes). |
Checkpoint: Teste deinen Device Flow
Teste jetzt deine Device Flow-Integration:
- Starte deine App und löse den Device Flow aus, um einen
device_codeunduser_codezu erhalten. - Öffne die
verification_uriin einem Browser und gib denuser_codeein, oder verwendeverification_uri_complete, um die manuelle Codeeingabe zu überspringen. - Schließe den Anmeldeprozess im Browser ab.
- Überprüfe, ob deine App nach dem Polling Tokens erhält.
Benutzerinformationen abrufen
ID-Token-Ansprüche dekodieren
Das im Token-Response zurückgegebene id_token ist ein standardmäßiges JSON Web Token (JWT). Du kannst den Base64URL-codierten Payload-Teil (der zweite Teil des JWT, durch . getrennt) dekodieren, um grundlegende Benutzeransprüche ohne zusätzliche Netzwerkabfrage zu erhalten.
Der dekodierte Payload enthält Ansprüche wie sub (Benutzer-ID), name, email usw., abhängig von den angeforderten Berechtigungen (Scopes).
Für den produktiven Einsatz solltest du die JWT-Signatur validieren, bevor du den Ansprüchen vertraust. Verwende das JWKS von deinem Logto-Endpunkt (https://your.logto.endpoint/oidc/jwks), um das Token zu überprüfen.
Vom userinfo-Endpunkt abrufen
Das ID-Token enthält grundlegende Ansprüche basierend auf den angeforderten Berechtigungen (Scopes). Einige erweiterte Ansprüche (wie custom_data, identities) sind nur über den OIDC UserInfo Endpoint verfügbar:
curl --request GET 'https://your.logto.endpoint/oidc/me' \
--header 'Authorization: Bearer ACCESS_TOKEN'
Ersetze ACCESS_TOKEN durch das opake Zugangstoken (nicht das JWT-Ressourcen-Token) aus der Token-Antwort. Die Antwort ist ein JSON-Objekt mit den Benutzeransprüchen basierend auf den gewährten Berechtigungen.
Zusätzliche Ansprüche anfordern
Du stellst möglicherweise fest, dass einige Benutzerinformationen im ID-Token fehlen. Das liegt daran, dass OAuth 2.0 und OpenID Connect (OIDC) nach dem Prinzip der minimalen Rechtevergabe (PoLP) konzipiert sind und Logto auf diesen Standards aufbaut.
Standardmäßig werden begrenzte Ansprüche zurückgegeben. Wenn du mehr Informationen benötigst, kannst du zusätzliche Berechtigungen anfordern, um auf mehr Ansprüche zuzugreifen.
Ein "Anspruch (Claim)" ist eine Behauptung über ein Subjekt; eine "Berechtigung (Scope)" ist eine Gruppe von Ansprüchen. Im aktuellen Fall ist ein Anspruch ein Informationsstück über den Benutzer.
Hier ist ein nicht-normatives Beispiel für die Beziehung zwischen Berechtigung und Anspruch:
Der "sub"-Anspruch bedeutet "Subjekt", was der eindeutige Identifikator des Benutzers ist (d. h. Benutzer-ID).
Das Logto SDK wird immer drei Berechtigungen anfordern: openid, profile und offline_access.
Um zusätzliche Berechtigungen (Scopes) anzufordern, füge sie in den scope-Parameter der Device Authorization Anfrage ein. Um beispielsweise die E-Mail und Telefonnummer des Benutzers anzufordern:
curl --request POST 'https://your.logto.endpoint/oidc/device/auth' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=your-application-id' \
--data-urlencode 'scope=openid offline_access profile email phone'
Berechtigungen und Ansprüche
Hier ist die Liste der unterstützten Berechtigungen (Scopes) und der entsprechenden Ansprüche (Claims):
Standard OIDC-Berechtigungen (Scopes)
openid (Standard)
| Claim-Name | Typ | Beschreibung |
|---|---|---|
| sub | string | Der eindeutige Identifikator des Benutzers |
profile (Standard)
| Claim-Name | Typ | Beschreibung |
|---|---|---|
| name | string | Der vollständige Name des Benutzers |
| username | string | Der Benutzername des Benutzers |
| picture | string | URL zum Profilbild des Endbenutzers. Diese URL MUSS auf eine Bilddatei (z. B. PNG, JPEG oder GIF) verweisen, nicht auf eine Webseite mit einem Bild. Beachte, dass diese URL speziell auf ein Profilfoto des Endbenutzers verweisen SOLLTE, das zur Darstellung des Endbenutzers geeignet ist, und nicht auf ein beliebiges vom Endbenutzer aufgenommenes Foto. |
| created_at | number | Zeitpunkt, zu dem der Endbenutzer erstellt wurde. Die Zeit wird als Anzahl der Millisekunden seit der Unix-Epoche (1970-01-01T00:00:00Z) dargestellt. |
| updated_at | number | Zeitpunkt, zu dem die Informationen des Endbenutzers zuletzt aktualisiert wurden. Die Zeit wird als Anzahl der Millisekunden seit der Unix-Epoche (1970-01-01T00:00:00Z) dargestellt. |
Weitere Standard-Ansprüche (Claims) wie family_name, given_name, middle_name, nickname, preferred_username, profile, website, gender, birthdate, zoneinfo und locale werden ebenfalls im profile-Scope enthalten sein, ohne dass der userinfo-Endpunkt angefragt werden muss. Ein Unterschied zu den oben genannten Claims besteht darin, dass diese Claims nur zurückgegeben werden, wenn ihre Werte nicht leer sind, während die oben genannten Claims null zurückgeben, wenn die Werte leer sind.
Im Gegensatz zu den Standard-Claims verwenden die Claims created_at und updated_at Millisekunden anstelle von Sekunden.
email
| Claim-Name | Typ | Beschreibung |
|---|---|---|
string | Die E-Mail-Adresse des Benutzers | |
| email_verified | boolean | Ob die E-Mail-Adresse verifiziert wurde |
phone
| Claim-Name | Typ | Beschreibung |
|---|---|---|
| phone_number | string | Die Telefonnummer des Benutzers |
| phone_number_verified | boolean | Ob die Telefonnummer verifiziert wurde |
address
Bitte siehe die OpenID Connect Core 1.0 für Details zum Address-Claim.
Scopes, die mit (Standard) gekennzeichnet sind, werden immer vom Logto SDK angefordert. Claims unter den Standard-OIDC-Scopes sind immer im ID-Token enthalten, wenn der entsprechende Scope angefordert wird — sie können nicht deaktiviert werden.
Erweiterte Berechtigungen (Scopes)
Die folgenden Scopes sind von Logto erweitert und liefern Claims über den userinfo-Endpunkt. Diese Claims können auch so konfiguriert werden, dass sie direkt im ID-Token enthalten sind, über Konsole > Benutzerdefiniertes JWT. Siehe Benutzerdefiniertes ID-Token für weitere Details.
custom_data
| Claim-Name | Typ | Beschreibung | Standardmäßig im ID-Token enthalten |
|---|---|---|---|
| custom_data | object | Die benutzerdefinierten Daten des Benutzers |
identities
| Claim-Name | Typ | Beschreibung | Standardmäßig im ID-Token enthalten |
|---|---|---|---|
| identities | object | Die verknüpften Identitäten des Benutzers | |
| sso_identities | array | Die verknüpften SSO-Identitäten des Benutzers |
roles
| Claim-Name | Typ | Beschreibung | Standardmäßig im ID-Token enthalten |
|---|---|---|---|
| roles | string[] | Die Rollen (Roles) des Benutzers | ✅ |
urn:logto:scope:organizations
| Claim-Name | Typ | Beschreibung | Standardmäßig im ID-Token enthalten |
|---|---|---|---|
| organizations | string[] | Die Organisations-IDs, denen der Benutzer angehört | ✅ |
| organization_data | object[] | Die Organisationsdaten, denen der Benutzer angehört |
Diese Organisations-Claims können auch über den userinfo-Endpunkt abgerufen werden, wenn ein opaker Token verwendet wird. Allerdings können opake Tokens nicht als Organisationstoken für den Zugriff auf organisationsspezifische Ressourcen verwendet werden. Siehe Opaker Token und Organisationen für weitere Details.
urn:logto:scope:organization_roles
| Claim-Name | Typ | Beschreibung | Standardmäßig im ID-Token enthalten |
|---|---|---|---|
| organization_roles | string[] | Die Organisationsrollen, denen der Benutzer angehört, im Format <organization_id>:<role_name> | ✅ |
API-Ressourcen und Organisationen
Wir empfehlen, zuerst 🔐 Rollenbasierte Zugangskontrolle (RBAC) zu lesen, um die grundlegenden Konzepte von Logto RBAC zu verstehen und wie man API-Ressourcen richtig einrichtet.
Zugriff auf API-Ressourcen anfordern
Um auf eine bestimmte API-Ressource zuzugreifen, füge den resource-Parameter in die Device Authorization Anfrage ein:
curl --request POST 'https://your.logto.endpoint/oidc/device/auth' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=your-application-id' \
--data-urlencode 'scope=openid offline_access' \
--data-urlencode 'resource=https://your-api-resource-indicator'
Sobald der Benutzer die Autorisierung abgeschlossen hat und du ein Auffrischungstoken (refresh_token) erhalten hast, kannst du JWT-Zugangstokens für die API-Ressource abrufen:
curl --request POST 'https://your.logto.endpoint/oidc/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=your-application-id' \
--data-urlencode 'grant_type=refresh_token' \
--data-urlencode 'refresh_token=REFRESH_TOKEN' \
--data-urlencode 'resource=https://your-api-resource-indicator'
Die Antwort enthält ein JWT access_token mit aud auf deinen API-Ressourcenindikator gesetzt.
Das refresh_token ist nur verfügbar, wenn der offline_access Scope in der initialen Device Authorization Anfrage enthalten ist. Speichere und verwende immer das neueste refresh_token, da Logto Token-Rotation verwendet.
Organisationstokens abrufen
Falls Organisationen neu für dich sind, lies bitte 🏢 Organisationen (Multi-Tenancy), um loszulegen.
Um organisationsbezogene Informationen anzufordern, füge den Scope urn:logto:scope:organizations in die Device Authorization Anfrage ein:
curl --request POST 'https://your.logto.endpoint/oidc/device/auth' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=your-application-id' \
--data-urlencode 'scope=openid offline_access urn:logto:scope:organizations' \
--data-urlencode 'resource=urn:logto:resource:organizations'
Sobald der Benutzer angemeldet ist, kannst du Organisationstokens mit dem Auffrischungstoken abrufen:
curl --request POST 'https://your.logto.endpoint/oidc/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=your-application-id' \
--data-urlencode 'grant_type=refresh_token' \
--data-urlencode 'refresh_token=REFRESH_TOKEN' \
--data-urlencode 'organization_id=your-organization-id'
Die Antwort enthält ein Zugangstoken, das auf die angegebene Organisation beschränkt ist.
Organisations-API-Ressourcen
Um ein Zugangstoken für eine API-Ressource innerhalb einer Organisation zu erhalten, füge sowohl die Parameter resource als auch organization_id hinzu:
curl --request POST 'https://your.logto.endpoint/oidc/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=your-application-id' \
--data-urlencode 'grant_type=refresh_token' \
--data-urlencode 'refresh_token=REFRESH_TOKEN' \
--data-urlencode 'organization_id=your-organization-id' \
--data-urlencode 'resource=https://your-api-resource-indicator'