Warum OpenID Connect und OAuth nicht das gleiche ist, und weshalb du nicht darauf verzichten solltest.

10.08.2022Tom Trapp
Cloud oauth oidc accesstokens Authorization / Authentication Security

OAuth

Nachdem wir in meinem letzten TechUp bereits SAML kennengelernt haben, wollen wir in der Geschichte weiter in die Gegenwart reisen und stossen direkt auf OAuth. Open-Authorization (OAuth) ist ein Protokoll, bzw. eine Anmeldemethode, welche im Jahr 2007 der Version 1.0 veröffentlicht wurde. Im Jahr 2012 wurde dann der nicht rückwärts kompatible Nachfolger, und heute immer noch weit verbreitete, Release 2.0 veröffentlicht. Von hier an ist mit OAuth immer OAuth 2.0 gemeint. Hinter OAuth stecken Entwickler von Firmen wie Twitter und Google. Über die Jahre hinweg wurde OAuth 2.0 immer wieder mit unterschiedlichsten RFCs erweitert und angepasst.

Wichtig zu erwähnen ist, dass OAuth in erster Linie ein Authorisierungsprotokoll ist, und somit nichts direkt mit Authentifizierung zu tun hat. Ziel ist es, Benutzerdaten zwischen mehreren Plattformen zu übertragen. Hierbei wird nie ein Passwort übertragen!

Beispielsweise kann es sein, dass eine Third Party Website im Auftrag des Benutzers Profilinformationen und Bilder von Facebook abfragen will. Dafür muss die Erlaubnis des Benutzers, dass die Webanwendung die Profildaten von Facebook abrufen darf, vorliegen. OAuth kann eine solche Autorisierung sicherstellen und durchführen. Dabei behält Facebook die volle Kontrolle über die Daten und es werden keine Login-Informationen ausgetauscht. Hierbei werden der Webapplikation spezifische zeitlich begrenzte Permissions gegeben. So kann sichergestellt werden, dass die Drittanbieterwebsite beispielsweise keine anderen Aktionen ausführen darf, als etwas auf Facebook zu posten. Der Benutzer ist bereits bei beiden Diensten angemeldet und OAuth stellt lediglich sicher, dass Berechtigungen zwischen den beiden System vom Benutzer geprüft werden, und dann entsprechend ausgetauscht werden.

Technisch gesehen nutzt OAuth einen Token, um diese speziellen Berechtigungen zu übertragen.

Flow

Eine Welt ohne OAuth?

Figure: Quelle: By Devansvd - Own work, CC BY-SA 4.0, https://commons.wikimedia.org/w/index.php?curid=109591037

Das will sicher niemand! Im vorherigen Beispiel würde hier unsere face-nova Website die Benutzerdaten des Kunden von Facebook bekommen, um dort die Benutzerinformationen und Fotos abfragen zu können. Hier hat der Benutzer keine Kontrolle mehr, was mit seinem Account o.ä. passiert. Die Website hat vollen Zugriff und kann Kuddelmuddel posten oder persönliche Daten abfragen.

Der richtige Weg - mit OAuth!

Figure: Quelle: By Devansvd - Own work, CC BY-SA 4.0, https://commons.wikimedia.org/w/index.php?curid=109591026

OAuth bietet hier die Möglichkeit an, dass der Benutzer unserer face-nova Website spezifische Berechtigungen gibt, wie z.B. ausschliesslich Profilinformationen und Fotos lesen zu können. Teil des Flows ist ein Schritt, bei dem der Benutzer die entsprechenden Berechtigungen aufgelistet bekommt (Authorization Request) und zustimmen muss (Authorization Grant).

Dies geschieht über einen speziellen Access Token, welcher vom Anmeldedienst von Facebook (Authorization Server) ausgestellt wird. Die Third-Party-Website (Der Client, in unserem Fall face-nova) bekommt so Zugriff auf die Profilinfos und Fotos (Resources), welche bei Facebook liegen (Resource Server).

