CLI-Tool braucht Login? Device Code Flow verwenden
Kommandozeilen-Tools muessen oft im Namen eines angemeldeten Benutzers handeln.
Aber eine CLI kann normalerweise keinen klassischen Browser Redirect empfangen.
Fuer diese Art von App ist das praktische Muster:
Device Code Flow.
Dieses Muster wird verwendet, wenn:
- ein Benutzer vorhanden ist
- die App im Terminal laeuft
- die App kein Client Secret sicher speichern kann
- die App nicht verlaesslich auf einen lokalen Browser Callback setzen kann
- die Authentifizierung ueber Microsoft Entra ID erfolgt
- die App delegierten Zugriff auf eine API benoetigt
In diesem Beispiel:
- CloudTrips CLI ist der Kommandozeilen-Client
- CloudTrips API ist die geschuetzte Resource
- Employee ist der angemeldete Benutzer
Die Authentifizierung erfolgt mit dem OAuth 2.0 Device Code Flow. Die Autorisierung wird ueber delegierte Berechtigungen gesteuert.
Unterschied zum SPA PKCE Flow
Der vorherige Trip hat Authorization Code Flow mit PKCE fuer eine browserbasierte SPA verwendet.
Diese SPA konnte denselben Browser zu Microsoft Entra ID weiterleiten und den Authorization Code unter /auth/callback empfangen.
Eine CLI ist anders.
Sie laeuft im Terminal. Sie kann ueber SSH, in einem Container, auf einem Server oder in einer Umgebung verwendet werden, in der ein Browser Callback unpraktisch ist.
Statt zur App zurueckzuleiten, teilt Device Code Flow die Anmeldung auf zwei Orte auf:
- die CLI fordert einen temporaeren Device Code von Microsoft Entra ID an
- die CLI zeigt einen kurzen User Code und eine Verification URL an
- der Benutzer oeffnet die Verification URL in einem beliebigen Browser
- der Benutzer gibt den Code ein und meldet sich an
- die CLI fragt den Token Endpoint ab, bis die Anmeldung abgeschlossen ist
- Microsoft Entra ID gibt delegierte Tokens an die CLI zurueck
Die Form ist:
CLI fordert Device Code an -> Benutzer meldet sich im Browser an -> CLI pollt -> CLI erhaelt Tokens -> CLI ruft API auf
Wichtig ist: Die CLI verarbeitet niemals das Passwort des Benutzers.
Architektur
Employee -> CloudTrips CLI -> Microsoft Entra ID -> CloudTrips API
Die CLI startet den Login.
Der Browser schliesst den Login ab.
Die CLI erhaelt ein Access Token fuer die API, nachdem Microsoft Entra ID bestaetigt hat, dass der Benutzer die Device-Code-Challenge abgeschlossen hat.
Es wird kein Client Secret verwendet.
CloudTrips API App erstellen
Erstelle zuerst die Resource-Anwendung.
Gehe zu:
Entra ID > App registrations > New registration
Erstelle eine Anwendung:
Name: CloudTrips-API
Diese App Registration repraesentiert die API, die Access Tokens empfaengt und validiert.

API exponieren
Oeffne in CloudTrips-API:
Expose an API
Setze die Application ID URI:
api://<cloudtrips-api-application-id>
Dieser Bezeichner wird zur Audience fuer Access Tokens, die fuer die CloudTrips API ausgestellt werden.

Delegierten Scope erstellen
Fuege in CloudTrips-API einen delegierten Scope hinzu:
Expose an API > Add a scope
Beispiel:
Scope name: Trips.Read
Who can consent: Admins and users
Admin consent display name: Read CloudTrips trips
User consent display name: Read your CloudTrips trips
State: Enabled
Die CloudTrips API kann spaeter pruefen, ob das eingehende Token diesen Scope enthaelt.

CloudTrips CLI App erstellen
Erstelle jetzt die Public-Client-Anwendung.
Gehe zu:
Entra ID > App registrations > New registration
Erstelle eine Anwendung:
Name: CloudTrips-CLI
Supported account types: Single tenant
Redirect URI: leer lassen
Die CLI benoetigt fuer Device Code Flow keine Web Redirect URI.

Public Client Flow aktivieren
Oeffne in CloudTrips-CLI:
Authentication
Suche:
Advanced settings > Allow public client flows
Setze den Wert auf:
Yes
Erstelle kein Client Secret fuer die CLI.
Eine CLI mit Device Code Flow ist ein Public Client. Ein Secret, das mit einem lokalen Tool ausgeliefert wird, kann kopiert werden.

API-Berechtigung hinzufuegen
Gehe zu:
App registrations > CloudTrips-CLI > API permissions
Waehle:
Add a permission
Waehle:
My APIs > CloudTrips-API > Delegated permissions > Trips.Read
Damit darf die CLI ein Access Token fuer die CloudTrips API im Namen des angemeldeten Benutzers anfordern.

Wenn dein Tenant Administratorfreigabe verlangt, klicke:
Grant admin consent

Device Code anfordern
Zur Laufzeit ruft die CLI den Device-Code-Endpoint auf:
POST https://login.microsoftonline.com/<tenant-id>/oauth2/v2.0/devicecode
Request Body:
client_id=CLOUDTRIPS_CLI_CLIENT_ID
scope=openid profile offline_access api://<cloudtrips-api-application-id>/Trips.Read
Microsoft Entra ID gibt Werte wie diese zurueck:
{
"user_code": "ABCD-EFGH",
"device_code": "long-device-code-for-the-cli",
"verification_uri": "https://microsoft.com/devicelogin",
"expires_in": 900,
"interval": 5,
"message": "To sign in, use a web browser to open..."
}
Die CLI zeigt dem Benutzer den user_code und die verification_uri.
Die CLI behaelt den device_code fuer das Polling.

Der Benutzer oeffnet:
https://microsoft.com/devicelogin
Dann gibt der Benutzer den kurzen Code ein, den die CLI angezeigt hat.
Nach der Code-Eingabe meldet sich der Benutzer mit Microsoft Entra ID an.
Wenn Consent erforderlich ist, genehmigt der Benutzer oder Administrator die delegierte Berechtigung.
CLI pollt den Token Endpoint
Waehrend der Benutzer sich anmeldet, pollt die CLI den Token Endpoint:
POST https://login.microsoftonline.com/<tenant-id>/oauth2/v2.0/token
Request Body:
client_id=CLOUDTRIPS_CLI_CLIENT_ID
grant_type=urn:ietf:params:oauth:grant-type:device_code
device_code=DEVICE_CODE_FROM_DEVICECODE_RESPONSE
Die CLI sollte zwischen den Polling-Versuchen den interval Wert aus der Device-Code-Response einhalten.
Bevor der Benutzer die Anmeldung abschliesst, kann Microsoft Entra ID zurueckgeben:
{
"error": "authorization_pending"
}
Das ist normal.
Nachdem der Benutzer die Anmeldung abgeschlossen hat, gibt Microsoft Entra ID Tokens zurueck.

Access Token Claims
Die CLI erhaelt ein Access Token fuer die CloudTrips API.
Decodiere das Access Token.
Wichtige Claims:
| Claim | Bedeutung |
|---|---|
aud |
API, die das Token akzeptieren soll |
scp |
Delegierte Berechtigungen, die der CLI erteilt wurden |
sub |
Stabiler Benutzerbezeichner fuer diese App |
tid |
Tenant ID |
iss |
Token Issuer |
Der wichtige Nachweis in diesem Trip ist:
{
"aud": "api://<cloudtrips-api-application-id>",
"scp": "Trips.Read"
}

Geschuetzte API aufrufen
Die CLI sendet das Access Token an die CloudTrips API:
GET https://api.cloudtrips.example/trips
Authorization: Bearer ACCESS_TOKEN
Die API validiert:
- Token-Signatur
- Issuer
- Audience
- Ablaufzeit
- delegierten Scope
Wenn das Token scp=Trips.Read enthaelt, gibt die API die Trips zurueck.

Unterschied zu anderen Flows
| Thema | Serverseitige Web-App | SPA mit PKCE | CLI mit Device Code |
|---|---|---|---|
| Client-Typ | Confidential | Public | Public |
| Client Secret | Ja | Nein | Nein |
| Benutzerinteraktion | Browser Redirect | Browser Redirect | Separate Code-Eingabe im Browser |
| Token Exchange | Serverseitig | Browser/Public Client | CLI Polling |
| Schutz | Client Secret | PKCE Verifier | Device Code plus Benutzerabschluss |
| Typische Nutzung | Web-Apps | Browser-Apps | CLI-Tools, Geraete, SSH-Sessions |
Enterprise-Hinweis
Device Code Flow ist praktisch, aber weiterhin interaktive Benutzeranmeldung.
Er ist kein Ersatz fuer Workload Identity.
Verwende ihn fuer Tools, bei denen ein menschlicher Operator vorhanden ist.
Fuer unbeaufsichtigte Automation verwende Managed Identity, Workload Identity Federation, Zertifikats-Credentials oder Client Credentials Flow.
In Enterprise-Umgebungen solltest du Conditional Access beruecksichtigen. Manche Tenants schraenken Device-Code-Anmeldung ein oder ueberwachen sie, weil sie in Phishing-Szenarien missbraucht werden kann.
Verwende separate App Registrations pro Umgebung, wenn API Audiences, Berechtigungen oder Conditional-Access-Grenzen unterschiedlich sind.
Beispiel:
CloudTrips-CLI-DEV
CloudTrips-CLI-TEST
CloudTrips-CLI-PROD
CloudTrips-API-DEV
CloudTrips-API-TEST
CloudTrips-API-PROD
Das bietet:
- klarere Consent-Grenzen
- sichereren Produktionszugriff
- unabhaengiges Troubleshooting
- sauberere Audit Logs
- keine versehentliche Token-Nutzung ueber Umgebungsgrenzen hinweg