OAuth2 in Bildern am Beispiel des Authorization Code Grants

Von: Till Born
Datum: 5. September 2019
Aktualisiert: 17. Februar 2021

Der Authorization Code Grant ist der komplexeste Ablauf bei OAuth2. Wie läuft eine Autorisierung und Authentifizierung mit diesem Ablauf ab? Um diese Leitfrage zu beantworten beschreibt dieser Artikel den Authorization Code Grant anschaulich Schritt für Schritt. Am Beispiel Authorization Code Grant wird über einen dritten auf eine Ressource zugegriffen. Hierfür wird ein fiktives Szenario verwendet, bei dem ein Benutzer mit OAuth2 seine Mails über einen Client bei einem Mail Service abrufen möchte. Dabei werden alle HTTP Anfragen und Antworten Schritt für Schritt aufgeführt und erklärt um einen tiefen Einblick in das OAuth2 Framework zu bieten.

Einleitung

OAuth2 wird verwendet um Autorisierung (und Authentifizierung durch Erweiterungen) und SSO (Single Sign-On) zu realisieren. Es ist dabei egal ob dies im Internet oder in der private Cloud stattfindet. Benutzer authentifizieren sich bei einem Authentifizierungsservice und können danach auf ihre Daten bei einem, an den Authentifizierungsservice gekoppelten, Service abrufen.

Szenario

Schauen wir uns OAuth2 im Detail an. Wir verwenden ein fiktives Beispiel bei dem ein Benutzer seine Emails über einen Web Mail Client bei einem Web Mailer abrufen möchte. Der Web Mailer unterstützt die Annahme von OAuth2 Access Tokens und stellt bei gültigem Access Token die Emails des zugehörigen Benutzers bereit.

Der Benutzer hat einen OAuth2 kompatiblen Web Mail Client. Neben der eigentlichen OAuth2 kompatibilität muss der Client sich zuvor bei dem zu nutzenden OAuth2 Provider registrieren. Um sein Konto mit dem Client nutzen zu können muss der Benutzer sich zuerst über den Authorization Code Grant von OAuth2 anmelden. Der Authorization Code Grant wird mit einem Authentifizierungsservice durchgeführt. Hier muss der Benutzer sich mit seinem Passwort einloggen. Hat der Benutzer mit Hilfe des Clients den Authorization Code Grant durchgeführt, so erhält der Client eine temporäre Erlaubnis zum Zugriff auf die Emails die im Web Mailer hinterlegt sind. Danach stehen die Email dem Benutzer in gewöhnter Weise zu Verfügung (typische Funktionsweise eines Email-Clients).

Wir weisen den Akteuren die folgenden OAuth2 Rollen zu

Akteur OAuth2 Rolle
Benutzer mit WebMail Client im Browser Resource Owner
Web Mail Client Client
Web Mailer Resource Server
Authentifizierungsservice Authorization Server

Die Rollen können von verschiedenen Parteien (z.B. Firmen) kontrolliert werden.

Aufbau

Es ergibt sich folgender, für den Authorization Code Grant typischer, Aufbau der Komponenten.

Aufbau

Abbildung : Szenario Aufbau

Zum Aufbau sei folgendes erwähnt:

  • Es wurden zuvor Client Credentials ausgetauscht – „Der Web Mail Client wurde bei Google registriert“
  • Der Client unterstützt mindestens 2 Interaktionen – Mails abrufen und von außen aufgerufen werden
  • User-Agent und Client werden durch den Web Mail Client abgedeckt

Durchführung des Authorization Code Grants

Die folgenden Unterkapitel beschreiben den Authorization Code Grant auf HTTP Ebene. Alle HTTP Anfragen und Antworten müssen mit TLS geschützt sein.

1. Erster Aufruf der Ressource

Der Benutzer möchte seine Mails abrufen. Er ruft die URL des Mail Service ab.


Abbildung : Benutzer ruft das erste mal seine Mails ab

Die HTTP Anfrage aus (1) sieht wie folgt aus:

GET /mails HTTP/1.1

Hierbei handelt es sich um den fachlichen Aufruf der Email Ressource. OAuth2 ist noch nicht involviert.

2. Redirect zum Authorization Server zur Authentifizierung

Der Client stellt fest, dass noch keine Autorisierung vorliegt und leitet den User-Agent zur Authentifizierung weiter.


Abbildung : Benutzer wird zum Authorization Server weitergeleitet

Die HTTP Antwort aus (2) sieht in etwa wie folgt aus:

HTTP/1.1 307 Temporary Redirect Location: https://auth-server:7000/oauth2/auth? client_id=abc& response_type=code& scope=openid mail& redirect_uri=https://client:2000/oauth2callback& state=security_token%3D3ndp324l1q2pld9cod3emhcqru%26url%3D/

Der User-Agent (bedient vom Resource Owner) ist beim Client nicht eingeloggt und darf deswegen nicht auf die Mails zugreifen. Der Client initiiert deswegen einen OAuth2 Grant um Autorisierung im Namen des Resource Owners zu erlangen um in dessen Namen die Resource Owner Mails abzurufen. Hierfür werden einige Parameter in die Antwort des Clients geschrieben

Teil der Nachricht Erläuterung
HTTP/1.1 307 Temporary Redirect Client leitet den User Agent zu einer anderen URL weiter
Location: https://auth-server:7000/oauth2/auth? Die vom User-Agent aufzurufende URL.
client_id=abc Teil der zuvor ausgetauschten Client Credentials - die Client ID. Hiermit tätigt der Client eine Teil-Authentifizierung indem er mitteilt welcher Client die Autorisierung beantragt.
response_type=code Bestimmt den gewählen OAuth2 Grant den der Client durchführen möchte. Hier wird der Authorization Code Grant über den Wert code gewählt.
scope=openid mail Bestimmt den Gültigkeitsbereich der Autorisierung. Hier wird geklärt, was der Client mit der Autorisierung durchführen kann. Mit den Werten openid und mail wird angegeben, dass der Client Informationen zum Benutzer und Zugriff auf dessen Mails anfragt.
redirect_uri=https://client:2000/oauth2callback Wurde bei der Anmeldung des Clients beim Authorization Server registriert. Der Client gibt an, wie er für den User-Agent zu erreichen ist. Die redirect_uri muss mit dem Wert übereinstimmen den der Authorization Server zur vorliegenden client_id gespeichert hat.
state=security_token%3D3ndp324l1q2pld9cod3emhcqru%26url%3D/ Um CSRF Angriffe zu verhindern wird ein Wert an die Anfrage angehängt der nach der Authentifizierung und dem Rückleiten auf den Client übereinstimmen muss. Einem Angreifer kann den CSRF Wert nicht einfach erraten und somit keine Angriffe auf den Benutzer durchführen um z.B. den Authorization Code durch einen anderen auszutauschen.

3. Authentifizierung beim Authorization Server

Der User-Agent folgt der Weiterleitungsanfrage zum Authorization Server


Abbildung : User-Agent folgt dem Redirect zum Authorization Server

Die HTTP Anfrage aus (3) sieht jetzt wie folgt aus:

GET /oauth2/auth? client_id=abc& response_type=code& scope=openid mail& redirect_uri=https://client:2000/oauth2callback& state=security_token%3D3ndp324l1q2pld9cod3emhcqru%26url%3D/ HTTP/1.1

Es wird der authorize Endpunkt des Authorization Server aufgerufen. Die Parameter stimmen mit den Parametern aus (2) überein

Login beim Authorization Server

Die Authentifizierung beim Authorization Server ist nicht Teil der Spezifikation. Ziel der Authentifizierung ist es, die Identität des Benutzers festzustellen (Login). Weiterhin soll dem Benutzer die Möglichkeit gegeben werden, den anfragenden Client, als auch die angefragten Scopes zu überprüfen (Zustimmung).

An dieser Stelle wird einmalig das höchste Credential des Benutzers benötigt. Das höchste Credential wäre beispielsweise das Passwort des Benutzers bei Authentifizierung mit Benutzernamen und Passwort. Eine erfolgreiche Authentifizierung setzt den gewählten OAuth2 Grant fort.

4. Redirect zum Client nach erfolgreicher Authentifizierung

Nach der Authentifizierung wird der User-Agent mit einem Code zurück zum Client geleitet.


Abbildung : Authorization Server initiiert Redirect zum Client.

Schauen wir uns die HTTP Antwort aus (4) an:

HTTP/1.1 307 Temporary Redirect Location: https://client:2000/oauth2callback? code=j67dgao1cce6tbnpk76c529vin& state=security_token%3D3ndp324l1q2pld9cod3emhcqru%26url%3D/

An dieser Stelle führt der OAuth2 Authorization Code Grant sein erstes Credential ein - den (Namensgeber) Authorization Code. Beim Authorization Code handelt es sich um ein einmalig verwendbares Token. Der Authorization Code dient als Vor-Authorisierung und ist an den Client über die Client ID gebunden. Der Authorization Code ist eine schwer erratbare zufällige Zeichenkette und hat nur einen Zweck - Tausch gegen ein anderes (dauerhafteres) Credential in einem späteren Teil des Authorization Code Grants.

Der State Wert muss mit dem Wert aus (2) übereinstimmen.

Teil der Nachricht Erläuterung

HTTP/1.1 307 Temporary Redirect

Location: https://client:2000/oauth2callback?

HTTP Weiterleitung auf den Client. Die Location ist die Redirect URI die der Client bei seiner Registrierung und bei (2) angegeben hat.
code=j67dgao1cce6tbnpk76c529vin Der Authorization Code - ein Einmal-Token zum Tauschen gegen ein anderes Credential.
state=security_token%3D3ndp324l1q2pld9cod3emhcqru%26url%3D/ Muss die Wiederholung des Werts aus (2) sein.

5. Callback Aufruf beim Client

Der User-Agent folgt der Weiterleitung auf den Client.


Abbildung : User-Agent ruft Client auf.

Die HTTP Anfrage aus (5):

GET /oauth2callback? code=j67dgao1cce6tbnpk76c529vin& state=security_token%3D3ndp324l1q2pld9cod3emhcqru%26url%3D/ HTTP/1.1

Fortführung der Weiterleitung aus (4). Der User-Agent liefert den Authorization Code an den Client.

6. Austausch des Authorization Codes gegen das Access Token

Nach Erhalt des Authorization Codes und der Überprüfung des States fordert der Client ein Access Token vom Authorization Server an.


Abbildung : Austausch des Authorization Codes gegen das Access Token

Die HTTP Anfrage aus (6) startet den Austausch des Codes für ein Access Token:

POST /oauth2/token HTTP/1.1 Content-Type: application/x-www-form-urlencoded Authorization: Basic YWJjOmRlZg== code=j67dgao1cce6tbnpk76c529vin& redirect_uri=https://client:2000/oauth2callback& grant_type=authorization_code

Bei Aufruf des Client Callbacks durch den Browser überprüft der Client den State um CSRF Angriffe zu vermeiden. Folgend soll der Authorization Code für das zweite OAuth2 Credentials - das Access Token - eingetauscht werden. Hierfür muss sich der Client gegenüber dem Authorization Server authentifizieren. Mit der Authentifizierung wird geprüft, ob der Client auch der ist, für den er sich ausgibt und ob der Authorization Code für diesen Client ausgestellt wurde. Die Authentifizierung findet über Basic Authentication statt.

Im Body der Anfrage stehen der einzutauschende Authorization Code, die vorherige Redirect URI und der gewählte Grant. Der Authorization Code ist der vom Authorization Server über den User-Agent erhalte Einmal-Token, der letztendlich auch die Autorisierung des Benutzers darstellt. Bei korrekten Client Credentials wird dieser gegen das dauerhaftere Access Token eingetauscht. Die Redirect URI muss erneut mit den vorherigen Werten übereinstimmen. Zuletzt kommt noch der Grant Type. Hier wird erneut der gewählte OAuth2 Grant erwähnt, damit der Authorization Server entsprechend reagieren kann.

Teil der Nachricht Erläuterung
POST /oauth2/token HTTP/1.1 Der Austausch des Authorization Codes wird als POST Anfrage durchgeführt. Es wird der Token Endpunkt des Authorization Servers aufgerufen
Content-Type: application/x-www-form-urlencoded Encoding des Bodies der Anfrage
Authorization: Basic YWJjOmRlZg== Hier sind die Client Credentials im Basic Authentication Format hinterlegt. Es werden die Werte client_id (abc) und client_secret (def) Base64 kodiert.
code=j67dgao1cce6tbnpk76c529vin Der auszutauschende Authorization Code
redirect_uri=https://client:2000/oauth2callback Die Redirect URI aus der Registrierung des Clients, aus (2), aus (4) und aus (5)
grant_type=authorization_code Teilt den ausgewählten OAuth2 Grant mit. Hier Authorization Code Grant.

7. Erhalt des Access Tokens

Der Authorization Server stellt das Access Token für den Client aus.


Abbildung : Der Authorization Server stellt das Access Token aus.

Der Authorization Server antwortet in (7) mit einem JSON bestehend aus der Autorisierung:

HTTP/1.1 200 Ok Cache-Control: no-store Pragma: no-cache {"access_token":"tl9jckcemkk4t3mrcujkj41260", "token_type":"Bearer", "expires_in":900, "scope":"openid mail", "id_token":"eyJraWQiOiJsdXRhYXVxMGE2ajdlOXI1Zm1lYWR…KfBHxRqpAlpfC3i2SmLxEev2SynrDqxmw", "refresh_token":"pc2movr8gls98er4e66ghhjpqi"}

Mit Erhalt des Access Tokens bekommt der Client die Autorisierung im Namen des Benutzers eine Aktion durchzuführen. Es handelt sich in diesem Beispiel wieder um eine schwer erratbare zufällige Zeichenkette. Das Access Token hat eine kurze Lebensdauer und ist Ersatz für die Benutzer Credentials. Die Lebensdauer wird über den expires_in Wert bereitgestellt. Der Typ des Tokens ist Bearer. Der Bearer Typ gibt 3 Möglichkeiten vor, wie das Access Token dem Resource Server präsentiert werden kann (Authorization Header, Body Payload und als Query Parameter). Der für dieses Access Token gewährte Gültigkeitsbereich wird im Scope Parameter beschrieben. Es wurden die selben Scopes gewährt, wie die, die angefragt wurden. Der Authorization Server könnte hier ggf. den Scope weiter einschränken, z.B. anhand der Client ID. Läuft ein Access Token ab muss nicht erneut der gesamte OAuth2 Grant durchlaufen werden. Über das Refresh Token kann erneut ein Access Token erfragt werden. Hierfür wird ein separater Grant durchgeführt. Durch den Scope Wert openid wurden implizit Informationen zum Authentifizierungsereignis des Benutzers bereitgestellt. Diese werden als JWT in compact serialization im ID Token übergeben. Hierdurch kann ein Client Informationen zum Benutzer an den Resource Server übermitteln.

Teil der Nachricht Erläuterung
HTTP/1.1 200 Ok Erfolgsmeldung zum Eintausch des Authorization Codes für das Access Token
Cache-Control: no-store Die Anfrage und Antwort sollen nicht gecacht werden.
Pragma: no-cache Kompatibilität: Eigentlich nur für Anfragen gültig, wird hier aber in der Antwort gesetzt und hat semantisch die selbe Auswirkung wie Cache-Control: no-cache
"access_token":"tl9jckcemkk4t3mrcujkj41260" Das Access Token ermöglicht dem Client im Namen des Benutzers auf den Resource Server zuzugreifen. Der Client hat es im Austausch für den Authorization Code erhalten.
"token_type":"Bearer" Gibt die Art und die Verwendungsmöglichkeiten des Access Tokens an.
"expires_in":900 Gibt die Lebensdauer des Tokens in Sekunden an. Hier 15 Minuten.
"scope":"openid profile" Der gewährte Gültigkeitsbereich des Access Tokens.
"refresh_token":"pc2movr8gls98er4e66ghhjpqi" Ermöglicht die Erneuerung der Autorisierung durch Erneuerung des Access Tokens
"id_token":"eyJraWQiOiJsdXRhYXVxMGE2ajdlOXI1Zm1lYWR…KfBHxRqpAlpfC3i2SmLxEev2SynrDqxmw" Nicht Teil von OAuth2, sondern von OpenID Connect Core Bereitstellung von Informationen zur Authentifizierung des Benutzers. Das Token ist hier nicht vollständig, sondern mit ... in der Mitte gekürzt.

