OAuth vs. OpenID Connect (OIDC) vs. SAML

Siehe auch

OAuth Flows

Der „Authorization Code“-Flow an einem konkreten Beispiel:

  • Eine eigene „PhotoPrint-App“ soll auf extern gespeicherte Fotos in einem Google Drive zugreifen können.

  • Die PhotoPrint-App benötigt daher eine „Google Drive Import“-Funktion, ohne selbst die Google-ID und das Passwort des Nutzers abzufragen. Stattdessen muss sich die PhotoPrint-App im Namen des Nutzers bei Google authentifizieren können.

  • Delegated Access: Die PhotoPrint-App und Google Drive vertrauen sich gegenseitig nicht, sondern nur dem Nutzer. Der Nutzer muss seine Zustimmung („Consent“) geben, damit die PhotoPrint-App auf Google Drive zugreifen kann. Eine Schaltfläche „Fotos von Google Drive importieren“ in der PhotoPrint-App leitet zu Google Drive weiter. Falls dort noch keine aktive Session besteht, wird der Nutzer von Google aufgefordert, sich wie üblich zu authentifizieren.

  • Nach dem Login bzw. dem ersten Zugriff wird Google darauf hinweisen, dass und in welchem Umfang eine PhotoPrint-App Zugriff auf bestimmte Daten benötigt. Der Nutzer kann dies ablehnen oder seine Zustimmung erteilen (User Consent). Der Delegation Process holt also den User Consent ein.

  • Die PhotoPrint-App kann nun im Namen des Nutzers handeln und auf geschützte Inhalte zugreifen. Nach dem User Consent wird der Nutzer zurück zur PhotoPrint-App geleitet und kann dort die zu bearbeitenden Fotos aus Google Drive auswählen.

Begriffe:

  • Resource Owner: der Nutzer

  • Client: die Applikation (im Beispiel oben die PhotoPrint-App), die Zugriff auf Daten des Resource Owners benötigt

  • Resource Server: API/Service, den der Client im Namen des Resource Owners verwenden möchte (im Beipsiel Google Drive)

  • Autorization Server: Verifiziert die Identität des Resource Owners (im Beispiel Google). keycloak ist ebenfalls ein Authorization Server.

In der Realität muss vorher eine Trust Relationship zwischen den Diensten erstellt werden, bei der folgende Informationen benötigt werden:

  • Der Client benötigt Zugang zum Authorization Server. Dafür werden Zugangsdaten zum Authorization Server (Client-ID, Client secret) plus Redirect URI zum Austausch von Informationen zwischen Authorization Server und dem Client konfiguriert.

  • OAuth Scopes: Liste an Funktionen, die der Client nutzen möchte (z.B. Read Pictures, Delete Pictures, Read Profile etc.)

Der „Authorization Code“-Flow technisch:

  • Beim „Request Access“ des Clients wird der Resource Owner an einen Authorization Server umgeleitet. Der Request des Clients sieht dafür ungefähr so aus:

    https://authorize.google.com
        ?response_type=code                           # Typ des OAuth Flows
        &client_id=your_client_id                     # ID der PhotoPrint-App
        &redirect_uri=https://photoprint.app/callback # nach Authorization hierhin zurück
        &scope=read                                   # angeforderte Privilegien
        &state=random_value
    
  • Der Resource Owner wird vom Authorization Server um seinen Consent gebeten.

  • Nach dem interaktiven Consent des Resource Owners sendet der Authorization Server dem Client einen Authorization (Authz)-Code an die Redirect URL. Der Authz-Code hat eine begrenzte Lebensdauer von beispielsweise 10 Sekunden.

  • Der Client wird nun mit dem Authz-Code beim Authorization Server um einen Access Token bitten. Dieser Backchannel Request ist für den Resource Owner nicht sichtbar und sieht ungefähr wie folgt aus:

    POST /token НTTP/1.1
    Host: accounts.google.com
    Content-Type: application/x-www-form-urlencode
    
    grant_type=authorization_code
    &code=YOUR_AUTHZ_CODE
    &client_id=YOUR_CLIENT_ID               # aus dem Setup
    &client_secret=YOUR_CLIENT_SECRET       # aus dem Setup
    &redirect_uri=YOUR_REDIRECT_URI
    

    Bemerkung

    YOUR_AUTHZ_CODE, YOUR_CLIENT_ID und YOUR_CLIENT_SECRET müssen fix im Client hinterlegt sein (konfigurierbar oder im Source Code).

  • Mit dem vom Authorization Server ausgestellten Access Token kann der Client nun den Resource Server kontaktieren. Für den Client können Access Tokens irgendetwas beliebiges sein - wichtig ist dieser nur für den Resource Server, und wie dieser ermittelt, ob das Token gültig ist.

