OpenID Connect: Login mit OAuth, Teil 2: Identity-Federation und fortgeschrittene Themen

Seite 3: Kombinierte Szenarien

Inhaltsverzeichnis

In Installationen mit einer hohen Anzahl von Login-Vorgängen kommt der Optimierung des Login-Vorgangs (Dauer und produzierte Last) eine große Bedeutung zu. Hier kann der Parameter "claims" zum Einsatz kommen, um die Anzahl der Requests zu verringern. Er erlaubt es dem Client, gezielt Claims zum Benutzer oder dem Authentifizierungsvorgang dem ID Token oder dem UserInfo-Endpunkt zuzuordnen. Wenn der Client das nutzt, um die essenziell erforderlichen Claims dem ID Token zuzuweisen, dann stehen alle erforderlichen Benutzerdaten sofort nach dem Umtausch des Autorisierungs-Codes zur Verfügung und der Client spart sich (und dem OP) den zusätzlichen Aufruf auf dem UserInfo-Endpunkt.

Unter der Annahme, dass der Mediendienst nur den Namen und die E-Mail-Adresse für die Durchführung des Logins benötigt, könnte der Parameter für das Beispiel wie folgt aussehen:

{
"id_token":
{
"name": {"essential": true},
"email": {"essential": true},
"email_verified"; {"essential": true},
}
}

Der entsprechende Authentifizierungs-Request enthält dann das JSON-Objekt (Form URL-encoded) als Wert des Parameters "claims":

  HTTP/1.1 302 Found
Location: https://accounts.funcorp.com/oauth/auth?
response_type=code
&scope=openid
&client_id=SDFGHJKLUZTREDFGHJ
&state=34790876543456789765
&redirect_uri=https%3A%2F%2Fmediaservice.funcorp.com%2Flogin_cb
&claims=%7B%22id_token%22%3A%0A%20%7B%22name%22%3A%20%20%7B%22essential%22%3A%20true%7D%2C%0A%20%20%22email%22%3A%20%20%7B%22essential%22%3A%20true%7D%2C%0A%20%20%22email_verified%22%3B%20%7B%22essential%22%3A%20true%7D%2C%0A%20%7D%0A%7D%0A

Im Ergebnis würde das ID Token dann die folgenden Daten enthalten:

{
"iss": "https://accounts.funcorp.com",
"sub": "786767677",
"aud": "SDFGHJKLUZTREDFGHJ",
"exp": 1388700360000,
"iat":1388696760000,
"auth_time": 1388696760000,
"name": "Max Mustermann",
"email": "m.mustermann@funcorp.com"
"email_verified": true
}

Alternativ lässt sich das Login mittels "grant type implicit" durchführen, denn hierbei werden alle Daten bereits mit dem Redirect zurück zum Client ausgeliefert. Der Client spart sich damit den Aufruf auf dem Token-Endpunkt. Probleme mit der Länge der Redirect-URL sollten dabei nicht auftreten, da der Server die ID-Daten in einem sogenannten Fragment nur zum User Agent überträgt. Dadurch wird die Implementierung aber auch schwieriger, denn das Frontend der Anwendung muss gegebenenfalls dafür sorgen, dass Access- und ID Token zum Backend übertragen werden. Hierzu ist im Frontend der Anwendung JavaScript und im Backend eine passende Schnittstelle erforderlich. Hinzu kommt, dass die Integrität und Authentizität des ID Token über eine digitale Signatur sicherzustellen ist. Des Weiteren muss man berücksichtigen, dass der Implicit Grant nicht geeignet ist, um Refresh Tokens auszustellen.

Letztlich ist die Wahl des "richtigen" Grant Type abhängig vom Verhältnis der Bandbreite zwischen User Agent und Relying Party (RP) beziehungsweise OP auf der einen Seite (implicit) und der Bandbreite zwischen RP und OP auf der anderen Seite (Code). Das bedeutet, bei langsamen Internet auf dem mobilen Endgerät ist der Grant Types Code besser geeignet, da hier die Daten direkt zwischen RP und OP übertragen werden. Auf dieser Strecke sollte in der Regel eine hohe Bandbreite verfügbar sein. Ein Vorzug von OpenID Connect ist, dass die Anwendung überhaupt eine Wahl hat, wie sich der Login-Prozess optimal implementieren lässt.

