OAuth2 in der Praxis: Anwendungssetup mit GitHub

OAuth2 ist inzwischen sicherlich einigen Lesern ein Begriff. Dazu beigetragen haben auch die vorherigen Artikel auf diesem Blog zu Single-Sign-On allgemein und OAuth2 im Konkreten. Daher soll in diesem Artikel einmal das grundlegende Setup einer OAuth2-Anwendung am Beispiel der GitHub-OAuth2-API durchgespielt werden.

Setup einer OAuth2-Anwendung

Um eine OAuth2-Anwendung aufzusetzen, muss diese zunächst beim betreffenden Service (in diesem Beispiel GitHub) registriert werden. Dabei wird neben einem Namen für die Anwendung und einer Website auch eine Callback-URL angegeben. Anschließend wird dann die öffentliche ClientId und ein privates Client Secret generiert. ClientId und Client Secret müssen der entsprechenden Client-Anwendung natürlich mitgeteilt werden, damit diese sich authentifizieren kann. Ein Beispiel, wie dieses Setup aussehen könnte, ist im folgenden, reduzierten Screenshot von GitHub zu sehen:

GitHub: Setup einer OAuth2-App

GitHub: Setup einer OAuth2-App


Auf GitHub gibt es Felder für den Anwendungsnamen, die Website, die Beschreibung, etc. Außerdem kann die Callback-URL im Feld ‘Authorization Callback URL’ angegeben werden. Diese ist die URL, an welche ein Client, beispielsweise während des Authorization-Code-Workflows, mit dem Authorization-Code weitergeleitet wird. Diese Callback-URL ist in unserem Fall zu Testzwecken auf https://localhost:8080/auth/code/ gesetzt.

Beispiel: GitHub

GitHub unterstützt bei seiner OAuth2-Schnittstelle die Authentifizierungsmethode mit Authorization Code. Wie der Informationsaustausch bei der Verwendung dieser Methode im Detail funktioniert, zeigt die folgende Grafik:

OAuth2 mit GitHub via Authorization Code

OAuth2 mit GitHub via Authorization Code

Im ersten Schritt wird eine GET-Anfrage vom Client an den Authorization Server von GitHub geschickt. Diese geht an die /authorize-URL. Für GitHub lautet diese https://github.com/login/oauth/authorize. Dieser GET-Aufruf enthält in unserem Bespiel aus der Abbildung einige Parameter. Der Parameter client_id enthält die während des Aufsetzens erhaltene, öffentliche ClientId der Anwendung. Außerdem wird der Permission-Scope, in diesem Fall user:email der angeforderten Berechtigungen mitgesendet. Hier soll nur auf die Emailadresse des Benutzers zugegriffen werden. Zusätzlich gibt es noch einige optionale Parameter, auf die in diesem Beispiel verzichtet wird, da die GitHub-OAuth-Schnittstelle für diese implizite Standardwerte vorhält, sofern sie nicht explizit spezifiziert werden. Dazu gehört etwa eine Redirect-URL, an welche der Browser anschließend weitergeleitet wird. Sie muss gleich der im Setup definierten Callback-URL sein oder diese erweitern. Auch könnte noch mittels response_type=code der Authorization-Code-Workflow ausgewählt werden. Die GitHub-API verwendet diesen Workflow allerdings standardmäßig, daher muss er nicht explizit angegeben werden. Des Weiteren kann ein zuvor generierter Zustand (z.B. state=test1337) als Parameter angehängt werden. Dieser dient dazu, die Transaktion später wieder zu identifizieren und zuordnen zu können. Dieser Zustand wird üblicherweise in einem Cookie gespeichert.

Nachdem der GitHub Authorization Server diese Anfrage an /authorize erhalten hat, muss der Benutzer die Berechtigungsanfrage bestätigen. Bei GitHub öffnet sich beispielsweise, sofern man bereits eingeloggt ist, ein Popup, welches in etwa so aussieht:

GitHub OAuth2 Notification

GitHub OAuth2 Notification