Tokens

Access Tokens
  • Typ 1: Reference Token - typischwerweise eine UID.

    • Wird vom Client mit dem (GET-)Request an den Resource Server gesendet. Der Resource Server muss das Reference Token an den Authorization Server senden, um es prüfen zu lassen und eine Liste der Scopes (Claims) abzufragen:

      POST /auth/realms/test/protocol/openid-connect/token/introspect HTTP/1.1
      Host: authorize.google.com
      
      token=664a2c74-4dd3-4116-9590-aa59ea710553
      &token_type_hint=access_token
      
    • Der Authorization Server antwortet mit der Liste der Scopes:

      {
          "exp" : 1632018803,
          "nbf": 1632015203,
          "sub": "123456",
          "client_id": "example-client",
          "scope": "read write",      # Liste an Scopes oder Roles, die dem Client zugewiesen wurden
          "jti": "1421b397-5f85-417a-9fd1-47055c47484a"
      }
      
    • Damit kann der Resource Server anschliessend eine Zugriffskontrolle durchführen.

    • Um ein Reference Token zu revoken, genügt es, wenn der Authorization Server dieses löscht, da dieses nur eine Referenz auf die aktuelle Tokendaten beinhaltet.

  • Typ 2: Self-contained Token. Anders als ein Reference Token enthalten sie alle benötigten Daten selbst, daher der Name. Dafür werden die Daten vom Authorization Server anhand der JWS-Spezifikation JSON-serialized encodiert und mit dessen Private Key signiert, womit ein „JWT“ (JSON Web Token) entsteht. Mit diesem Token kann der Resource Server daher direkt und ohne weiteren Request an den Authorization Server eine Zugriffskontrolle durchführen. Self-contained Token werden auf dem Client, also ausserhalb der Kontrolle der Authorization Server, gespeichert. JWT bestehen aus drei base64-encodierten JSON-Teilen, die durch einen Punkt voneinander getrennt sind:

      1. Header: Enthält den Typ des Tokens (z.B. „jwt“) und den verwendeten Signing-Algorithmus (z.B. „hs256“).

      1. Payload: Enthält die Claims. Claims sind Angaben über Entititäten, z.B. über den Nutzer und Metadaten wie Issuer, Subject, Audience usw.

      1. Signatur: Damit lässt sich die Datenintegrität sowie der Absender (der Authorization Server) anhand seines Public Keys verifizieren. In die Signaturerstellung fliesst der encodierte Header, der encodierte Payload und ein Secret ein.

Reference Token vs. Self-contained Token - was wird wann verwendet?

  • Reference Token: Wenn die Tokens klein sein sollen, die enthaltene Information unabhängig vom Resource Server geschützt verwaltet werden soll, und wenn Revoking wichtig ist. Generieren dafür Last auf dem Authorization Server.

  • Self-contained: Wenn der Resource Server schnell entscheiden können soll, ob Zugriff erlaubt sein soll. Dafür verliert man die Kontrolle über das Token. Werden in der Regel aber bevorzugt, da JWT leichter zu implementieren ist und besser skaliert.

Refresh Tokens