Und was ist nun mit den eingangs erwähnten kombinierten Szenarien, in denen der Client nicht nur Identitätsdaten benötigt, sondern auch im Namen des Benutzers auf andere Ressourcen zugreifen möchte? Solche Anwendungen machen für Multi-Service-Anbieter wie Google oder die Deutsche Telekom Sinn. Im Beispiel könnte man sich vorstellen, dass der Mediendienst im Namen des Benutzers auch auf dessen Adressbuch beim E-Mail-Dienst von Fun Corp zugreifen möchte, um Einladungen für Shares versenden zu können. Umgekehrt ist es denkbar, dass der E-Mail-Service den Mediendienst verwendet, um Anhänge abzulegen oder von dort Dateien zu laden.

Ist der OpenID Provider auch der OAuth-Autorisierungsserver des Anbieters, sollte ein Client mit dessen Access Tokens außerdem auf andere Ressourcenserver zugreifen können. Bezüglich der Nutzbarkeit eines konkreten Access Token bei unterschiedlichen Diensten gibt es leider – bedingt durch unterschiedliche Token-Designs und Security Policies – essenzielle Unterschiede zwischen den Implementierungen der Anbieter. Bei Google etwa kann der Client ein Access Token für alle freigeschalteten Dienste eines Clients verwenden. Andere Dienstanbieter wie die Deutsche Telekom stellen aus Sicherheitsgründen verschiedene Access Tokens für unterschiedliche Ressourcenserver aus. Das soll verhindern, dass sich bei einem Einbruch bei einem konkreten Dienst abgefangene Access Tokens für unautorisierte Zugriffe auf andere Dienste missbrauchen lassen. Diese Vorgehensweise hat natürlich Auswirkungen auf das Token-Handling des Clients.

Auf das Beispiel angewendet bedeutet das,dass sich ein Access Token für den UserInfo-Endpunkt gegebenenfalls nicht für den Zugriff auf den Adressbuchdienst verwenden lässt. Dem Client stehen dann zwei Optionen zur Auswahl: Er kann weitere Access Tokens durch ein erneutes Durchlaufen des OAuth Browser-Flows erlangen. Die bessere Nutzungserfahrung wird aber erreicht, wenn der Autorisierungsserver dem Client initial ein Refresh Token ausstellt, dass dieser danach zum Abfragen weiterer dienstspezifischer Access Tokens verwenden kann. Diese von Justin Richer, Principal Technologist bei MITRE, als "Über Refresh Token" bezeichnete Vorgehensweise soll am Beispiel skizziert werden. Der Client fordert mit dem initialen Authentifizierungs- und Autorisierungs-Request sowohl OpenID Connect als auch Zugriff auf den Adressbuchdienst an.

HTTP/1.1 302 Found
Location: https://accounts.funcorp.com/oauth/auth?
response_type=code
&scope=openid%20contacts
&client_id=SDFGHJKLUZTREDFGHJ
&state=300965456343676767
&redirect_uri=https%3A%2F%2Fmediaservice.funcorp.com%2Flogin_cb

Im Beispiel entscheidet der Autorisierungsserver, das initiale Access Token für den UserInfo-Endpunkt auszustellen, und teilt das dem Client im Response-Parameter "scope" mit.

HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache

{
"access_token": "4vfKjkM8FcGvnzZUN4_KSP0aAp",
"scope": "userinfo",
"token_type": "Bearer",
"expires_in": 3600,
"id_token": "eyJhb...cifQ.ew...fQ.gg...zqg",
"refresh_token": "67676q6876r8978rq7"
}

Des Weiteren stellt der Autorisierungsserver ein Refresh Token aus, dass der Client beim Anfordern weiterer Access Tokens für den betreffenden Benutzer verwenden kann. Hierzu nutzt der Client den Grant Type refresh_token wie folgt:

POST /oauth/token HTTP/1.1
Host: accounts.funcorp.com
Content-Type: application/x-www-form-urlencoded
Authorization: Basic U0RGR0hKS0xVWlRSRURGR0hKOnRlc3QxMjM0

grant_type=refresh_token&
refresh_token=67676q6876r8978rq7&
scope="contacts"

Nun ist der Client im Besitz von Access Tokens für beide relevanten Dienste.

Mehr Infos

Und so weiter ...

Man könnte noch viele weitere Anwendungsfälle vorstellen, die OpenID Connect adressiert. Dem interessierten Leser sei dafür das Studium der Kernspezifikationen und die ergänzende Spezifikation zur Sitzungsverwaltung und zum Log-out ans Herz gelegt: