Die sichere Verwendung des OIDC-Autorisierungscode-Flows bei öffentlichen Clients mit Einzelseitenanwendungen

11.10.2018
-Minuten Lesezeit
Managing Director, Iya CyberSecurity Solutions

Einführung


Wenn OAuth2 oder OpenID Connect (OIDC) mit Single Page Applications (Einzelseitenanwendungen, SPAs) laufen sollten, wurde traditionell die implizite Oauth2-Gewährung bzw. der implizite OIDC-Flow verwendet, und viele Entwickler halten es auch weiterhin so. Seit kurzem sieht man aber bei öffentlichen Clients immer öfter die Verwendung des OAuth2-Gewährungsflows für Autorisierungscode (oder des OIDC Autorisierungscode-Flows). Externe Identitätsanbieter (IdP) und Blogger haben sich auf unterschiedliche Weise über die Verwendung des OIDC-Autorisierungscode-Flows bei öffentlichen Clients für SPAs geäußert, aber mit den richtigen Sicherheitsvorkehrungen ist dieser Ansatz praktikabel und birgt mehrere Vorteile, wie unter anderem folgende:

 

  • Verwendung von Aktualisierungstoken. (Nicht zu unterschätzen.)

  • Mehr Kontrolle über die Ablaufzeit der Benutzersitzung mithilfe von spezifizierten Mechanismen.

  • Konsistenz über verschiedene Anwendungsfälle hinweg (SPAs, native mobile Anwendungen, native Desktop-Anwendungen, Webanwendungen usw.).

Ich bin in früheren Blog-Beiträgen wesentlich ausführlicher auf diese Vorteile eingegangen. Der absehbare Trend in der Branche geht bei öffentlichen Clients stärker in Richtung einer Verwendung des OAuth2-Gewährungsflows für Autorisierungscode (oder des OIDC-Autorisierungscode-Flows). Dieser Blog-Beitrag befasst sich damit, wie man dafür sorgt, dass dieser Ansatz bei SPAs auf sichere Art und Weise verwendet wird

Die Architektur eines OIDC-Autorisierungscode-Flows (bei öffentlichen Clients)

Um sicherzustellen, dass wir alle das Gleiche meinen, gehe ich hier von einer Architektur und einer Interaktion aus, die mit dem folgenden Diagramm beschrieben werden kann.

 

 

Zudem möchte ich diese Annahmen ausformulieren (einige, aber wahrscheinlich nicht alle, werden für Ihren Anwendungsfall zutreffen):

 

  • Verwendung eines zustandslosen Sicherheitsmodells anstelle eines Cookies zur Sitzungsverfolgung mit dem Anwendungs-Backend (API Gateway, in der Abbildung oben). Bei diesem zustandslosen Sicherheitsmodell wird der Sicherheitskontext bei jedem API-Aufruf im Backend neu erstellt, wobei entweder die Informationen im Zugriffstoken verwendet werden (JSON Web Token angenommen: JWT) oder es werden Daten vom OIDC UserInfo-Endpunkt abgerufen. Weitere Informationen zu diesem Thema finden Sie unter „How To Submit Your Security Tokens to an API Provider Pt. 1“ (dt.: Übermitteln Ihrer Sicherheitstoken an einen API-Anbieter Teil 1).

     

  • Die Ablaufzeit des Zugriffstokens ist kürzer als die Ablaufzeit der Benutzersitzung. Daher wird ein Aktualisierungstoken benötigt. Mit seiner Hilfe wird die Lebensdauer von Token verlängert und eine angemessene Sitzungsdauer erreicht. Es gibt verschiedene Methoden zum Aktualisieren von Token. Ein Aktualisierungstoken für die „Offline-Nutzung“, das die Benutzerauthentifizierung überdauern soll, eignet sich nicht für SPAs. Stattdessen wird die Aktualisierung fehlschlagen, sobald der Benutzer zur Interaktion mit dem IdP zurückkehren muss (z. B. für eine erneute Authentifizierung). Die Lebensdauer des Tokens ist zwar nicht festgelegt, es lässt aber keine Aktualisierung zu, wenn die Geschäftsintelligenz auf eine erneute Feststellung des Benutzers besteht. Die Geschäftslogik und die Daten hinter einem Aktualisierungstoken sind für niemanden ersichtlich, außer für den IdP; die Interaktion mit dem IdP wird größtenteils von einer Authentifizierungs-Bibliothek abgewickelt, es sei denn, es ist eine Benutzerinteraktion (z. B. die Angabe von Anmeldedaten) erforderlich.

     

  • Es ist die SPA, die als OAuth2-Client agiert, und keine serverseitige Komponente. Der OAuth2-Client ruft die Token vom Token-Endpunkt ab. In unserem SPA-Szenario ist der OAuth2-Client der im Browser laufende Javascript-Code (die SPA) und nicht eine serverseitige Komponente.

     

  • Der Static Asset Server antwortet auf die registrierte Umleitungs-URI mit index.html (oder gleichwertig). Auf diese Weise wird die SPA neu geladen und initialisiert, und beispielsweise der Angular Router wird erkennen, dass die Umleitungs-URI gerade aufgerufen wurde (und entsprechende Schritte unternehmen, um den OIDC-Flow abzuschließen).

     

  • Dieser Beitrag befasst sich nicht mit dem Leistungsumfang einzelner Identitätsanbieter. Auf diese Weise sind diese Informationen für ein möglichst breites Publikum nützlich und wir können unsere Aufmerksamkeit auf die Leistungsmerkmale konzentrieren, die in den Spezifikationen vorgegeben sind.


Hinweis: Dieser Blog-Beitrag geht nicht näher auf die Interaktion zwischen der SPA und dem API-Gateway ein. Wenn Sie an diesem Thema interessiert sind, erhalten Sie Aufschluss in den bereits zurückliegenden Beiträgen „How To Submit Your Security Tokens to an API Provider Pt. 1“ und „How To Submit Your Security Tokens to an API Provider Pt. 2“ (dt.: Übermitteln Ihrer Sicherheitstoken an einen API-Anbieter Teil 1 und Teil 2)”.

Sicherheitsimplikationen

An diesem Punkt lege ich den Schwerpunkt der Betrachtung auf die Spezifikationen. Das bedeutet, dass ich die Frage stelle: "Wie können wir X innerhalb der Grenzen der relevanten Spezifikationen A, B, C usw. lösen?" Die meisten Identitätsanbieter (IdP) stellen neben einigen nützlichen (aber zumeist proprietären) Funktionen auch Kontrollmechanismen für die Dauer authentifizierter Benutzersitzungen und den Erhalt neuer Token zur Verfügung, ohne dass der Benutzer dazu aufgefordert wird, sich über eine mit einem Cookie verfolgte Sicherheitssitzung erneut zu authentifizieren.

 

Was bedeutet dies für die Sicherheit? Die Spezifikationen für OAuth2, OIDC und JWT (und unterstützende) sehen komplementäre Kontrollmechanismen vor, um die Integrität eines OIDC-Anmeldevorgangs zu gewährleisten, wie unter anderem folgende:

 

  1. Das Transport Layer Security TLS/SSL-Serverzertifikat des Identitätsanbieters (IdP) wird vom Browser überprüft, um sicherzustellen, dass der Browser mit dem echten IdP kommuniziert.

     

  2. Die (von der SPA verwendete) Authentifizierungs-Bibliothek validiert das ID-Token (Validierung der digitalen Signatur und Vertrauensvalidierung des Ausstellerzertifikats) gemäß den JWT- und OIDC-Spezifikationen. Verwenden Sie den OIDC-Discovery-Endpunkt und den JWKS-Endpunkt, um den Truststore für die Validierung des JWS-Ausstellerzertifikats zu erhalten und dynamisch zu aktualisieren. Dies wird von den meisten Javascript-Authentifizierungs-Bibliotheken (in Browsern), die ich bisher verwendet habe, nicht übernommen. Anhand dieser Überprüfung kann man mit höherer Sicherheit von der korrekten Kenntnis der tatsächlichen Herkunft des Tokens ausgehen.

     

  3. Verwenden einer vorab registrierten URL-Weiterleitung. Auf diese Weise wird sichergestellt, dass nur der/die vorgesehene(n) Anwendungsendpunkt(e) Zugriff auf die Token erhalten.

     

  4. Das TLS/SSL-Zertifikat des Webservers für statische Inhalte (der die SPA-Assets hostet) wird vom Browser überprüft, damit sichergestellt wird, dass der Browser tatsächlich mit der echten Umleitungs-URI (und Anwendung) kommuniziert. Im nächsten Schritt (der den Rahmen dieses Blog-Beitrags sprengen würde) könnte man TLS bei jedem Netzwerk-Hop verwenden, bei dem Sicherheitstoken weitergegeben werden.

     

  5. Das Verwenden des Statusparameters (und seine Validierung bei Erhalt des Autorisierungscodes) für den Autorisierungsendpunkt, den Authentifizierungs-Workflow, die delegierte Einwilligung für den Zugriff und alle weiteren beteiligten Umleitungsendpunkte.

     

  6. Die OAuth2-Spezifikation gibt vor, dass der Autorisierungsendpunkt des IdP, Authentifizierungs-Workflow und die Einwilligungsdialoge für den delegierten Zugriff entsprechende CSRF-Schutzstrategien verwenden. Es ist in der Tat eine gute Idee, diese generell für jeden Endpunkt zu verwenden.

     

  7. Der Benutzer wird aufgefordert, der Anwendung (SPA) seine Einwilligung für den Zugriff auf seine Daten (Profil auf dem Autorisierungsserver, IdP) zu erteilen (zu delegieren). Normalerweise geschieht dies nur bei der ersten Anmeldung eines Benutzers. Zur Steigerung der Sicherheit könnte man auch bei jedem Anmeldevorgang so vorgehen. Auf diese Weise wird außerdem sichergestellt, dass der Benutzer auch wirklich wie geplant auf die Anwendung zugreift. Nicht jeder OAuth2-Autorisierungsserver unterstützt das.

     

  8. Obwohl dies nicht ausdrücklich in den Spezifikationen definiert ist, kann durch die Verwendung von Cross-Origin Ressource Sharing (CORS) am Token-Endpunkt durch einen Mechanismus, der dem beschriebenen Client gültige Ursprünge zuordnet, eine zusätzliche Sicherheitsebene geschaffen werden. Dadurch wird verhindert, dass sich eine andere, nachahmende Anwendung (die von einem nicht registrierten Ursprung geladen wurde) Zugriff auf eine Reihe von Token verschaffen kann. Es gibt jedoch Methoden, um die CORS-Beschränkungen zu umgehen. Daher ist es nicht besonders hilfreich, sich darauf zu verlassen. Hinweis: Andere IdP-Endpunkte, die Sie für Ihren Anwendungsfall benötigen, können CORS unterstützen oder auch nicht.

     

  9. Dies ist zwar auch nicht in den Spezifikationen definiert, aber Sie sollten die ID-Token, Zugriffstoken und (vor allem) die Aktualisierungstoken im Sitzungsspeicher ablegen, damit sie nur so lange verfügbar bleiben, bis der Browser geschlossen wird. Dies ist ein weiteres Thema, das im Internet viel diskutiert wurde. Leider gibt es nur wenige Optionen für die Speicherung im Browser.