In Kürze: F5 + Refresh Token = neues Access Token. Vom Client verwendetes Token, um ein neues Access Token zu erhalten, nachdem das originale Access Token abgelaufen ist. Damit muss der Nutzer nicht jedesmal neu authentifiziert werden. Ein Refresh Token hat eine längere Laufzeit als ein Access Token.

OpenID Connect (OIDC)

OAuth wird für die Autorisierung und den delegierten Zugriff verwendet, wobei ein Nutzer einen Dienst autorisiert, in seinem Namen zu handeln. OAuth kümmert sich also um Berechtigungen und erteilt dem Client einen Zugriffsschlüssel.

OIDC basiert auf OAuth 2.0, erlaubt aber zusätzlich den Zugriff auf die Identitätsinformationen des Nutzers. Statt eines einzelnen Schlüssels stellt OIDC dem Client also eine Art „Badge“ aus, der nicht nur den Zugriffsschlüssel enthält, sondern auch Auskunft darüber gibt, wer der Nutzer ist. Sobald ein Authorization Server OIDC unterstützt, spricht man auch von einem Identity Provider (IdP).

OIDC ist damit ein vollwertiges Authentifizierungs- und Autorisierungsprotokoll.

Damit ein „OpenID Connect“-Exchange stattfindet, wird der Scope im Request erweitert:

https://authorize.google.com
    ?response_type=code
    &client_id=your_client_id
    &redirect_uri=https://photoprint.app/callback
    &scope=read+openid                            # mit OpenID
    &state=random_value

Fordert der Client später beim Authorization Server mit dem Authz-Code ein Access Token an, erält er zusätzlich dazu ein Identity Token (ebenfalls ein JWT).

ID-Tokena enthalten im Payload unter anderem folgende Claims:

  • User-ID

  • Name

  • Login Time

  • Token Expiration

ID-Tokens können zusätzliche Nutzerdaten vom Authorization Server liefern, indem der Scope erweitert wird, z.B. scope=read+openid+email.

SAML 2.0

SAML 2.0 ist ähnlich wie OIDC, jedoch viel älter (2002). Es hat seine Wurzeln in SOAP und der Fülle an WS-Spezifikationen, so dass es tendenziell ausführlicher ist als OIDC. SAML 2.0 ist in erster Linie ein Authentifizierungsprotokoll, bei dem XML-Dokumente zwischen dem Authorization Server und dem Client ausgetauscht werden. Signaturen und Verschlüsselung werden verwendet, um Requests und deren Antworten zu prüfen.

SAML kommt hauptsächlich für Browseranwendungen und REST-Aufrufe zum Einsatz:

  1. Ein Client fordert den Authorization Server auf, einen Nutzer zu authentifizieren. Nach einer erfolgreichen Anmeldung erhält der Client ein XML-Dokument mit einer SAML-Assertion, die verschiedene Attribute über den Nutzer enthält. Dieses XML-Dokument ist vom Realm digital signiert und enthält Zugriffsinformationen (z. B. Rolle des Nutzers), anhand derer der Client bestimmen kann, auf welche Ressourcen der Nutzer zugreifen darf.

  2. Ein Client wünscht Zugriff auf Remotedienste und fordert den Authorization Server auf, eine SAML-Assertion auszustellen, mit der der Client im Namen des Nutzers andere Remotedienste aufrufen kann.

OpenID Connect vs. SAML

  • Keycloak empfiehlt die Verwendung von OIDC.

  • OIDC ist moderner als SAML, SAML dagegen ist ausführlicher als OIDC und bietet mehr Funktionen.

  • OIDC ist für das Web entwickelt worden und eignet sich besser für moderne HTML5 / JavaScript-Clients, da es auf der Anwendungsseite einfacher zu implementieren ist. Da Token im JSON-Format vorliegen, können sie leichter automatisiert verwendet werden. SAMLs Webfähigkeit wurde nachgerüstet.

Built on 2025-01-06