Hiermit endet die Spezifikation zu OAuth2. Es bleiben aber einige Fragen unbeantwortet, z.B.:

  1. Behält der Client die Autorisierung für sich?
  2. Sendet er die Autorisierung zum Resource Server?
  3. Wie wird ein Access Token validiert?

Mögliche Varianten folgen und werden teilweise mit OpenID Connect Core beantwortet

8. Aufruf der Mails Ressource

Der Client ruft die Mails Ressource auf


Abbildung : Aufruf der Ressource

Eine beispielhafte HTTP Anfrage für (8) ist folgend aufgeführt:

GET /mails HTTP/1.1 Authorization: Bearer tl9jckcemkk4t3mrcujkj41260 X-Authenticated-Username: thomas X-EMAIL: batman007@predic8.de

Wichtig: Die Spezifikation enthält keine Angaben, wie der Aufruf des Resource Server erfolgt.

Die Anfrage enthält mehrere Möglichkeiten wie der Resource Server angesprochen werden kann. Sind Client und Resource Server nicht unter Kontrolle von verschiedenen Parteien so ist es völlig frei, ob das Access Token, ein User Identifier, die Email o.ä. übertragen wird. Hier muss der Resource Server nur mit einer der Möglichkeiten umgehen können und der Client sicherstellen, dass keiner der Header ohne Kontrolle von außen eingespielt werden kann.

In der Abbildung angedeutet ist der Fall, dass das Access Token mit der Anfrage mitgeschickt wird. Dieses würde im Format Authorization: Bearer {TOKEN} als Header mitgeliefert werden (Bearer Token Usage, RFC 6750).

9. und 10. Resource Server validiert Anfrage

Der Client hat der Anfrage ausreichend Informationen beigelegt damit der Resource Server seine Arbeit vervollständigen kann. Hier kann das Access Token ausreichen, ggf. wurde Benutzername oder Email mitgeschickt.

Der Resource Server antwortet mit den Emails.


Abbildung : Antwort des Resource Servers

Die HTTP Antworten aus (9) und (10) haben keine OAuth2 spezifischen Angaben, sondern beinhalten die fachliche Antwort der Gegenseite:

HTTP/1.1 200 Ok {…}

Die Emails werden an den User-Agent übergeben.

(11.) Anfragen an die Ressource nach Durchführung eines OAuth2 Grant

Über den User-Agent wird erneut eine Anfrage an den Resource Server gesendet.


Abbildung : Anfrage an den Resource Server mit Hilfe eines Session Cookies.

Nach erfolgreicher Autorisierung ruft der User-Agent erneut den Client auf. Der Client hatte zuvor eine Session angelegt und diese im Cookie Header hinterlegt. (1) Bei folgenden Anfragen kennt der Client den User-Agent bereits und kann dann in (2) z.B. direkt das Access Token an die Anfrage anhängen. (3) und (4) verhalten sich wie zuvor - es werden die Emails übermittelt.

Hinweis: Das Access Token hat nur eine geringe Lebensdauer und muss gelegentlich vom Client erneuert werden. Hierfür kann das Refresh Token oder eine erneute Durchführung des Authorization Code Grants genutzt werden.

Fazit

In diesem Artikel wurde der Authorization Code Grant im Detail auf HTTP Ebene aufgezeigt. Der Ablauf wird durch den Client initiiert, gefolgt von der Authentifizierung des Resource Owners, Ausgabe des Authorization Codes und Austausch des Access Tokens. Es wurde klar, dass die Benutzer Credentials nur beim Authorization Server überprüft werden und die weitere Autorisierung über das Access Token stattfindet.

Doch wie wird die Autorisierung überprüft? Das OAuth2 Framework lässt hier Fragen offen die über weitere Spezifikationen zu klären sind. Die OAuth 2.0 Token Introspection als auch die OpenID Connect Core Spezifikation liefern hier weitere Informationen.

YouTube

Das Video zum Artikel:


API Sicherheit aus der Perspektive eines Hackers:

Schulungen

Erfahre mehr zu OAuth2 und OIDC in der Schulung zur API Sicherheit.