Autorisierungsdienste mit OAuth

Das OAuth-Protokoll spielt in einigen Webanwendungen für den Datenaustausch und für REST-Webservices bereits eine große Rolle.

In Pocket speichern vorlesen Druckansicht
Lesezeit: 13 Min.
Von
  • Dr. Lofi Dewanto
  • Alexander Neumann
Inhaltsverzeichnis

Das OAuth-Protokoll ist nicht so bekannt wie OpenID, spielt jedoch in einigen Webanwendungen für den Datenaustausch und für REST-Webservices bereits eine große Rolle. heise Developer untersucht, welche Formen des Datenaustauschs und welche Integrationsmöglichkeiten OAuth unterstützt.

Mehr Infos

Internet-Identität und Datenaustausch heute – Nutzung und Möglichkeiten von OpenID und OAuth

Die Geburtsstunde von OAuth liegt im Jahr 2007. Das Protokoll findet mittlerweile in vielen konsumentenorientierten Websites wie Yahoo, AOL, Google und Flickr Verwendung. Es ermöglicht dem User (Endnutzer) einer Webanwendung (Service-Provider) private Ressourcen (Protected Resources) wie Fotos, Videos, Kontaktliste und Kontoauszug mit allen anderen Webanwendungen (Konsument) auszutauschen, ohne Nutzername und Passwort der Service-Provider-Webanwendung den Konsumenten-Applikationen preiszugeben. OAuth verwendet ein sogenanntes Token für die Übertragung von Nutzername und Passwort.

Oberflächlich betrachtet ist der Prozess mit dem in OpenID vergleichbar. Beide haben jedoch unterschiedliche Einsatzbereiche. Sämtliche Spezifikationen im OpenID-Umfeld beschäftigen sich mit Authentifizierung und Identitätsmanagement. Eine typische Frage im OpenID-Kontext ist beispielsweise: "Ist die Person, die sich einloggen will, tatsächlich Herr Frank Müller?" OAuth hingegen unterstützt schwerpunktmäßig einen zentralisierten Autorisierungs- und Datenaustauschprozess sowie einen delegierten Aufruf von REST-Webservices (Represential State Transfer) [1]. Wie sich der Nutzer – etwa über einfaches Login mit Name und Passwort oder per OpenID-Authentifizierungsprozess – autorisieren lässt, spielt eine untergeordnete Rolle. Die typische Frage im Kontext lautet: "Darf Herr Frank Müller, der sich korrekt authentifiziert hat, die Fotos seiner Flickr-Anwendung an die Applikation eines Druckdienstleisters Printeria übertragen?"

Da ein Datenaustausch à la "OpenID Attribute Exchange"-Spezifikation ebenfalls möglich ist, benötigt man eine klare Abgrenzung. Eine solche liefert der nächste Artikel der Serie ausführlich. Es ist allerdings wichtig, vorab zu erwähnen, dass OAuth keine OpenID-Erweiterung darstellt, denn es sollten sich unterschiedliche Authentifizierungsmechanismen außer OpenID verwenden lassen. Das bedeutet jedoch nicht, dass das OAuth-Protokoll eine komplette Neuentwicklung ist. Es hat seinen Ursprung in bekannten Autorisierungsmechanismen wie Google AuthSub, AOL OpenAuth, Yahoo BBAuth, Flickr API und Amazons Webservices-API (AWS).