Wichtige Keywords

  • Resource Owner: Entität, welche Zugriff auf eine geschützt Ressource beantragt, klassischerweise der Endbenutzer.
  • Resource Server: Der Server, auf dem die geschützte Resource liegt. Dieser ist in der Lage auf Basis eines JWT Access Token den Zugriff zu gewähren.
  • Client: Die Anwendung (Web, Mobile, Desktop o.ä., auch Relying Party genannt), welche Zugriff auf die geschützte Ressource des Resource Owners möchte.
  • Authorization Server: Dienst, welcher den Resource Owner authentifiziert und einen Token ausstellt, klassischerweise der IdP (siehe IdP-SAML TechUp).
  • Consent: Die Eingabemaske, welcher der Benutzer sieht, bspw. “Anwendung X möchte Zugriff und beantragt Berechtigungen X”.
  • JWT: JSON Web Token, Art des Tokens, der zum Übertragen der Daten genutzt wird (mehr dazu siehe Stateless Sessions dank JSON Web Tokens.).
  • Grant Types: Mehr als vier unterschiedliche Prozesse zur Autorisierungsgenehmigung (authorization code, implicit, resource owner password credentials, client credentials, etc.), um Client und Resource Owner authentifizieren.
  • Scopes: Die einzelnen Berechtigungen können mittels unterschiedlicher Scopes angefragt werden.

Soviel zu OAuth. bzw. OAuth 2.0, nun wollen wir auf diesem Wissen aufbauen und OIDC genauer anschauen!

OIDC

Open ID Connect ist ein Authentifizierungsstandard, welcher OAuth 2.0 als Grundlage verwendet. Hinter dem Standard steckt die OpenID Foundation. Gleich wie bei SAML, wird OIDC genutzt, um einen Benutzer, welcher sich zuvor an einer zentralen Stelle, dem IDP, angemeldet hat gegenüber weiteren Systemen zu authentifizieren. Dabei spielt die Datenübertragung eine zentrale Rolle. In der tokenbasierten Authentifizierung können Benutzerdaten und Rechte direkt im Token mit übergeben werden. Die Kommunikation findet hier primär zwischen den IdP und dem Client, der sogenannte Relying Party, statt.

Heute ist OpenID Connect sehr weit verbreitet und nahezu alle IdP-Systeme unterstützen den Standard. Schauen wir uns das jetzt also etwas genauer an.

Tokens

Access Token

Access Tokens werden genutzt, um Zugriff auf eine Ressource zu gewähren. Eine Ressource kann hier ein API-Endpunkt, ein File, eine Datenbank oder ähnliches sein. Der Access Token wurde von OAuth ins Leben gerufen. Der Access Token kann einfach ein einfacher String sein, meist nutzt man hier aber ein JWT Token. Meist ist ein Access Token nur eine kurze Zeit gültig, daher nutzt man oft den Refresh Token in Kombination mit dem Access Token (mehr dazu später).

DO’s & DON’Ts

  • ❌ Access Tokens werden nicht zur Authentifizierung verwendet.
  • ✅ Access Tokens sollten rein zur Autorisierung genutzt werden.
  • ❌ Über einen Access Token sollte man den Benutzer nicht erkennen können, ferner kann man nicht sagen, ob der Benutzer noch eingeloggt ist oder nicht

ID Token

Der Identification Token wird dafür genutzt, um den Benutzer zu identifizieren. Speziell ist hier, dass der ID Token nicht von OAuth, sondern von OpenID Connect (OIDC) ins Leben gerufen wurde. Der ID Token muss immer im JWT Format mit Header, Payload/Body und Signature vorliegen.

Grundsätzlich besteht er unter anderem aus folgenden Feldern:

  • sub: Subject; die eindeutige Kennung oder ID des Benutzers.
  • aud: Audience; der Client, also die Applikation, für welchen der JWT generiert wurde.
  • iss: Issuer; der Aussteller des Tokens (issuing authority).

Ziel des ID-Tokens ist immer die Benutzung im Client (aud), um dort Informationen über den Benutzer, wie Kürzel, Vor- und Nachnamen nutzen zu können.

DO’s & DON’Ts

  • ❌ ID Tokens werden nicht für Autorisierung verwendet, lediglich für Identifizierung und Authentifizierung.
  • ❌ ID Tokens sollten keine Informationen zur Autorisierung wie Rollen o.ä. enthalten.
  • ❌ ID Tokens sollten nicht an eine API gesendet werden.