Dies sollten Sie beachten

Nachdem wir nun einige der Sicherheitsimplikationen bei der Verwendung des OIDC-Autorisierungscode-Flows (bei öffentlichen Clients) für eine SPA betrachtet haben, folgen nun ein paar Punkte, die Sie im Auge behalten sollten, damit Ihr System optimal geschützt bleibt:

 

  • Nicht jeder IdP unterstützt den OIDC-Autorisierungscode-Flow bei öffentlichen Clients. Wenn Ihr IdP dies nicht anbietet, sind Sie auf einen IdP-spezifischen Mechanismus (z. B. ein Cookie zur Sitzungsverfolgung) angewiesen, um ohne das erneute Abfragen der Benutzeranmeldedaten ein neues Zugriffstoken zu erhalten. Dieses Vorgehen ist zwar bekannt, aber nicht durch eine Spezifikation abgedeckt.

     

  • Manche IdPs erlauben kein CORS auf dem Token-Endpunkt. Dadurch wird verhindert, dass der Browser die Antwort des Token-Endpunkts auslesen kann. Demnach wird eine SPA mit einem OIDC-Autorisierungscode-Flow und einem öffentlichen Client nicht unterstützt. Die Verwendung eines Reverse-Proxys (falls diese Option rechtlich und technisch möglich ist), kann alle CORS-Probleme mit dem Token-Endpunkt lösen. Alternativ dazu wäre die implizite Gewährung (oder der implizite Flow) der am besten geeignete Ansatz.

     

  • Szenarien mit einer verhältnismäßig kurzen Ablaufzeit für Benutzer könnten den impliziten OIDC-Flow verwenden. Wenn die gesamte Sitzungszeit des Benutzers relativ kurz bleibt und das Zugriffstoken nie abläuft, ist kein Aktualisierungstoken erforderlich. Die Verwendung des impliziten Flows ist also eine vereinfachte Option.

     

  • In manchen Fällen sind möglicherweise OAuth2-Gewährungen vorteilhafter als OIDC-Flows und umgekehrt. In meinem Beitrag dazu gehe ich ausführlich darauf ein, wann die verschiedenen OAuth2-Gewährungen und OIDC-Flows verwendet werden sollten.

     

  • Selbst wenn die SPA (oder eine andere beliebige Javascript-Anwendung, die in einem Browser läuft) eine Client-ID und ein Client-Geheimnis hat, die im Javascript-Code kodiert sind, kann dem Client-Geheimnis als Form der Authentifizierung für den Client nicht vertraut werden. Es wäre ein Kinderspiel für einen Dritten, das Client-Geheimnis zu erfahren. Dieser Ansatz ist für sich gesehen nicht unsicher, aber der IdP muss berücksichtigen, dass dies nicht mehr Sicherheit bietet, als ein öffentlicher Client ohne ein Geheimnis innerhalb seiner Sicherheitsmodelle. Wie bereits erwähnt, verhindert die redirect_uri-Whitelist, dass Anwendungen, die den Browser nicht umgehen, eine client_id wiederverwenden können.

     

  • Geben Sie das ID-Token oder Aktualisierungstoken nicht an andere Komponenten Ihrer Architektur oder an Dritte weiter. Wenn die SPA als OAuth2-Client (OIDC Relying Party) fungiert, sollte sie diese Token auf keinen Fall an eine serverseitige Komponente weitergeben. Wenn Ihre Architektur dies vorschreibt, kann die serverseitige Komponente als OAuth2-Client fungieren und als vertraulicher Client ein Client-Geheimnis sicher bewahren. In dem Fall sollte die SPA ein Cookie verwenden, damit die Sicherheitssitzung mit dem Webserver verfolgt werden kann. Die gemeinsame Nutzung des Aktualisierungstokens mit einer anderen Komponente des Systems gefährdet die Sicherheitsbeziehung zwischen dem OAuth2-Client (SPA) und dem IdP.  Eine gemeinsame Nutzung eines id_token gefährdet nicht die Sicherheit zwischen dem IdP und dem Client, sondern die Sicherheit anderer Komponenten, die sich darauf verlassen (da es sich um eine Assertion handelt, die nur für diesen Client bestimmt ist). Sie möchten nicht, dass eines dieser Szenarien eintritt.

     

  • Proof Key for Code Exchange (PKCE) ist für die Verwendung mit nativen Anwendungen gedacht. Es bietet keine zusätzliche Sicherheit für eine SPA (oder Javascript-Anwendung), die in einem Browser läuft. Es kann jedoch ratsam sein, PKCE mit SPAs zu verwenden, damit ein einheitlicher Satz von OAuth2/OIDC-Verwendungsregeln beibehalten wird.

     

  • Bei der dynamischen Clientregistrierung (RFC 7591) gibt es einige Vorbehalte. Die dynamische Clientregistrierung (DCR) kann eine zusätzliche Schutzschicht für eine Instanz einer SPA-Anwendung hinzufügen, aber das dynamisch an eine Instanz der SPA ausgegebene Client-Geheimnis ist eine weitere Information, die neben dem OIDC-ID-Token, dem OAuth2-Zugriffstoken und dem OAuth2-Aktualisierungstoken geschützt werden muss. Die DCR kann das Problem mit dem Schutz dieser Werte im Browser nicht lösen. Ihr IdP sollte auch in der Lage sein, für viele OAuth2-Clients zu skalieren (einen pro Browser, Benutzer) – stellen Sie sich Ihre Anwendung in dieser Art von Szenario mit Millionen von Benutzern vor. Die DCR könnte auch einen wirksamen Mechanismus zur Erkennung von Mustern bei der Nutzung von Anwendungen bieten, der es einem IdP ermöglichen würde, die rechtmäßige Nutzung besser zu validieren, der aber von der Anwendung abstrahiert ist.

 

Bedenken Sie, dass als Voraussetzung für all dies der Browser und das zugrundeliegende Betriebssystem/Gerät nicht kompromittiert sein dürfen. Im Falle einer Kompromittierung wäre das meiste, was ich hier erwähnt habe, von geringer Bedeutung.

Zusammenfassung

Früher wurde in der Branche bei SPAs die implizite OAuth2-Gewährung (oder der implizite OIDC-Flow) verwendet. Es gibt keine Sicherheitsbestimmungen, die eine weitere Verwendung vorschreiben. In Zukunft sollte der OAuth2-Gewährungsflow für Autorisierungscode (oder OIDC-Autorisierungscode-Flow) mit SPAs verwendet werden.

 

Weitere Informationen und Erläuterungen zu Themen dieser Art finden Sie in meinem Blog on API Management, Integration, and Identity (dt.: Blog über API-Management, Integration und Identität) auf medium.com.  

Diesen Artikel teilen:
Verwandte Ressourcen

Starten Sie jetzt

Kontaktieren Sie uns

sales@pingidentity.com

Erfahren Sie, wie Ping Ihnen helfen kann, sichere Erlebnisse für Mitarbeiter, Partner und Kunden in einer sich schnell wandelnden digitalen Welt zu bieten.