OAuth zu verwenden ist mit der Bezahlung per EC-Karte zu vergleichen. Möchte man in einem Restaurant mit der Karte (Service-Provider) bezahlen (Geld stellt die auszutauschenden Ressource dar), gibt niemals der PIN-Code (Benutzername und Passwort) dem Kellner (Konsument) Bescheid. Stattdessen tippt der Karteninhaber den PIN-Code direkt in das Eingabegerät des Kartenlesers ein. (Ein anderes Beispiel, wie das Zusammenspiel zwischen Service-Provider, Konsument und Endnutzer anschaulich aussehen kann, findet man in Eran Hammer-Lahavs "Beginner's Guide to OAuth".

Die folgende Tabelle beschreibt Rollen und Begriffe in OAuth. Sie dienen als Basis für die Definition des OAuth-Protokolls beziehungsweise die mit ihm einhergehende Spezifikation.

Begriff Bedeutung
Service-Provider Ein Service-Provider stellt seine private Ressourcen zur Verfügung, auf die sich von anderen Anwendungen zugreifen lässt. Anzumerken ist, dass ein Service-Provider nicht gleichzeitig derjenige sein muss, der eine Authentifizierung des Endnutzers durchführt. Ein Service-Provider kann die Aufgabe beispielsweise an einen OpenID-Provider weitergeben.
Endnutzer Ein Endnutzer besitzt private Ressourcen, die er, nachdem er zugestimmt hat, den anderen Webanwendungen zur Verfügung stellen will.
Konsument Ein Konsument beziehungsweise eine Konsumenten-Anwendung ist eine Applikation, die einen bestimmten Service oder private Endnutzer-Ressourcen eines Service-Providers in Anspruch nehmen will. Die Anwendung kann unterschiedliche Formen annehmen wie eine Desktop-, Mobile- und Webanwendung. Wichtig ist, dass der Entwickler der Anwendung (genannt Konsumenten-Entwickler) sich im Voraus Konsumenten-Schlüssel und -Geheimnis vom Service-Provider besorgt hat und sie in der Konsumenten-Anwendung einbauen muss.
Private Ressourcen Private Ressourcen können in unterschiedlichen Formen auftreten: Daten (Fotos, Dokumente, Kontakte), Aktivitäten (Blog posten, Geld überweisen) und einfacher URL, der zu schützen ist. Private Ressourcen stellen ein oder mehrere Webservices, meist in Form eines REST-Modells, dar.
Token Ein Token verwendet man statt des Nutzernamens und des Passworts, um Autorisierung auf privaten Ressourcen zu ermöglichen. Ein Token besteht meistens aus einem zufälligen String (Buchstaben und Zahlen). Es ist eindeutig und schwer zu erraten. Zudem wird es mit einem Konsumenten-Geheimnis kombiniert. OAuth verwendet zwei unterschiedliche Token-Typen: Anfrage- und Zugriffs-Token.

Es gibt zwei typische Anwendungen für OAuth:

1. Szenario: OAuth mit Endnutzerszenarien (originale OAuth-Version oder dreibeiniger OAuth-Typ genannt):
Es ermöglicht eine Interaktion mit Endnutzern. Service-Provider, Konsument und Endnutzer stellen die drei Elemente dar, die diesen Typ ausmachen (daher die Bezeichnung "dreibeinig"). Er ist für Datenaustausch und Webservice-Aufrufe zwischen Webanwendungen mit der Zustimmung des Endnutzers gedacht. Das Beispiel "Bezahlung mit einer EC-Karte" gibt seine Workflow wieder. Abbildung 1 zeigt ein Interaktionsdiagramm des Protokolltyps.

Interaktion bei OAuth mit Endnutzerszenarien (Abb. 1)


2. Szenario: OAuth ohne Endnutzeraktivitäten (Basisversion, "phone home", "signed request" oder zweibeinige OAuth genannt):
Es geht ausschließlich um eine Maschine-zu-Maschine-Kommunikation, ohne Interaktion von Endnutzern (daher die Bezeichnung zweibeinig, da der Endnutzer entfällt). Bei diesem Typ ist keine Authentifizierung des Endnutzers nötig. Er wird per ID aus der Konsumentenanwendung erkannt und an den Service-Provider weitergegeben. Der Typ ist für einen sicheren Zugriff über Webservices gedacht. Abbildung 2 zeigt die Interaktion des Protokolls.

Interaktion bei OAuth ohne Endnutzerszenarien (Abb. 2)

Konsumenten-Schlüssel und -Geheimnis (Abb. 3)


Für den dreibeingen Typ existiert eine offizielle Spezifikation, für die es bereits eine Überarbeitung gibt (siehe unten "Sicherheitsproblem in OAuth"). Für den zweibeinigen Typ ist nur eine Draft-Spezifikation vorhanden. Sie nimmt jedoch eine wichtige Rolle ein, da REST-Webservices ohne Endnutzer-Interaktion von der Spezifikation profitieren. Zudem verwendet sie die Open-Social-Community intensiv.

Bevor eine Konsumenten-Anwendung auf einem Service-Provider zugreifen kann, ist sie zuvor beim ihm anzumelden. Service-Provider benötigen meistens folgende Daten: Name, Autor und URL der Anwendung. Anschließend erhält die Konsumenten-Applikation Konsumentenschlüssel und -geheimnis. Der Schlüssel wird während der gesamten Kommunikation zwischen Konsumenten und Providern innerhalb einer Anfrage mit angegeben. Damit kann ein Service-Provider die Konsumenten-Anwendung erkennen. Die wiederum verwendet das Geheimnis für das Signieren der Anfrage. Der Service-Provider erhält die Ergebnissignatur und überprüft sie darauf hinsichtlich ihrer Korrektheit. Das Diagramm aus Abbildung 3 stellt den Sachverhalt übersichtlich dar.

Detaillierte Interaktion bei OAuth mit Endnutzerszenarien (Abb. 4)

Das Aktivitätsdiagramm aus Abbildung 4 zeigt, wie die Interaktionen zwischen den Akteuren in der originalen OAuth-Version stattfinden. Im Prinzip handelt es sich um die Kommunikation zwischen Konsumenten, Service-Provider und Endnutzer. Bei der Originalversion finden folgende Schritte statt:

  • Der Konsument fragt nach einem nicht bestätigtem Anfrage-Token des Service-Providers.
  • Der Endnutzer bestätigt den Anfrage-Token mit einer Authentifizierung beispielsweise durch ein Login beim Service-Provider. Den bestätigten Token erhält darauf der Konsument mitgeteilt.
  • Der Konsument tauscht das bestätigte Anfrage-Token mit einem Zugriffs-Token aus.
  • Mit dem zuvor empfangenen Zugriffs-Token fragt der Konsument anschließend aus den privaten Ressourcen des Service-Providers heraus nach den Daten.
  • Der Service-Provider antwortet mit den erfragten Daten.
  • Der Konsument erfragt die Daten bei den privaten Ressourcen des Service-Providers.
  • Der Service-Provider antwortet nach einer Überprüfung des Tokens mit den erfragten Daten.
Explanation: The Difference Between OpenID and OAuth

Wie heise Developer berichtete, gab es ein Sicherheitsproblem für das dreibeinige OAuth-Protokoll. Dabei ging es um das Ausnutzen des Anfrage-Tokens und der Session beim Autorisierungsprozess in OAuth (dreibeiniges Oauth-Protokoll Version 1.0, Sektion 6). Der Angreifer loggt sich in eine Konsumenten-Webanwendung ein und initiiert den Autorisierungsprozess zu einem Service-Provider. Statt jedoch den Prozess weiter durchzuspielen, speichert er den Anfrage-URI (Uniform Resource Identifier) inklusive des Anfrage-Tokens. Später versucht der Angreifer beispielsweise mit Phishing ein Opfer zu finden, das den Autorisierungsprozess mit dem gespeicherten Anfrage-URI aus dem gleichen Konsumenten weiterführt. Damit ermöglicht das Opfer dem Service-Provider einen Zugriff auf seine private Ressourcen.

Mit dem Klick auf den Anfrage-URI des Angreifers führt das Opfer den Autorisierungsprozess des Angreifers mit dem vom Konsument ausgestellten Anfrage-Token weiter. Das heißt, das Opfer würde gar nicht merken, dass ein Angriff stattgefunden hat. Nachdem es seine privaten Ressourcen beim Service-Provider freigegeben hat, kann der Angreifer den gespeicherten Anfrage-URI wieder ausführen. Er kann nun auf sämtliche vom Opfer freigegebenen Ressourcen zugreifen. Im Fall, dass der Angreifer ebenfalls ein Konto auf dem echten Konsumenten besitzt, wird der Zugriff für die zukünftigen Aktionen sogar gespeichert. Damals schlugen die von der Sicherheitslücke betroffenen Organisationen schnell eine Lösung vor, die die Endnutzer darüber informiert, dass eine Autorisierung aus einer unbekannten Quelle eine Gefahr darstellt und sie diese nicht durchführen sollten.

Derzeit existieren zwei OAuth-Bibliotheken für Java: zum einen die originale OAuth-Implementierung auf Google Code. Zum anderen findet man mit oauth-signpost eine Alternative, jedoch ausschließlich für Konsumenten beziehungsweise Konsumenten-Entwickler. Der Artikel widmet sich im Folgenden der originalen Bibliothek. Das dieser entnommene Beispiel zeigt ausschließlich dreibeinige Implementierungen, da sie aufwendiger als die zweibeinigen sind.

Zu Beginn ist ein einfacher Service-Provider aufzubauen. Anschließend erstellt man eine Konsumenten Anwendung, die auf den implementierten Service-Provider zugreift.

Die Quellcodes lassen sich hier als Eclipse-Workspace herunterladen. Folgende Voraussetzungen sind für die Beispiele wichtig:

README.txt

Die Servlet-Klasse SampleProviderConsumer dient als Konsumenten-Beispiel für den im nächsten Abschnitt beschriebenen Beispiel-Service-Provider. Die wichtigsten Punkte in der Klasse sind:

  • Die Methode doGet(...) in der Klasse SampleProviderConsumer wird aufgerufen, falls der Beispiel-Service-Provider in der Startseite des Konsumenten ausgewählt wird (http://localhost:9090/oauth-example-consumer/SampleProvider). Hier ist zu beachten, dass der Service-Provider keine persistente Speicherung der Session durchführt, sodass nach seinem Neustart eine neue Autorisierung – und gleichzeitig eine neue Authentifizierung – stattfinden muss.
  • In der Klasse CookieConsumer liest man die Konfiguration des Konsumenten-Geheimnisses ein. Zudem speichert man das Zugriffs-Token, das der Service-Provider zur Verfügung stellt. Die Klasse CookieConsumer lässt sich in der Methode doGet(...) der oben genannten Klasse verwenden.

Es sind drei wichtige Servlet-Klassen vorhanden, die die Anfrage eines Konsumenten bedienen sollten. Die wichtigsten Punkte der einzelnen Servlet-Klasse sind:

  • RequestTokenServlet (ein nicht bestätigter Anfrage-Token): Die Servlet-Klasse kümmert sich um das Anfrage-Token und das Konsumenten-Geheimnis.
  • AuthorizationServlet (ein bestätigter Anfrage-Token): Die Servlet-Klasse dient als Beispiel, wie die Authentifizierung und Autorisierung des Endnutzers stattfinden können. Falls er noch nicht authentifiziert und autorisiert ist, bietet man ihm eine einfache Login-Seite (authorize.jsp) an. Falls das bereits geschehen ist, wird der Endnutzer an die Konsumenten-Seite zurückgeleitet (über die Methode returnToConsumer).
  • AccessTokenServlet: Sie generiert den Zugriffs-Token und gibt ihn anschließend an die Konsumenten-Seite weiter.

Die Tatsache, dass viele Webanwendungen OAuth unterstützen, ist Grund genug, es in eine Webanwendung zu integrieren, falls Bedarf an Datenaustausch und delegierten Webservices-Aufrufen vorhanden ist. Um auf die Daten und Funktionen von Google, Twitter und Yahoo zugreifen zu können, kommt man sowieso nicht mehr an OAuth vorbei. Derzeit ist die dreibeinige OAuth-Umsetzung verbreiteter, jedoch erscheint die Erweiterung um die zweibeinige OAuth-Realisierung auf jeden Fall sinnvoll, da dadurch viele Integrationsarbeiten im Bereich der REST-Webservices einfacher umzusetzen sind. Eine einfache Erklärung für die beiden Spezifikationen ist derzeit leider noch schwer oder nur verstreut zu finden. Das liegt wahrscheinlich daran, dass die zweibeinige Spezifikation bis heute noch nicht final ist. Ansonsten ist die Spezifikation für OAuth sowohl durch die drei- als auch die zweibeinige gut strukturiert und einfach zu verstehen. Vom Aufbau der Spezifikationen sind viele Ähnlichkeiten zu OpenID zu erkennen, da einige verantwortliche Personen gleichzeitig in beiden Spezifikationen mit arbeiten.

Für Java-Entwickler gibt es OAuth für Java und oauth-signpost, sodass eine Protokoll-Implementierung der Spezifikation für die Integration von OAuth in den eigenen Anwendungen nicht mehr notwendig ist. Java-Entwickler müssen nur noch die entsprechenden APIs ansprechen. In den genannten Projekten sind einige Anwendungsbeispiele zu finden. Leider fehlt oft die relevante Dokumentation. Java-Code-Beispiele für die zweibeinige Spezifikation existieren kaum und sind meistens auf Basis der Protokollbeschreibungen umgesetzt.

Dr. Lofi Dewanto
arbeitet als Softwareentwickler bei der Deutschen Post Com GmbH. Er engagiert sich insbesondere für "javanische" Open-Source-Software sowie MDA.
(ane)