Refresh Token

Der Refresh Token ist ein Token, welcher grundsätzlich länger gültig ist als der Access Token, und zum Anfordern eines neuen, gültigen Access Tokens genutzt werden kann.

Wichtig ist hier zu beachten, dass der Refresh Token mit Vorsicht eingesetzt werden soll, und nicht zu lange gültig sein sollte. Ansonsten geniert man einen Masterschlüssel, mit dem man immer wieder gültige Access Tokens ausstellen kann.

Hier bietet OAuth bzw. OIDC weitere Sicherheitsmethoden, wie Token Rotation o.ä. an.

DO’s & DON’Ts

  • ❌ Refresh Tokens sollten nicht zu lange gültig sein.
  • ✅ Refresh Tokens müssen sicher aufbewahrt werden.

Endpoints

Authorization Endpoint

Über diesen Endpunkt wird der ganze Prozess der Autorisierung des Clients, sowie die Authentifizierung des Benutzers abgewickelt. Je nach Flow (mehr dazu später), ist hier eine Benutzerinteraktion nötig.

Token Endpoint

Der Token Endpoint tauscht einen OAuth 2.0 Grant (z.B. Code, Refresh Token o.ä.) in einen ID- und / oder Access Token um.

UserInfo Endpoint

Der UserInfo Endpoint gibt, wenn ein gültiger Access Token mit dem Request mitgeschickt wird, Benutzerinformationen / Claims zurück. Die zuvor angefragten Scopes werden zurückgegeben.

Scopes & Claims

Mittels sogenannter Scopes kann OAuth bestimmte Anweisungen geben oder Daten abfragen. Hierbei gibt es standardisierte Scopes wie OpenID, es besteht aber auch die Möglichkeit, eigene Scopes zu definieren.

Ein Scope kann aus einem Claim bestehen. Ein Claim ist einfach gesagt eine Aussage, bzw. eine Assertion, welche ein Subject (ein User oder der Authorization Server (IdP)) über sich oder ein anderes Subject macht. Schauen wir uns ein Beispiel an, damit alles klarer wird:

Der Scope profile ist genormt und besteht laut OIDC Spec aus (unter anderem) den folgenden Claims:

  • name: Der Name des Benutzers in leserlicher Form, z.B. Tom Trapp.
  • family_name: Der Nachname des Benutzers, z.B. Trapp.
  • given_name: Der Vorname des Benutzers, z.B. Tom.

Somit bekommt man, wenn man den Scope profile anfragt, End-User Informationen (Claims) zurück. Diese Claims werden in den JWT Token geschrieben, und sind dann beispielweise über dem UserInfo Endpoint abrufbar.

Mit Scopes kann aber beispielsweise auch ein bestimmtes Verhalten angefragt werden. So muss z.b. der Scope openid immer präsent sein, wenn es sich um einen OpenID Connect (OIDC) Flow handelt.

Wichtig zu erwähnen ist, dass alle Scopes im OIDC Client auf dem IdP freigeschaltet werden müssen. So kann man steuern, welcher Client bzw. welche Relying Party Zugriff auf welche Scopes & Claims und somit Benutzerattribute bekommt.

Flows

Nachfolgend wollen wir uns die unterschiedlichen Flows im OpenID Connect-Kontext genauer anschauen. Wichtig zu erwähnen ist, dass es für jede Webapplikation, welche einen OIDC Flow starten will, einen registrierten OIDC Client auf dem IdP braucht.

Dieser OIDC Client besteht (je nach Flow, unter anderem) aus folgenden Informationen:

  • Client ID: Die eindeutige ID des OIDC Clients.
  • Client Secret: In eindeutiges Passwort für diese Client ID.
  • Redirect uri: Der Callback Endpoint, welcher mit den Token vom IdP auf der Relying Party aufgerufen wird.
  • Response Types: Der Typ der Antwort, welche der Client erwartet. Klassischerweise code für einen Authorization Code.
  • Scopes: Die Assertions oder Permissions, welche die Relying Party anfragen darf.