Sobald der Benutzer auf den grünen Button mit der Aufschrift ‘Authorize steffenjacobs’ geklickt hat, wird der Browser mit seinem Authorization Code an die beim Aufsetzen hinterlegte Callback-URL weitergeleitet. Wenn in der vorherigen GET-Anfrage eine Redirect-URL angegeben wurde, muss diese mit der beim Aufsetzen festgelegten Basis-URL (Callback-URL) übereinstimmen, darf aber Unterordner der angegebenen Basis-URL enthalten. Bei diesem HTTP-Redirect wird der Authorization Code dem Browser als URL-Parameter mitgegeben. Die Idee ist, die Redirect-URL so einzustellen, dass diese entweder gleich auf den Applicationserver des Anwendungsanbieters weiterleitet, oder auf eine lokale Adresse, auf welcher ein Server wartet, der den Authorization Code dann in Empfang nimmt.

Im nächsten Schritt wird nun der Authorization Code in ein Access-Token umgetauscht. Dazu wird eine POST-Anfrage an die /token-URL (bei GitHub /access_token-URL) des Dienstes geschickt. Diese POST-Anfrage enthält, wie aus der obigen Abbildung zu entnehmen ist, wieder die ClientId und außerdem den soeben erhaltenen Authorization Code. Zusätzlich wird das Client-Secret, welches beim Aufsetzen der Anwendung erstellt wurde, mitgeschickt. Zurück kommt vom Authorization Server ein Access-Token und je nach Implementierung eine Verfallszeit und der Umfang der Berechtigung (Scope, im Beispiel oben user:email).

In unserem GitHub-Beispiel kommt die folgende Antwort zurück:

access_token=083e0adba93e78bde9d02292cd7ce60492679d53
&scope=user%3Aemail
&token_type=bearer

Es handelt sich also um ein Bearer-Token, welches auf alle API-Funktionalitäten zugreifen kann, für die die Berechtigung user:email nötig ist.

Alternativ kann bei der HTTP-POST-Anfrage auch im Header das Feld Accept auf application/json gesetzt werden. Dann kommt nach dem Aufruf der /token-Methode ein JSON-Objekt zurück:

{
    "access_token": "b194dc8c2dc6e26ff1d4847250e1b7ae87321863",
    "token_type": "bearer",
    "scope": "user:email"
}

Dieses lässt sich von der eigenen Client-Anwendung möglicherweise einfacher verarbeiten.

Anschließend lässt sich mit Hilfe des Access-Tokens auf die API des Dienstes zugreifen. In diesem Beispiel kann nun neben dem öffentlichen Profil des Benutzers die Emailadresse abgerufen werden. Um zum Beispiel die öffentlichen Profildaten abzurufen, wird eine GET-Anfrage an den entsprechenden User-Endpunkt der GitHub-API geschickt, welche als URL-Parameter das Access-Token enthält:

https://api.github.com/user?access_token=b194dc8c2dc6e26ff1d4847250e1b7ae87321863

Zurück kommt ein größeres JSON-Objekt mit allen Profildaten.

{
    "login": "steffenjacobs",
    "id": xxxxxxx,
    ...
    "created_at": "2014-08-18T14:49:17Z",
    "updated_at": "2019-01-08T15:37:24Z"
}

Alternativ kann auch eine GET-Anfrage an denselben Endpunkt (https://api.github.com/user) geschickt werden und im HTTP-Header das Feld ‘Authorization’ auf den Wert token b194dc8c2dc6e26ff1d4847250e1b7ae87321863 gesetzt werden. Zurück kommt das gleiche JSON-Objekt.

Short URL for this post: https://wp.me/p4nxik-3aq
Steffen Jacobs

About Steffen Jacobs

Java Consultant & Developer at Orientation in Objects GmbH. Follow me on Twitter and find me on LinkedIn and Xing. Some of the source code associated with the blog articles can be found on GitHub.
This entry was posted in Security and tagged , , , . Bookmark the permalink.

2 Responses to OAuth2 in der Praxis: Anwendungssetup mit GitHub

  1. Pingback: OAuth2 mit Java: Versenden eines Tweets über die Twitter-API | techscouting through the java news

  2. Pingback: Spring Boot: SSO mit OAuth2 via GitHub oder Facebook | techscouting through the java news

Leave a Reply