Hier ist zu erwähnen, dass der OIDC Flow fehlschlägt, wenn z.B. eine falsche Redirect URI oder ein nicht freigeschalteter Scope von der Relying Party angefragt wird.

Authorization Code Flow

Für wen? Webapplikationen mit einem eigenen Backend, welches nicht öffentlich einsehbar ist (z.B. ein Server).

Ein Authorization Code ist ein sehr kurzlebiger Code, welcher beim Token Endpoint in Kombination mit dem client_secret gegen einen Access Token, einen ID-Token und/oder einen Refresh Token eingetauscht werden kann.

OIDC Authorization Code Flow

Figure: Quelle: (25.07.2022) https://backstage.forgerock.com/docs/am/7/oidc1-guide/openid-connect-authorization-code-flow.html

Authorization Code Flow with Proof Key for Code Exchange (PKCE).

Für wen? Beispielweise eine Single Page Application (SPA) ohne eigenes Backend.

PKCE sorgt mit code_challenge und code_verifier für zusätzliche Sicherheit, da der eigentliche Client Secret nicht sicher abgelegt werden kann (da FE Applikation). Diese beiden Parameter werden von der Relying Party generiert, auf dem IdP bei Request for Authentication gespeichert und später beim Eintauschen vom Auth Code wieder geprüft. So kann sichergestellt werden, dass der Aussteller eindeutig verifiziert wird.

OIDC Authorization Code Flow

Figure: Quelle: (25.07.2022) https://backstage.forgerock.com/docs/am/7/oidc1-guide/openid-connect-authorization-code-flow-pkce.html

Für wen? Single Page Application (SPA), welche keinen Access Token benötigt.

Sehr offen, wenig Sicherheit, DO NOT USE!

OIDC Implicit Flow

Figure: Quelle: (25.07.2022) https://backstage.forgerock.com/docs/am/7/oidc1-guide/openid-connect-implicit-flow.html

Client Credential Flow

Für wen? Machine to Machine oder Service to Service Communication. Wird genutzt, wenn der Resource owner auch der Client ist, quasi die eigenen Daten abgefragt werden.

OIDC Client Credential Flow

Figure: Quelle: (25.07.2022) https://backstage.forgerock.com/docs/am/7/oauth2-guide/oauth2-client-cred-grant.html

Resource Owner Password Flow

Für wen? Mit Vorsicht zu benutzen, wenn redirect-based Flows (wie Authorization Code Flow) nicht genutzt werden können. Hier benutzt der Client die Credentials des Resource Owners, um einen Access Token zu bekommen.

Auch dieser Flow ist nicht recommended und wird als “most insecure OAuth 2.0 Flow betrachtet”

OIDC Resource Owner Password Flow

Figure: Quelle: (25.07.2022) https://backstage.forgerock.com/docs/am/7/oauth2-guide/oauth2-ropc-grant.html

Ausblick OAuth 2.1

OAuth 2.1 steht in den Startlöchern und bringt einige wichtige Änderungen mit sich! Ziel ist es unter anderem, den OAuth 2.0 RFC-Dschungel wieder zu standardisieren.

Die wichtigsten Änderungen kurz erläutert:

  • PKCE (Proof Key for Code Exchange) ist neu zwingend erforderlich für den Authorization Code Flow.
  • Redirect URIs müssen neu mit einem exact String matching verglichen werden (Regex darf nicht mehr eingesetzt werden).
  • Der Implicit Grant Flow (response_type=token) wird aus der Spec komplett entfernt, dieser gilt als unsicher.
  • Resource Owner Password Credentials Grant Flow wird ebenfalls aus der Spec entfernt.
  • Bearer Tokens dürfen nicht mehr in Query String Parametern mitgegeben werden.
  • Refresh Tokens für “public” Clients werden eingeschränkt bzw. sicherer gemacht.

Ich hoffe, dass ich euch OAuth und OIDC etwas näher bringen konnte. Stay tuned für weitere interessante TechUp’s! 🚀

Tom Trapp

Tom Trapp – Problemlöser, Innovator, Sportler. Am liebsten feilt Tom den ganzen Tag an der moderner Software und legt viel Wert auf objektiv sauberen, leanen Code.