Shownotes & Links
OAuth 1.0
- Die OAuth 1.0 Spec: RFC5849
- OAuth and the Road to Hell – nur noch über die Wayback Machine verfügbar
- Die OAuth 2.0 Homepage
OAuth 2.0
- OAuth 2.0 Core Spec: RFC 6749
- Bearer Token Usage: RfC 6750
- Token Introspection: RFC 7662
- Discovery: RFC 8414
- OAuth 2.0 Threat Model und Security Best Practice
OAuth 2.1
Software
Feedback
Falls ihr Fragen oder Anregungen habt, schreibt uns gerne eine E-Mail an [email protected]
.
Transkript
Christoph Iserlohn Hallo und herzlich Willkommen zur siebten Ausgabe des INNOQ Security Podcast. Beim letzten Mal haben wir die feinen Unterschiede zwischen Autorisierung und Authentisierung und Authentifizierung besprochen. Heute wollen wir mal ein bisschen mehr in die Praxis einsteigen und deshalb werden wir über OAuth sprechen. Und dazu habe ich mir den Stefan eingeladen. Hallo Stefan!
Stefan Bodewig Hallo Christoph!
Christoph Iserlohn Und ich habe den Simon eingeladen. Hallo Simon!
Simon Kölsch Hallo Christoph! Hallo Stefan!
Christoph Iserlohn So, wir haben ja gesagt, es gibt Unterschiede zwischen Autorisierung, Authentifizierung und Authentisierung. Und OAuth lässt das jetzt schön offen, weil es bei Auth einfach aufhört, worum es da geht. Vielleicht könnt ihr beiden doch mal kurz sagen: Worum handelt es sich denn dabei?
Simon Kölsch Also ich würde ja an der Stelle mal ganz massiv widersprechen, die lassen das natürlich nicht offen. Also der verkürzte Name von der Spec vielleicht. Aber das kann man nochmal ganz klar machen, steht auch im ersten Satz von der Spezifikation drin: OAuth zum Delegieren von Third-Party-Autorisierung. Das heißt, immer dann, wenn wir sowas wie einen Login haben, reden wir wahrscheinlich nicht von OAuth, sondern immer dann, wenn wir eine dritte Partei haben, die Zugriff auf irgendetwas bestimmtes von einem Benutzer oder ähnliches haben möchte, dann würden wir OAuth benutzen, um diesen Zugriff zu delegieren an der Stelle.
Stefan Bodewig Genau, also insofern geht es um einen Spezialfall von Autorisierung eigentlich nur. Das ist kein generisches Autorisierungsprotokoll, Framework, was auch immer, sondern es geht tatsächlich im Kern um die Delegation von Berechtigungen.
Christoph Iserlohn Ja, wenn es um Delegation von Berechtigungen geht, dann haben wir es wahrscheinlich dann mit einem verteilten System zu tun, also es sind mehrere Parteien beteiligt und welches Problem soll denn damit gelöst werden dann, dass man dafür ein spezielles Protokoll haben will?
Stefan Bodewig Das Standardbeispiel, das glaube ich auch in der Spec drinsteht als das Beispiel, ist die Vorstellung: Es gibt Leute, die haben Bilder bei einem Fotoservice abgelegt und sie möchten einen anderen Dienstleister, der Fotos drucken kann, Zugriff auf ihre Fotos geben ohne dass sie die Fotos zu ihm rüberschicken müssen und ohne dass sie ihr Passwort für den Fotoservice dem Druckerdienstleister, dem Druckdienstleiser mitteilen müssen. Also das ist dann ein Rahmenwerk, um zu sagen, da gibt es diesen Druckdienstleister und dem möchte ich erlauben meine Fotos zu sehen. Meine Fotos, auch nicht alle vielleicht, sondern ganz bestimmte Fotos und die soll er für mich drucken dürfen. Ohne dass der Druckdienstleister erfährt mit welchen Credentials ich mich bei dem Fotodienstleister angemeldet habe. Also das ist…
Simon Kölsch Ein anderes Beispiel was man da vielleicht ergänzen könnte, ist sowas wie eine App, die lustige Statistiken über mein Twitter Verhalten irgendwie erstellt und am Ende so eine Zusammenfassung auch noch in meiner Timeline posten möchte. Die brauch ja irgendwie Zugriff auf meine Daten, wenn die nicht öffentlich verfügbar sind und dann möchte ich so einer App natürlich nicht meine Account-Zugangsdaten irgendwie mitteilen, sondern möchte die halt berechtigen für einen bestimmten Zeitraum auf bestimmte Daten meines Profils oder ähnliches zugreifen zu können oder vielleicht bestimmte Rechte zu geben, nämlich genau einmal oder mehrmals, auch wieder für einen bestimmten Zeitraum, in meiner Timeline zu posten. Und da möchte ich eben nicht mein Passwort hinterlegen, sondern möchte das irgendwie deutlich machen, dass das halt eben nochmal spezielle Berechtigungen sind, die ich hier erlaube, dieser Third Party und sowas könnte man dann eben mit OAuth realisieren.
Christoph Iserlohn Also der wichtigste Teil scheint mir dann zu sein, dass ich dann sozusagen einer dritten Partei Zugriff gewähren kann, ohne dass ich der dritten Partei meine Credentials mitteilen muss. Kann man das so zusammenfassen, dass das das ist was OAuth lösen will, dieses Problem?
Simon Kölsch Ja, würde ich schon sagen. Zumindest auch historisch aus der Ecke kommt das, ja.
Christoph Iserlohn Ja. Du erwähnst gerade historisch. Was wir jetzt so ein bisschen unterschlagen haben, dass es OAuth ja sozusagen in zwei Varianten gibt. OAuth 1.0 und 2.0, wahrscheinlich werden wir heute mehr über 2.0 sprechen, aber vielleicht können wir nochmal kurz drauf eingehen, wo denn die Unterschiede dazu sind? Oder wie es dazu gekommen ist, dass wir das jetzt haben? Und ob das vielleicht auch kompatibel ist oder nicht?
Simon Kölsch Ja, OAuth 1.0, kann man sagen, hat genau diesen Lösungsansatz nämlich gehabt. Die Idee, dass man sein Passwort für Account oder sowas woanders irgendwie hinterlegen muss, ist ja eigentlich aus Security-Perspektive eine superschlechte. Das wird gar nicht transparent, dass da gar nicht ein anderer User gerade auf den Account zugreift, sondern dass das halt eben ein Stück Software ist oder ein Dienstleister oder wer auch immer. Und das möchten wir natürlich anders behandeln als einen normalen Benutzer, der auf ein System zugreift. Einfaches Beispiel dazu: Wir wollen die Rechte irgendwie einschränken. So eine Third Party sollte zum Beispiel nicht mein Passwort ändern können. Wenn ich das irgendwie technisch nicht vorsehe, dann kann ich ja nicht verhindern, dass so eine Third Party App sich bei mir einloggt und plötzlich mein Passwort ändert. Und da so ein bisschen aus der Historie herausgetrieben hat sich quasi OAuth 1.0 entwickelt. Ich kenne das genaue Umfeld da gar nicht wie das entstanden ist, aber Spec-Autor ist der Eran Hammer-Lahav, ich muss zugeben ich weiß gar nicht wie man den Doppelnamen am Ende ausspricht. Das war der Haupt-Spec-Autor von OAuth 1.0 und was OAuth 1.0 letztendlich war, war ein Verfahren, um genau diesen Zugriff zu delegieren mit einem Scope nur für klassische Webanwendungen. Das heißt, wir haben da eine Art Back-End, also einen Service dahinter, der sich im Vorfeld auch schonmal bei dem Dienst registrieren kann. Der dann auch ein Secret und Credentials halten kann und dann konnte der, wenn der Benutzer dem Zugriff auf diese Daten zugestimmt hat, bei einem Resource Server dann auf diese Daten zugreifen. Und hat dafür dann einen Token bekommen, dass er das nochmal signiert hat und konnte dann diese API-Funktionalität an der Stelle nutzen. Das war verkürzt quasi OAuth 1.0 und jetzt ist natürlich die Frage: Warum sind wir heute bei OAuth 2.0? Also OAuth 1.0 ist inzwischen ein Stück weit als obsolet markiert, zumindest von den OAuth 2.0- Spec-Autoren auch. Da hat man einfach gesagt: Wir möchten den Scope größer machen, wir möchten da mehr Use Cases irgendwie mitabdecken können. Was ist denn eigentlich mit so einer nativen Applikation? Was ist mit einer irgendwie Desktop-Applikation? Alles so Fälle, wo ich vielleicht gar keinen Back-End irgendwie im Hintergrund habe, sondern mein Client für sich alleine so auf diese API zugreift. Das waren alles Dinge, die sind bei OAuth 1.0 nicht abgedeckt, plus wir haben relativ komplexe Signatur Algorithmen da noch drin, also damit ist gemeint: Ich muss dann als Entwickler diese Tokens nochmal selbst signieren und entsprechend encodieren. Das macht das ein bisschen komplizierter und um das alles irgendwie abzudecken haben sich dann eine ganze Reihe an größere Firmen zusammengesetzt, wurde da so ein OAuth 2.0 Konsortium gebildet und die haben dann über die nächsten Jahre quasi OAuth 2.0 entwickelt und spezifiziert. Und man kann eigentlich sagen OAuth 1.0 sollte keine Rolle mehr spielen, zumal sich irgendwie alle Use Cases von OAuth 1.0 auch mit OAuth 2.0 abdecken lassen. Von daher ist OAuth 1.0 tatsächlich obsolet.
Christoph Iserlohn Also das heißt im Weiteren, auch wenn wir dann OAuth sagen, werden wir immer von OAuth 2.0 sprechen, es sei denn wir werden es explizit erwähnen, dass es OAuth 1.0 betrifft. Jetzt war dieser Übergang nicht ganz ohne Konflikte, wie ich gehört habe. Könnt ihr dazu nochmal kurz etwas sagen?
Stefan Bodewig Na gut, der von Simon schon erwähnte Eran hat irgendwann zwischendrin gemeint, dass er während er eigentlich immer noch derjenige war, der die Spezifikation von OAuth 2.0 federführt als Editor vorangetrieben hat, dass die Spezifikation in Richtungen getrieben wurde, mit denen er nicht einverstanden war. Aus seiner Sicht sei OAuth 2.0 inhärent unsicherer als OAuth 1.0. In OAuth 1.0, wenn ich es richtig verstanden habe, signiere ich jeden Request einzeln und in OAuth 2.0 sind die einzelnen Requests überhaupt nicht mehr signiert und ich verlasse mich vollständig darauf, dass ich eine Transportverschlüsselung habe und alle anderen Sicherheitsfeatures, die in OAuth 1.0 drin waren, sind in 2.0 erst einmal ein Stück weit entschärft wurden, würde ich sagen. Und der hatte so den Eindruck, das Ganze wird komplizierter eigentlich als das was wir vorher hatten und gleichzeitig unsicherer, sodass er sich dann zurückgezogen hat und das auch mit lauten Fanfaren getan hat und nicht einfach sich still und heimlich davongestohlen hat, sondern eben auch seine Kritik sehr öffentlich gemacht hat. Und das hat dann eben ein paar Wellen geschlagen.
Simon Kölsch Genau, es gab da von ihm so einen Blog Post “OAuth the road to hell” or “the long road to hell” und er hat dann auch nachträglich seinen Namen aus der Spec als Autor entfernen lassen. Das kann man durchaus mal lesen, hat glaube ich auch zum großen Teil berechtigte Kritikpunkte auch drin, muss allerdings da auch im Hinterkopf behalten, dass das ist jetzt irgendwie 9 Jahre her, seitdem hat sich auch ein bisschen was geändert. Aber ist sicherlich kein schlechter Einstieg in das Thema, vielleicht mal mit der Kritik anzufangen.
Christoph Iserlohn Ja, darüber können wir vielleicht später doch auch mal diskutieren, wie eure Meinung dazu aussieht, ob er da vielleicht an Stellen Recht hatte oder nicht. Oder was sich da getan hat inzwischen, Simon, du meintest ja, das ist jetzt schon 9 Jahr her, seitdem ist ja bestimmt auch viel passiert. Aber als erstes sollten wir vielleicht mal noch die Grundlagen klären. Wir haben jetzt festgestellt, es handelt sich um ein verteiltes System, wo das eingesetzt wird. Und in so einem verteilten System gibt es ja wahrscheinlich ganz verschiedene Akteure oder Beteiligte, die da eine Rolle spielen. Simon, du erwähntest gerade schon einen so beiläufig, den Resource Server. Vielleicht könnt ihr mal erklären, wer denn alles beteiligt ist? Also welche Rollen gibt es denn in so eine OAuth 2.0 System und was haben diese Rollen zu bedeuten?
Simon Kölsch Genau, vielleicht generell nochmal einfach zum Einstieg: Wir haben also den Benutzer, der irgendwo bei einem Service Daten liegen hat und dieser Benutzer ist…, dem gehört ja eine Ressource und ist damit der Resource Owner. Und diese Daten liegen irgendwo in einem System, zum Beispiel die hochgeladenen Bilder oder was auch immer wir hier als Beispiel benutzen wollen, die liegen auf einem Resource Server. Und bei OAuth 1.0 war das so, es wurde nicht unterschieden zwischen der Rolle nur eine Ressource zur Verfügung zu stellen und der Rolle die Autorisierung zu überprüfen. Das war vorher bei OAuth 1.0 eine Rolle, das hat man bei OAuth 2.0 auseinandergezogen. Das heißt, ich habe jetzt neben den Resource Server noch einen Authorization Server, der diese Autorisierung von der dritten Partei, die darauf zugreifen will, irgendwie überprüfen kann. Und das ist wahrscheinlich der am meisten verwirrendste Teil am Anfang: Diese dritte Partei, diese Third Party, die da auf Daten zugreifen möchte, die heißt Client. Und mit Client verbinden wir ja häufig sowas wie ein Webbrowser oder ein User Client oder sowas in der Richtung, im OAuth 2.0 Kontext ist der Client immer die dritte Partei, die gerne Zugriff auf eine Resource haben möchte, die bei einen Resource Server liegt. Der Resource Server kann das Ganze mit dem Authorization Server überprüfen und der Resource Owner hat im Vorfeld normalerweise dann Consent gegeben, dass der Zugriff soweit in Ordnung ist.
Christoph Iserlohn Also, um auf das Beispiel, das am Anfang gebracht wurde nochmal zurückzugreifen: Dem Print Service, der auf die Bilder zugreifen muss wäre dann in dem Fall, wenn wir das mal zuordnen wollen, also der Resource Owner wäre der Nutzer dieser beiden Services und der Resource Server wäre der Bilder Server, auf dem erstmal die Bilder liegen und die Ressourcen wären die Bilder selbst. Und der Client wäre aber nicht beim User angesiedelt, also nicht sein Browser oder ähnliches, sondern der Client wäre dann der Print Service, der darauf zugreifen will, um daraus vielleicht ein Fotoalbum oder ähnliches zu machen. Habe ich das so richtig verstanden?
Simon Kölsch Genau.
Christoph Iserlohn Gut. Was ich dann so beim Überfliegen der Spec auch noch gesehen habe, was oft verwendet wird und nicht nur bei der Spec, auch wenn ich ein paar Blog Posts darüber gelesen habe, kommen immer wieder auch die Worte “User Agent” und “Identity Provider” da vor. Könnt ihr da nochmal versuchen die zu erklären und abzugrenzen und welche Rolle die dabei spielen?
Stefan Bodewig User Agent kennen wir ja auch im anderen Kontext durchaus als Synonym für den Webbrowser. Also das Ding, das ich benutze, um http-Requests auszuführen. Also das ist das, was der Resource Owner verwendet, um mit dem Client zu kommunizieren, um mit dem Resource Server oder den Authorization Server zu kommunizieren. Konkret in den meisten Fällen, wenn wir über Webapplikationen reden, ist das der Browser des Benutzers. Identity Provider war das andere? Identity Provider spielt bei OAuth 2.0…, als Wort sollte es eigentlich keine große Rolle spielen, weil es gar nicht um Identitäten geht. Wir haben ausschließlich mit Autorisierung, nicht mit Authentication zu tun an der Stelle. Die Erwartung ist, dass wenn der Client nach Berechtigungen fragt, dass ich als Resource Owner mich beim Authorization Server anmelden muss, um zu sagen: Ja, der darf das jetzt. Aber niemand, weder Client noch der Resource Server, erfahren am Ende explizit, dass ich das gewesen bin und dass ich mich da gerade angemeldet habe. Insofern hat Identity mit OAuth 2.0 nicht wahnsinnig viel zu tun. Identity Provider ist somit eigentlich ein Konzept, das nicht wirklich aus meiner Sicht zu OAuth 2.0 dazugehört.
Simon Kölsch Genau, man muss da vielleicht ein bisschen einen Ausblick in die nächsten Folgen geben. Nämlich irgendwann werden wir auch mal über sowas wie Single Sign-On und OpenID Connect sprechen. Und OpenID Connect legt halt eben ein Identity Layer über OAuth 2.0 drüber und wahrscheinlich immer, wenn es um Identity Provider geht, geht es wahrscheinlich nicht um OAuth 2.0, sondern geht es wirklich um ein Login und Single Sign-On und damit OpenID Connect und da hat man dann eben Berührungen mit OAuth als Unterbau. Und oft, wenn wir uns sowas wie Keycloak zum Beispiel angucken als Identity Provider Beispiel, da kann Keycloak natürlich Single Sign-On-Protokolle, kann aber außerdem noch irgendwie Low-level Auth 2.0 für Access Delegation supporten. Und so haben wir dann häufig die gleichen Begriffe im gleichen Software Produkt, sollte aber so wie OAuth 2.0 gedacht ist keine Rolle spielen und in dem Kontext auch nicht auftauchen. Wenn es das tut, machen wir irgendetwas falsch.
Christoph Iserlohn Na, dann lassen wir den Identity Provider mal raus, aber den User Agent, den verfrachten wir jetzt nochmal in das Beispiel. Der User Agent ist dann der Browser von dem Nutzer, der diesen Print Service benutzen will, um seine Bilder auszudrucken oder ein Fotobuch zu machen oder ähnliches. Und im normalen Sprachgebrauch ist es halt oft der Client, das müssen wir aber auseinanderhalten, weil der Client dann halt der Print Service ist.
Simon Kölsch Genau.
Christoph Iserlohn Das habe ich soweit verstanden. So, jetzt haben wir die Akteure geklärt, die da eine Rolle spielen. Aber die Akteure, die müssen ja auch irgendwie zusammenarbeiten in irgendeiner Form und dabei kommt einen immer das Wort “Flow” unter. Und davon gibt es scheinbar auch verschiedene. Vielleicht könnt ihr mal sagen, was ist denn so ein Flow? Welche verschiedenen Flow gibt es denn? Und warum gibt es denn überhaupt verschiedene Flows? Und dann können wir danach vielleicht nochmal gucken, dass wir so einen Flow oder vielleicht auch zwei mal explizit erklären, wie der denn funktioniert.
Stefan Bodewig Grundsätzlich basiert OAuth auf der Idee, dass der Client vom Authorization Server einen Token erhält, das er dann dem Resource Server vorzeigt, um zu sagen: Das sind Berechtigungen, die mir zugeteilt worden sind. Und die verschiedenen Flows sind verschiedene Wege, auf denen der Client ein solches Token erhalten kann. Und wir haben eben unterschiedliche Szenarien. Der Simon hat schon gesagt, es gibt die Möglichkeit, die in OAuth 1.0. die einzige war, wir haben eine Webapplikation, die der Client ist. Aber es sollten eben auch andere Szenarien abgebildet werden, wie zum Beispiel die native Applikation oder 2012, als die Spec finalisiert worden ist, noch sehr, sehr neue Dinge, Applikationen, die komplett im Browser ablaufen. Also einen Client, der nur aus JavaScript, das im Browser läuft da ist. Also die Single Page Application würden wir heute sagen, ich bin mir gar nicht sicher, ob die 2012 schon so hießen. Und die haben eben verschiedene Möglichkeiten da ran zu gehen und deshalb gibt es eben unterschiedliche Flows für unterschiedliche Szenarien. Darüber hinaus gibt es dann eben noch spezielle Rand Use Cases, Dinge, wo ich gar nicht den Endbenutzer als solchen anmelden möchte oder Berechtigung von dem hole, sondern eher so einen technischen User anmelde, dass der Client für sich selber einen Token beschafft, nicht im Namen eines Anderen einen Token erhält.
Simon Kölsch Ein Beispiel dafür wäre zum Beispiel auch sowas wie “living room devices”, hatte das die Spec damals schon genannt. Damals habe ich mich ein bisschen gefragt, was das denn eigentlich sein soll, inzwischen haben wir halt sowas wie Alexa oder halt eben das SmartTV mit einer installierten YouTube App. Und bei so einem Fernseher habe ich üblicherweise halt eben nicht eine Tastatur und so ein Browser, die ich so direkt benutzen kann, sondern muss vielleicht nochmal andere Wege finden irgendwelche Bestätigungen von einem User einzuholen. Zum Beispiel indem ich in einer YouTube App einen QR-Code scanne, sowas ist dann auch nochmal mit entsprechenden OAuth Flows abgebildet. Einfach als Ergänzung mal.
Christoph Iserlohn Also, ich habe verstanden, es gibt verschiedene Flows und so ein Flow ist erstmal dazu da, damit ich so einen Token bekomme, um irgendwie bei einer Autorisierung nachzuweisen. Welche Flows gibt es denn jetzt aber? Welche haben wir denn in der Spec drinnen?
Stefan Bodewig Die ursprüngliche Spezifikation, also die RFC, die den Namen OAuth 2.0 im Titel trägt und das Framework, also nicht das Protokoll, sondern das Framework, da legt die Spezifikation Wert drauf, dass sie ein Rahmenwerk für solche Autorisierungs-Delegationsprozesse anbietet, die definiert selber erstmal nur vier Flows. Aber es ist klar, man kann weitere Flows definieren und hinterlegen. Und es gibt eben auch weitere RFCs zum Beispiel für eben diese “living room devices”, die zusätzliche Flows definieren. Und ich glaube der am einfachsten zu erklärende Flow, die haben alle so ein bisschen komische Namen, an die man sich gewöhnen muss, ist der Implicit Flow von dem man heute sagt, den darf man unter keinen Umständen mehr benutzen. Dazu kommen wir wahrscheinlich später noch, aber er ist am einfachsten zu erklären. Das ist ein Flow bei dem mein Client eine Redirect, also mich als den Browser an den ich als Resource Owner sitzte, mit einem Redirect zum Authorization Server sendet und sagt: Hallo, ich bin der Client mit dem folgenden Namen und ich hätte gerne ein paar Berechtigungen von dem Benutzer. Und dann werde ich mich wahrscheinlich bei dem Authorization Server anmelden, das ist nicht so genau klar definiert, wie das passiert und dann fragt der Authorization Server mich als Resource Owner, ob ich dem Ganzen zustimme möchte. “Consent” ist so ein Begriff, der dann da auftritt. Ich sage: Ja, ist in Ordnung, das darf der Client. Und dann redirected mich der Authorization Server zurück zu einem re-direct URI, der im Client liegt und übergibt das Token, das in sich einkapselt, welche Berechtigungen denn ich erteilt habe an den Client im Fragment des URI. Also dem Teil des URI, der hinter dem Doppelkreuz/Hash/Schweinegitter, wie auch immer man das Ding nennen möchte, also ich sage jetzt mal Hash, der dahintersteht und der deshalb auch immer nur im Browser ist und nicht in irgendwelchen Log-Files auf Servern landen könnte oder so. Genau, das heißt dieser Redirect URI, den muss der Authorization Server kennen, an den er das Ganze schicken möchte und das ist glaube ich auch ein Unterschied zu OAuth 1.0, wo man dynamisch sagen konnte: Bitte gib mir das Token an folgenden URI zurück. In diesem Fall müssen Client und Authorization Server sich vorher kennen und der Client muss dem Authorization Server mitgeteilt haben: Bitte schicke die Redirects zurück hierher. Der gibt es auch nochmal mit als Parameter, aber eigentlich ist das vorher schonmal festgelegt: Das ist ein erlaubter URI an dem ich das Token weiter zurücksenden würde. Im Fragment des URIs heißt eben, tatsächlich muss mein Client im Browser laufen, sonst käme er gar nicht dran an das Token. Also dieser Flow ist explizit gedacht für einen Client, der in JavaScript im Browser implementiert ist.
Christoph Iserlohn Bevor wir jetzt nochmal zu den nächsten Flows kommen, das war jetzt relativ abstrakt. Könntest du das vielleicht nochmal so erklären, an dem Beispiel mit unserem schönen Printer und Bilder Service, wo kommt denn der User da an? Also fängt der am im Bilder Service? Fängt der an im Printer Service? Wo kommt die Redirect URI her? Und wer macht da was? Damit man das ein bisschen greifbarer hat.
Stefan Bodewig Gut, dann müssen wir wahrscheinlich noch, bevor ich überhaupt irgendwas tue als Resource Owner, anfangen. Der Printer Service muss wissen, dass irgendwann mal Benutzer kommen werden, die was von einem anderen Service haben wollen, für den eben ein bestimmter Authorization Server zuständig ist. Und dann muss der Printer Service und der Authorization Service, die müssen sich miteinander bekannt machen und da müssen so ein paar Metadaten konfiguriert werden. Also Printer Service erhält vom Authorization Service eine Client ID, also etwas das den Printer Service als Client identifiziert und hinterlegt dort mindestens einen Redirect URI, also einen URI an den das Token nachher ausgeliefert werden soll. Dann kommen wir an den Punkt, dass tatsächlich so ein Benutzer vorbeikommt und möchte den Print Service Zugriff auf den Foto Service geben. Der startet beim Print Service. Der startet nicht beim Foto Service und sagt dem Foto Service: Übrigens später möchte ich mal diesen Drucker irgendwas erlauben. Sondern ich starte beim Print Service, ich starte beim Client der abstrakteren Variante und sage: Bitte drucke diese Bilder, die da hinten auf dem Foto Service liegen. Und dann weiß der Print Service, dass der Foto Service diesen Authorization Server benutzt. Das heißt auch Print Service und Foto Service müssen…, zumindest muss der Print Service den Foto Service kennen. Und schickt mich mit einem Redirect zum Authorization Server. Dem Authorization Server, von dem er weiß, dass der mit dem Foto Service zusammenarbeitet. Und dort melde ich mich dann also an Resource Owner, vielleicht bin ich auch schon angemeldet. Ich verteile dann halt die Berechtigungen und der Redirect geht zurück vom Authorization Server zum Print Service mit dem Token.
Simon Kölsch Hier haben wir so ein bisschen das Problem mit dem Beispiel, dass der… Also was wir besprochen haben ist dieser Implicit Grant. Das Beispiel mit dem Print Service und vielleicht irgendwie einer Applikation, die dann auf dem Gerät läuft, wo ich es auswählen kann, was ich denn gedruckt haben möchte oder ähnliches, ist eigentlich der, wo ich so ein Back-End im Hintergrund habe. Das ist nicht eine Applikation, die die Bilder für mich irgendwie bearbeitet und bei mir lokal auf dem Gerät speichert, sondern es gibt irgendwo diesen Service im Hintergrund, der dann diese Bilder bekommen soll. Und der Implicit Flow ist eigentlich dafür gedacht gewesen initial, dass ich genau dieses Back-End nicht habe. Das heißt in unserem Beispiel würden wir wahrscheinlich sowieso den Authorization Code Grant an der Stelle benutzen.
Christoph Iserlohn Das ist ja die perfekte Überleitung, dass du den dann vielleicht auch mal erklären kannst, was denn dieser Authorization Code Grant denn Flow eigentlich bedeutet. Und wie der sich vielleicht auch unterscheidet von dem Implicit Flow?
Simon Kölsch Genau, also bei dem Authorization Code Grant betrachten wir primär erstmal: Wer muss denn eigentlich diese Tokens bekommen? Also für wen sind die denn? Ich als Benutzer besuche, so wie Stefan das erwähnt hat, irgendwie die Seite und werde dann da hin und her umgeleitet und dann fragt mein Foto Host dann mich: Möchtest du denn diesen Service Zugriff gestatten? Und dann sage ich: Ja, das möchte ich! Und dann müssen wir irgendwie, werden da Tokens getauscht. Und beim Implicit Flow würde ich direkt diese Tokens erhalten und dann ist die Frage: Schickt dann mein Browser dieses Token quasi irgendwie indirekt zu dem Client, also zu meinem Druck Service? Oder landet dieses Token irgendwie sicher direkt bei diesem Druck Service? Und der Authorization Code Grant Workflow funktioniert eben so, wir haben ja keine irgendwie speziellen Kommunikationskanäle zwischen dem Client und irgendwie diesem Host da für die Bilder, sondern wir haben in der Mitte diesen Benutzer stehen und da sind wir in einem Browser oder einer App, die mich halt dementsprechend redirected. Und anstatt dieses Token, was ja eigentlich für mein Back-End für den Print Service bestimmt ist, ich als Benutzer muss in meinem lokalen Browser oder meiner lokalen Applikation gar nicht dieses Token haben, weil ich hole da keine Daten mit ab. Das ist einfach nur die delegierte Berechtigung für Back-End. Dann wäre es ja eigentlich wünschenswert, dass auch nur dieses Back-End Zugriff auf dieses Token hat. Wir wissen alle wie Browser inzwischen im Web aussehen und wie viele Plug-Ins da mit drin sind. Gibt welche, die machen das mit dem Sandboxing ganz gut und es gibt welche, da bricht man auch mal aus so einer Sandbox aus. Und aus der Perspektive raus, ist es eigentlich gar nicht notwendig, dass der Benutzer zu irgendeinem Zeitpunkt diese Tokens bekommt. Deswegen bekommt der Benutzer halt eben nur einen Code und dieser Code, den übergibt er seinen Back-End, in dem Fall unseren Druck Service. Und der Druck Service kann dann den Code und seine Credentials, weil irgendwann hat der sich ja vorher mal bei unseren Bilder Host da registriert, kann dann mit seinen Credentials und den Code das Ganze eintauschen und erhält dafür dann Tokens, die später Zugriff auf die Ressourcen gestatten.
Stefan Bodewig Genau, das heißt in Ergänzung zu dem was ich zu Anfang beschrieben habe, erhält der Client vom Authorization Server nicht nur eine ID, sondern die teilen auch noch ein Geheimnis miteinander. Zusätzliche Specs können dann vielleicht noch sagen: Das machen wir mit asymmetrischer Kryptographie. Aber im Großen und Ganzen gibt es irgendwie neben den Einzelnen, denn eigentlichen Client ID, gibt es weitere Möglichkeiten, wie sich der Client als der Client auch ausweisen kann.
Christoph Iserlohn Okay. Was ich jetzt verstanden habe ist, der Hauptunterschied, jetzt mal abgesehen von den Sicherheitsaspekten, die wir vielleicht gleich noch gesondert besprechen, von den beiden Flows, dass ich bei dem Implicit Flow das Token direkt bekomme, bei dem Authorization Code Grant Flow aber gar nicht das Token in die Hand bekomme als Endnutzer, sondern… beziehungsweise mein Browser, sondern der bekommt einen Code. Der geht wieder an das Back-End und das Back-End weist sich dann mit Code zusätzlich mit seinen Client Credentials aus, um dann ein Token zu bekommen.
Simon Kölsch Genau, richtig.
Christoph Iserlohn Also das ist eine Indirektion mehr, um da mehr Sicherheit zu schaffen, weil der Browser und der Nutzer dann gar nicht so viel weiß, um selbständig das Token zu bekommen, weil ihm ja die Client-Credentials fehlen.
Simon Kölsch Genau das, so hat im Prinzip auch OAuth 1.0 funktioniert und das war dann mit ein Kritikpunkt, der damals geäußert wurde, wo man sagen muss: Okay, wie lösen wir denn das Problem, wenn wir halt eben nicht ein Back-End haben, sondern meine App ist direkt nativ auf eine Telefon eben installiert. Das können wir ja dann plötzlich nicht, weil der Client sich vorher nicht registriert und ein Geheimnis austauschen kann, also hat man dann dafür den Implicit Flow eingeführt.
Stefan Bodewig Auch da muss man das glaube ich nochmal zeitlich einordnen, wenn wir anschauen, wann die Spec geschrieben worden ist. Ich glaube CORS kam erst später, das heißt wir hatten Same Origin Policy im Browser. Der Browser wäre gar nicht in der Lage gewesen einen HTTP-Request zu machen, um das Token zu bekommen, zu dem Zeitpunkt. Wenn der Authorization Server nicht zufällig in der gleichen Domain liegt, in der auch der Client ist. Das heißt der Implicit Flow, der rein redirect-basiert ist, war einer der funktioniert, aber ich hätte bei JavaScript keine eigenen XMLHttpRequest machen können, um ein Token zu erhalten. Rein technisch war da einfach auch eine Restriktion im Weg.
Christoph Iserlohn Und wenn die halt…, also wenn das Ziel ist Third Parties zu autorisieren, dann ist es ja sehr unwahrscheinlich, dass die auch in derselben Domain liegen würden.
Stefan Bodewig Genau, deshalb brauchte man da den Ausgang um diese three-leg Flows, also dreigeteilte Domains im schlimmsten Fall zu haben und die im Browser überhaupt abbilden zu können.
Christoph Iserlohn Jetzt haben wir zwei Flows besprochen und wobei der eine, hast du schon angedeutet, dass man den nicht mehr benutzen soll. Bevor wir drüber sprechen, was man denn stattdessen machen würde, weil es gibt ja immer noch single-page Apps oder native Apps auf dem Mobiltelefon, gibt es aber noch weitere Flows? Welche wären das denn? Und welche Use Cases würden die denn updaten? Weil ich nehme mal an, wenn ich das jetzt gelernt habe, gibt es die unterschiedlichen Flows halt, weil das die unterschiedlichen Use Cases unterschiedliche Anforderungen an diesen Flow haben.
Stefan Bodewig Genau, ich hatte gesagt vier Stück sind in der originalen Spezifikation drin. Der nächste wäre ich glaube eine Abfolge der Client Credentials Grant Flow, ist noch immer Grant mit im Flow, um es noch komplizierter zu machen. Bei dem beschafft sich der Client nicht einen Token, in dem ein Resource Owner Berechtigungen einteilt, einreicht, einräumt, sondern der Client beschafft sich ein Token für sich selber. Das sind eben so sehr spezifische Dinge, wo wir eigentlich sonst technische Benutzer in unserem Use Cases einrichten würden, also wo wir einem Client grundsätzliche Berechtigungen einräumen, die vielleicht sehr klein sind, die beschafft er sich selbst und das ist die einfachst mögliche Variante. Da gibt es einen HTTP-Endpunkt an den schickt der Client seine ID und seine Credentials und bekommt ein Token zurück. Und im Prinzip sehr ähnlich funktioniert dann der vierte und letzte Flow, das ist der Resource Owner Password Grant Flow. Bei dem fragt der Client den Benutzer selber nach seinen Credentials, also nach Benutzernamen und Passwort für den Authorization Server und überträgt die. Das heißt wir machen genau das, für das was OAuth 2.0 vermeiden sollte, wir fragen den Benutzer nach seinem Passwort und geben dieses Passwort dem Client und der überträgt das dann. Also selbst wenn wir dem Client jetzt besonders vertrauen, ist das trotzdem nicht unbedingt das wozu dieses Framework ursprünglich mal erfunden worden ist. Das ist vor allem Dingen gedacht, glaube ich, für Clients, die eben nicht Browser-basiert sind, die auch mit http Redirects nicht so wahnsinnig viel anfangen können. Und bei denen der Start vielleicht bedeuten würde: Ich mache einen Request zum Authorization Server und der rendert dann seine Log-In-Maske. Ich habe aber vielleicht gar keinen Browser in der Hand, der eine HTML-Seite anzeigt, also müsste ich irgendwie die Log-In-Maske da rausparsen, damit ich dem Benutzer etwas anzeigen kann in der Desktop App, in der mobilen App. Also das sind so Flows, die ursprünglich dafür gedacht wurden sind.
Simon Kölsch Genau. An der Stelle lohnt es sich dann wahrscheinlich nochmal hinzugucken: OAuth 1.0 ist ein Protokoll, OAuth 2.0 ist ein Framework. Und damit ist das Scope von OAuth 2.0 natürlich viel, viel größer als das von OAuth 1.0 war. Und ich meine mich zu erinnern, dass diese Sache reingekommen ist nachdem Twitter da mit an der Spec saß und Twitter eben gesagt hat: Naja, wir haben halt folgenden Use Case, wir haben hier einen Client und diesem Client… Sorry, jetzt habe ich Client falsch benutzt, sondern ich meine natürlich, wir haben eine eigene Applikation, wo der Benutzer sich halt eben anmeldet. Wir möchte da halt mit OAuth 2.0 machen und wir vertrauen aber dieser Applikation, weil wir selbst haben halt eben diese Twitter App, die wir über die App Stores von den beiden großen Plattformen irgendwie verteilen und dann ist das absolut okay, wenn der Benutzer da sein Passwort und seinen Benutzernamen eingibt. Und sowas lässt sich dann halt eben mit diesem Flow abbilden, wo man halt eben sagt: Okay, die Plattform, auf der der Benutzer das Ganze eingibt, der vertrauen wir, wir möchten aber eben trotzdem das Ganze über OAuth 2.0 irgendwie lösen.
Christoph Iserlohn Also was du sagst heißt dann: Es gibt eigentlich gar keine Third Party im echten Sinnen, sondern das ist die eigentliche First Party, die ihren eigenen Client ausliefert, aber jetzt nicht dafür eine andere Autorisierungsmechanismus benutzen muss, sondern auch OAuth benutzen kann. Aber da sie es selbst rausgibt ist es auch egal, ob die Passwörter jetzt da eingegeben werden oder in deren eigenen Maske. Es ist beides Mal in derselben party. Habe ich das so richtig verstanden?
Simon Kölsch Ja, das kommt so ein bisschen darauf an, wie eng man diesen Begriff ziehen möchte, beziehungsweise aus welcher Perspektive man sich das anguckt. Für Twitter selbst ist natürlich alles Third Party was irgendwie über eine API-Schnittstelle drauf zugreift, schon allein dadurch, dass der Client auf einen Mobilgerät irgendwo installiert ist. Dann kann man das unter der Perspektive quasi so betrachten, hier delegiert man trotzdem Zugriff an eine Third Party, in dem Moment ist, das halt die App und sowas kann ein Benutzer dann später auch wieder revoken.
Stefan Bodewig Mir ist gerade eben noch eingefallen, dass ich von vier Flows gesprochen habe in der originalen Spec und man eigentlich den Refresh Token Flow irgendwo noch mit sehen kann als darüberhinausgehenden Flow. Also das ist so, dass, ich glaube ganz zu Anfang hat der Simon das mal erwähnt, dass diese Token nur so eine beschränkte Lebensdauer auch möglicherweise haben sollen. Das ich also sage: Ich erteile jemanden nicht auf alle Ewigkeit das Recht, sondern nur für einen begrenzten Zeitraum und das ganz bewusst tue. Es gibt aber vielleicht auch Gründe, dass ich möchte, dass bestimmte Dinge immer wieder passieren. Also, dass ich tatsächlich einem Client dauerhaft den Zugriff geben möchte. Die Token gehen aber möglicherweise relativ häufig über das Netz, sodass ich das einzelne Token, das diese Berechtigung trägt, trotzdem nicht ewig langlebig machen möchte. Da sieht die Spezifikation in dem Framework einen Mechanismus vor, dass ich zusätzlich zu dem Access Token, das mir den Zugriff gibt, noch einen weiteren Token erhalten kann, wenn ich den Authorization Code Grant Flow genutzt habe im Wesentlichen. Und dieser zusätzliche Token ist das sogenannte Refresh Token. Dieses Refresh Token ist deutlich langlebiger als das Access Token und da gibt es eben einen weiteren Mechanismus mit dem der Client, der ein solches Refresh Token besitzt direkt zum Authorization Server gehen kann und sagen kann: Ich habe hier dieses Refresh Token damals erhalten und ich hätte gerne ein neues Token, das mir die gleichen…, ein neues Access Token, das mir die gleichen Berechtigungen gibt, die mein ursprünglich ausgestelltes Access Token hatte, als ich dieses Refresh Token bekommen habe. Weiß ich nicht, wir können uns vorstellen: Ich möchte Kalender drucken einmal im Jahr und ich möchte, dass in jedem Jahr der Print Service vorbeigeht und meine zwölf schönsten Bilder, wie auch immer er die identifiziert, abholt und mir den Kalender druckt. Dann möchte ich, dass er das jetzt tut und dann kriegt er ein Token, das vielleicht nur für die nächste halbe Stunde gültig ist, um die zwölf Bilder zu holen. Und das soll er dann ab jetzt bitte jeden November machen, damit ich zu Weihnachten meinen Kalender fertig habe. Und dann kriegt er eine Refresh Token, dass er in zwölf Monaten noch verwenden kann, um die Fotos abzuholen, die nächsten zwölf. Und bekommt dann auch ein neues Refresh Token, wenn er sich dann wieder ein eine halbe Stunde lang gültiges Access Token abgeholt hat.
Simon Kölsch Der Sicherheitsgewinn ist halt hier ganz klar durch diese Trennung zwischen Authorization Server und dem Resource Server. Weil mein Access Token, so wie Stefan das gesagt hat, das wird häufig irgendwie über das Netzwerk ausgetauscht, wir wissen auch nicht, wo das noch weiterwandert. Wir wissen nicht: Was passiert denn eigentlich damit beim Resource Server? Wird das irgendwie im Back-End nochmal weiter benutzt an irgendwelchen anderen Stellen, um nachzuweisen für wen war denn jetzt eigentlich dieser Request? Alles was da quasi so dranhängt. Und beim Refresh Token können wir uns, auch von der Spec her, sicher sein, dass darf eigentlich nur zwischen dem Besitzer, in dem Fall unseren Client und diesem Authorization Server ausgetauscht werden. Da schreibt die Spec vor, dass wir TLS benutzen müssen, das heißt wir haben einen verschlüsselten Übertragungsweg und die Wahrscheinlichkeit, dass mein Access Token irgendwo abhandenkommt, ist halt eben wesentlich höher als das mit dem Refresh Token passiert. Deswegen ist das okay langlebige Refresh Tokens zu benutzen und eben nur kurzlebige Access Tokens.
Christoph Iserlohn Das verstehe ich. Wenn wir jetzt mal noch ein bisschen konkreter werden: Ich habe jetzt so ein Token in der Hand und wie sieht das denn jetzt überhaupt aus, also steht da dann eine Lebenszeit drin? Gibt es da ein festes Format? Und wie kriege ich die überhaupt zu dem anderen Server? Also der müsste ja wissen, wenn er so OAuth benutzt, das bekomme ich jetzt über Weg XY. Wie funktioniert das denn?
Stefan Bodewig Da triffst du geraden einen der ganz starken Kritikpunkte, der sich OAuth 2.0 hat immer wieder aussetzen müssen und auch berechtigt aussetzt, wenn wir nur auf den einen RFC schauen, der das OAuth 2.0 Framework festlegt. Ganz häufig findet man innerhalb dieser Spezifikation ist “beyond the scope of the spec”, das heißt bestimmte Dinge sind ausdrücklich als das OAuth 2.0 Framework festgelegt wurden ist, nicht definiert wurden. Dazu zählt: Wie sieht eigentlich so ein Token aus? Das stimmt schon nicht ganz. Die Spec sagt: Das ist irgendein String und das geht dich nichts an, wie das aussieht. Wenn wir draufschauen, für wen ist dieses Token eigentlich gedacht? Das Access Token erhält zwar der Client, aber der Client muss gar nicht wissen, was da drinsteht. Der soll das auch gar nicht interpretieren können. Der bekommt halt irgendwie ein Token in die Hand und das gibt er dem Resource Server. Der Resource Server, der muss dann schon wissen, was dahintersteckt. Das heißt, derjenige, der wirklich wissen müsste, was mache ich denn jetzt mit dem Token, ist der Resource Server und wie der Resource Server herausbekommt, was dieses Token bedeutet, wie lange das gültig ist, welche Berechtigungen darin stecken, das ist in dem Framework in der originalen Spezifikation so nicht festgelegt. Da gibt es dann spätere Spezifikationen, es gibt einen Token Introspection eEndpoint in einem zusätzlichem RFC, wo der Resource Server das Token hinschickt und das praktisch geparst bekommt, wenn man so will. Das könnte auch einfach der Primary Key von irgendwas was in der Datenbank des Authorization Servers liegt sein, also das muss gar nicht irgendwas sein was man außerhalb des Authorization Servers verstehen kann. Und der Token Introspection Endpoint würde dann sagen: Okay, dieses Token habe ich ausgestellt, das ist bis dann und dann gültig. Das ist auch jetzt tatsächlich noch gültig und darein eingekapselt sind die folgenden Berechtigungen. Das sind die Dinge, die derjenige, der dieses Token vorweist tun darf. Und das habe ich ausgestellt für diesen Client, auch das könnte durchaus drinstehen, sodass ich eben als Resource Server weiß: Derjenige, der mir jetzt das Token gibt, ist das überhaupt derjenige, für den das ausgestellt worden ist? Und bin ich eigentlich der Resource Server, für den das Token ausgestellt wurde? Auch das ist Teil dessen was ich da zurückbekommen kann. Später hat es weitere Spezifikationen gegeben, die andere Formate für Token festlegen. Zum Beispiel es gibt Definitionen: So ein Token könnte eine SAML Assertion sein, das ist ein XML-Dokument, das relativ komplex ist oder eben relativ neu in Anführungsstrichen, inzwischen auch ein paar Jahre alt, ist. JSON Strukturen zu haben, die so abgebildet sind, dass sie etwas kompakter werden und dabei noch signiert und optional verschlüsselt sein können, das sogenannte JSON Web Token JWT oder “JOT”, wie man das ausspricht, wenn man der Spezifikation folgt. Das wären Formate, die solche Token haben könnten, aber OAuth 2.0 legt nicht fest wie so ein Token aussieht. Auch für den Weg, wie das Token übertragen wird an den Resource Server, ist es zunächst einmal in der Spezifikation nicht festgelegt. Da gibt es dann auch weitere RFC, die einen zum Beispiel auf http Authorization Header basierendes Subprotokoll definieren. Also man konnte schon immer das Protokoll, das http festlegt für Authentisierung eigentlich, den Authorization Header und den www-authenticate Header nutzen um das zu erweitern, dass man nicht nur basic Auth und digest authentication, die im Kern definiert sind nutzen kann, sondern das erweitern kann und sie haben das erweitert um ein Subprotokoll namens “bearer”. Das heißt ich schreibe dann also: authorization-bearer und dahinter gebe ich mein Token. Also ich haben einen http Header, eine definierten http Header, in dem ich das Token reinschreibe. Aber auch andere Mechanismen waren definiert, zum Beispiel der gleiche RFC, der die Bearer Token Authentication für den Authorization Header definiert, sagt auch: Ich könnte das Token als Query-Parameter übergeben im URI bei Requests. Und dann gibt es durchaus noch weitere Möglichkeiten, dass sind aber… Also das Bearer Token im Header ist so der gängigste Weg eigentlich, wie ich das Token übertrage.
Christoph Iserlohn Du sagtest gerade, dass ganz viel in der Spec auch außerhalb des Scopes ist und hast jetzt gerade auch erwähnt, dass man dann zusätzliche RFCs gemacht hat, um solche Lücken auszugleichen. Bevor wir jetzt darauf eingehen welche zusätzlichen RFCs und Specs es denn noch gibt, wird mich denn mal noch interessieren welche Lücken es denn sonst noch so gibt? Du hast das als großen Kritikpunkt genannt, jetzt haben wir gerade darüber gesprochen, wie so ein Token überhaupt aussieht und wie ich das übertragen kann an den Resource Server ist nicht definiert, aber da gibt es dann wahrscheinlich noch mehr Lücken, die sich da aufgetan haben. Welche wären das denn?
Stefan Bodewig Daher kommt, wenn wir erst einmal schauen was die Spezifikation explizit offenlässt, sind das solche Fragen wie: Wie kennen sich eigentlich Resource Server und Authorization Server? Wie lernen sich Client und Authorization Server eigentlich kennen? Also solche Protokolle, um Clients zu registrieren und zu kommunizieren: Das ist übrigens der Authorization Server mit dem ich eben… der für mich zuständig ist als Resource Server. Diese Dinge sind zunächst einmal nicht definiert gewesen, sind auch heute eher noch so ein bisschen im Fluss, um zu sehen, wo man hinkommt. Kann ich Token widerrufen, wenn sie einmal ausgestellt worden sind? Lässt die Spezifikation offen, ob das überhaupt möglich ist und wenn ja, wie finde ich das raus, dass das passiert ist?
Simon Kölsch Wir haben da ja auch im Vorfeld ein bisschen drüber geredet und dann war es halt eben so ein bisschen die Frage: Wie wurde denn OAuth eigentlich auch so aufgenommen und umgesetzt? Und ich hatte das erwähnt, dass OAuth 1.0 ein Protokoll war. Das konnten wir einfach runterimplementieren und damit waren eben auch alle Implementierungen kompatibel miteinander. OAuth 2.0 ist ein Framework, um Third Party Access Delegation zu bauen und dieses Framework deckt nicht alle Punkte ab, die man für eine Implementierung braucht. Selbst wenn wir jetzt ein Format für diese Tokens festlegen, dann haben wir immer noch nicht definiert: Was steht denn in dem Token eigentlich drinnen? Also klar, wenn wir sagen: Das ist eine SAML Assertion, dann wissen wir natürlich auch was in einer SAML assertion drinsteckt, an Keys oder ähnliches. Aber die konkrete Implementierung, die wird dazu neigen nicht kompatibel miteinander zu sein. Und das hat OAuth da so ein bisschen erstmal auch gar nicht als Aufgabe gesehen, sondern die haben gesagt: Naja, wir definieren hier halt eben Flows wie man diese Tokens tauscht, wie man das auf eine sichere Art und Weise tun kann. Meine Kritik daran wäre, man hat da einfach zu viel versucht abzubilden. Da saßen einfach zu viele Leute zusammen und da musste halt jeder Use Case rein, egal ob das halt eben noch im Entferntesten mit OAuth zu tun hat oder eben nicht. Die Spec ist auch so geschrieben, dass es sich sehr einfach erweitern lässt und dementsprechend haben wir auch ich weiß gar nicht wie viele Drafts im Moment es noch gibt. Aber es ist nicht damit getan, dass man halt irgendwie bei OAuth 1.0 diese 30 Seiten RFC hat oder 40 Seiten RFC, sondern ich weiß nicht, es sind bestimmt 20 Dokumente, 30 so in der Größenordnung, die das Ganze dann nochmal erweitern. Also macht es dann da an der Stelle irgendwie problematisch und was man halt eben einfach nicht erwarten darf ist, dass ich hier eine OAuth 2.0 Implementierung auf der einen Seite habe und eine OAuth 2.0 Implementierung auf der anderen Seite und das die magisch miteinander funktionieren. Das wird wahrscheinlich nicht der Fall sein.
Christoph Iserlohn Ob das ein guter Ansatz ist für so ein RFC, das würde ich gerne noch diskutieren, aber vielleicht etwas später. Stefan hat gerade eine ganze Menge Lücken in diesem Core RFC erwähnt und auch gesagt, was jetzt so alles dazu gekommen ist. Simon du hast auch ein bisschen ergänzt, das ist jetzt auch ein paar Jahre her und da ist was dazugekommen. Vielleicht könnten wir nochmal kurz listen welche Specs denn wirklich relevant sind, also die neu dazu gekommen sind und so ein bisschen Interoperabilität der Implementierung dann herzustellen. Wir verlinken die dann vielleicht auch nochmal in den Shownotes, aber damit man weiß: Welche gibt es? Und welchen Zweck erfüllen die? Der Stefan hatte gerade schon eine genannt, da ging es um zum Beispiel das Format der Tokens dabei und wie das übertragen wird, aber da gibt es ja noch mehr.
Simon Kölsch Naja, wenn man das versuchen will grob zu kategorisieren, dann hätte man eben die OAuth 2.0 Framework Spec. Die beschreibt so ganz grundlegend was es denn da so gibt. Und zu diesem Core Teil dazu gehören dann eigentlich nochmal diese bearer Token Geschichte und halt eben FRAD model und Security Considerations. Das würde ich behaupten sind die drei Core OAuth Specs an der Stelle eigentlich. So und die würde man jetzt noch ergänzen zum Beispiel durch sowas wie Token introspection, wo man halt eben einen Token hinschicken kann an einen Server und bekommt dann die eigentlichen Informationen da raus. Oder sowas wie Token Revocation und generell sowas wie schaut, was man da noch mit reingenommen hat. Aber das kann Stefan wahrscheinlich jetzt ergänzen auch.
Stefan Bodewig Ich würde dann von einem Token Teil vielleicht sogar ein Stück weggehen und sagen wir haben darüber hinaus einen durchaus interessanten Teil der eigentlich aus OpenID Connect gekommen ist, den Discovery Teil. Wir haben halt eine ganze Menge von URIs, die man kennen muss. Also es gibt den URI zu dem ich als Client einen Redirect mache, damit der Benutzer mir die Berechtigung erteilen kann. Ich muss einen URI haben bei dem ich das Token bekomme, wenn ich Authorization Code Grant Flow mache. An diversen Stellen sind verschiedenste Algorithmen erlaubt um Dinge zu tun, ich muss vielleicht wissen welchen Algorithmus unterstützt denn der konkrete Authorization Server jetzt mit dem ich rede? Also gerade um doch etwas mehr Interoperabilität in diesem sehr losen Framework Gedanken hinzubekommen hat man im Umfeld der OpenID Connect Spezifikation eine Spezifikation zur Discovery entworfen. Da gibt es dann einfach einen wohl definierten URI unter dem ein JSON Dokument steckt, das wohl definierte Schlüssel hat. Da steht dann also drin: Hier ist der URI für den Authorization Endpoint. Und dann rufe ich nur dieses eine JSON Dokument ab und dann kann ich mich selber konfigurieren als Client, der das Ganze benutzten möchte. Davon gibt es jetzt auch eine Variante, die nicht mehr OpenID Connect spezifisch ist. OpenID Connect hat halt so ein paar Dinge da drin, die für OAuth 2.0 alleine keinen Sinn ergeben, sodass ich da einerseits das Ganze ein wenig eingeschränkt hat auf das was wirklich OAuth 2.0 braucht und auf der anderen Seite ein paar Dinge hinzugekommen sind. Zum Beispiel hat man, um den Authorization Code Grant Flow und auch den Implicit Flow ein Stück weit besser absichern zu können ein paar zusätzliche Parameter definiert. Das ist PKCE spricht sich diese Spezifikation aus, PKCE: Proof Key, mir fällt gerade nicht ein, wofür das C steht, Challenge Exchange. Wo also wir zusätzlich zu den Credentials, die der Client hat, in den eigentlichen Austausch noch etwas hinzufügen bei dem nachher der Authorization Server sicherer sein kann, dass derjenige der das Token abholt, auch derjenige ist, der ursprünglich den Flow gestartet hat. Also um so ein Stück weit zusätzlich zu dem eigentlichen Passwort noch etwas an extra Sicherheit hinzuzufügen. Würde ich definitiv noch hinzunehmen als Spezifikation. Im Kontext von Token gibt es häufiger auch noch den Anwendungsfall, dass ich einen Token habe und das möchte ich so wie es ist aber eigentlich gar nicht versenden. Ich brauche vielleicht ein anderes Token, das weniger Berechtigungen hat als das, was ich da jetzt habe. Oder ich habe ein Token von einem Authorization Server bekommen, brauche aber ein Token von einen anderen Authorization Server, da gibt es so Federation Protokolle, bei denen man verschiedene Server miteinander sprechen lassen kann. Und in deren Kern steckt eine Spezifikation für den Austausch von Token, also ich habe einen Token und ich möchte gerne ein anderes haben, da gibt es den Token Exchange Endpunkt. Da muss man allerdings sagen, dass während Token introspection/revocation und auch PKCE von sehr vielen Implementierungen von Authorization Servern angeboten werden, auch Discovery eigentlich inzwischen weitgehend vorgefunden wird, zumindest in der OpenID Connect Geschmacksrichtung, bei Token Exchange das noch nicht so wahnsinnig viele Server sind, die das auch tatsächlich unterstützen, vollständig unterstützen.
Simon Kölsch Genau, da muss man vielleicht einfach erwähnen, ich meine warum liest man denn diese Specs? Das ist nicht so die Lektüre, die man zum Einschlafen lesen will, zumindest wenn man keine Albträume haben möchte. Aber normalerweise versucht man ja irgendwie ein Produkt oder ähnliches zu evaluieren, beziehungsweise überlegt sich, ob ich ein Problem damit lösen kann und da muss man einfach sagen es gibt halt eine ganze, ganze Reihe an OAuth 2.0 Specs. Was man da immer im Hinterkopf behalten muss ist: Diese ganze Spec Framework Geschichte ist halt sehr modular und ich muss immer prüfen, selbst wenn es da eine Lösung in Form eines RFCs oder ähnliches gibt, muss ich immer prüfen, ob meine Implementierung das halt auch wirklich unterstützt. Es gibt nicht diese OAuth 2.0 kompatible Authorization Server Implementierung, sondern ich muss genau hingucken welche Features möchte ich denn eigentlich haben? Und ganz oft ist es halt eben so, wie eben so Standards entstehen, es gibt erstmal so einen Draft und dann gibt es da vielleicht einen oder zwei Implementierungen davon. Und am Ende stellt sich raus, dabei bleibt es halt eben und dann ist so ein Dokument halt einfach trotzdem 5/6/7 Jahre als Draft zwar irgendwie Teil dieses Standards, aber man kann nicht davon ausgehen, dass das breit irgendwie unterstützt wird.
Christoph Iserlohn Zu den konkreten Implementierungen kommen wir vielleicht gleich nochmal, vorher würde ich gerne noch ein anderes Thema besprechen. Stefan hatte gerade das Stichwort Sicherheit genannt. Wenn ich so ein Framework habe und nicht direkt ein ganzes Protokoll, was vorgefertigt ist, dann muss ich ja wahrscheinlich auch bestimmte Aspekte der Sicherheit dabei betrachten, wenn ich das implementiere das Framework und das sozusagen in ein konkretes Protokoll überführe. Was ich vorhin mitgenommen hatte war, dass zum Beispiel bei OAuth 1.0 alle Requests signiert werden. Wie sieht es denn hier bei OAuth 2.0 mit der Sicherheit aus? Also was ich vorhin gehört hatte oder was man daraus schließen kann, dass die Tokens gar nicht definiert sind, wie die aussehen, heißt ja auch im Umkehrschluss, dass ich zum Beispiel nicht vorschreiben kann, dass so ein Token signiert sein muss oder kann, weil das ist einfach erstmal noch undefiniert. Dann habe ich noch etwas gehört von, dass es ja ganz viele Redirects in diesen Flows gibt. Redirects sind ja auch immer ein bisschen kritisch zur Sicherheit und da gibt es vielleicht auch noch mehr Aspekte, die dabei betrachtet werden sollten, wenn wir das machen. Was sind denn so die Sachen, worauf man denn aufpassen muss? Und wo vielleicht auch die Spec auch mal wieder eine Lücke hat oder was sie auch explizit vorsieht, wo man drauf achten muss?
Stefan Bodewig Ganz explizit sagt die Spec sehr weit vorne, dass TLS zwingend vorgeschrieben ist für alles was da passiert. Man sieht bei sehr vielen Requests, die in der Spezifikation vorgesehen sind, dass Credentials…, Token sind am Ende ja auch Credentials, wenn man so möchte, vollkommen offen in HTTP-Request durch die Gegend gereicht werden das zu tun ohne dass zumindest der Transporter verschlüsselt wäre, wäre grob fahrlässig. Das sagt die Spezifikation aber auch ganz klar so, wo es trotzdem Menschen, die das nachher umsetzen, nicht unbedingt daran hindert das zumindest in Spielwiesen unverschlüsselt zu betreiben. Also was dann auch dazu führt, dass Authorization Server das zumindest aufweichen und auch HTTP-Requests möglicherweise zulassen, obwohl es laut Spezifikation in der Form natürlich strengstens verboten wäre das zu machen. Bei Redirects habe ich erzählt zu Anfang, es gibt einen Redirect vom Authorization Server zurück zum Client und ich gebe den URI auch an zu dem ich gerne mein Redirect zurückhaben möchte. Das droht natürlich, dass ich da vielleicht Redirect zu irgendwelchen bösen anderen Seiten aufmache oder dass ich missbraucht werde, um bei Fishing Attacken ein Redirect auf Seiten auszuführen, zu denen eigentlich kein Redirect hätte gemacht werden sollen. Das ist so das Open Redirector, ist da glaube ich das Stichwort, wenn man da nach der Sicherheitslücke, die dahintersteckt, suchten möchte. Dagegen schützt sich der Authorization Server, indem er eben nur auf registrierte Redirect URIs seinen Redirect nachher ausführt. Sollte er zumindest tun. Insgesamt gibt es da eine zusätzliche Spezifikation, die relativ ausführlich so ein paar Security Best Practices in Form eines RFCs ausführt und da steht das eben auch drin. Beispielsweise in diesem Fall, wie man sich gegen einen solchen Angriff schützen könnte. Ein anderer Angriff wäre CSRF im Endeffekt, also Cross Site Request Forgery, das jemand mich verleitet, ich, der ich ein Client bin, der einen Authorization Code Grant Flow prinzipiell mit einen bestimmten Authorization Server sprechen würde, mich verleitet einen Token Request zu machen, in dem ich einen bestimmten Code mitgebe, indem er mir nicht aufruft, direkt meinen Redirect URI aufruft mit einem Code. Und dann würde ich den Request ausführen, obwohl ich überhaupt gar kein Token bestellt habe, ursprünglich bestellt, in Anführungsstrichen. Da gibt es Mechanismen, um mich davor zu schützen, da gibt es einen State Parameter, den ich herausreiche, wo ich als Client sage: Bitte gib mir einen Token. Und der Authorization Sever sendet diesen State Parameter auch wieder zurück an mich. Das heißt, ich kann sicher sein, wenn ich einen State Parameter in meinem Redirect URI finde, kann ich ihn vergleichen mit den, den ich ursprünglich mal geschickt habe. Ich muss mir den also irgendwie merken für den Browser, der hier gerade unterwegs ist und kann so sicherstellen: Diese Antwort gehört wirklich zu einem Request den ich selber gesendet habe und auch wirklich zu dem Request für den ich gerade eine Antwort erwarte. Und so finden sich da durchaus noch weitere Angriffsvektoren, für die es sich auf jeden Fall lohnt da reinzuschauen, auch wenn man einen Client oder Resource Server oder gar eine Authorization Server selber implementieren möchte, Anleitungen zu finden, worauf man achten sollte.
Simon Kölsch Genau, das sind zwei Dokumente: OAuth 2.0 Threat Model und Security Consideration, das ist quasi der offiziell verabschiedete Standard und darauf gibt es halt inzwischen…, also der ist von 2013 und darauf gibt es inzwischen noch eine Erweiterung, nämlich das ist jetzt halt ein Draft, das ist einfach OAuth 2.0 Security Best Current Practice und der ist ein bisschen aktueller, da sind glaube ich die letzten Edit vom Oktober 2020. Genau, das sind die zwei Dokumente, die man sich eigentlich in jedem Fall einfach mal anschauen sollte. Und es geht einmal Querbeet über das ganze Threat Model, was das Framework angeht eben durch und gibt da entsprechende Empfehlungen.
Christoph Iserlohn Dann haben wir jetzt alles zusammen, um sozusagen eine vernünftige Implementierung zu machen. Also wir haben die Core Spec, wir haben alle Ergänzung Spec, damit die möglichen Lücken geschlossen werden, wir wissen, wie wir es sicher machen können oder wie wir es sicher machen sollten. Stefan du hast gerade erwähnt, wenn man sowas selber implementiert, aber wahrscheinlich wird man sowas ja gar nicht selber implementieren, oder? Also wahrscheinlich wird man da doch auf vorhandene Lösungen zurückgreifen. Da ist die Frage: Gibt es denn sowas? Gibt es sowas im Open Source? Muss ich das kommerziell kaufen oder muss ich mich doch entscheiden das selber zu machen? Und wenn ja, welche Teile müsste ich denn überhaupt selber machen? Den Client? Den Server? Wie sieht es da aus?
Stefan Bodewig Authorization Server ist etwas, was sich ja geradezu aufdrängt als Produkt. Also nicht nur, dass man das kaufen möchte oder einen fertigen Server als Open Source verwenden möchte, sondern umgekehrt, dass es sich aufdrängt, irgendwie sowas als Produkt selber zu bauen. Insofern gibt es gerade auf dem Serverbereich für den Authorization Server eine ganze Reihe von Anbieter, sowohl kommerzielle als auch solche die Open Source sind. Keycloak ist glaube ich schon mal von Simon erwähnt wurden, kommt aus der Red Hat Ecke, ist die Open Source, also praktisch die Community Edition des Red Hat Authorization Servers oder so glaube ich heißt der.
Simon Kölsch Inzwischen ja.
Stefan Bodewig Okay.
Christoph Iserlohn Wir verlinken es in den Shownotes mit dem Namen.
Stefan Bodewig Gut, also es gibt ein kommerzielles Produkt von Red Hat und Keycloak stellt die Community Variante davon da. Man bekommt also keinen, zumindest von Red Hat, keinen Support für den Keycloak. Aber ansonsten ist das eigentlich der Kern dessen, was sie als Produkt verkaufen. Dann gibt es eine ganze Reihe von Software-as-a-Service Anbietern, Auth0 ist eins, das mit ziemlich im Gedächtnis geblieben ist, vor allem Dingen das, dass sie so hervorragende Dokumentationen haben. Und offensichtlich sich sehr stark an Entwickler wenden. Ich glaube die sind nicht so wahnsinnig sexy auf der Marketing Seite, aber sie geben einem als Entwickler das Gefühl, dass sie wirklich wissen, wovon sie sprechen. Was für Security Software nicht unbedingt das Schlechteste ist. Aber es gibt auch da andere Anbieter, sowohl im Bereich von as-a-Service, die großen Cloud Plattform Anbieter haben eigentlich alle irgendeine Art von Authorization Server unter dem… Nein, eher kommen sie aus dem Identity Management Bereich. Also es gibt dann eine OpenID Connect Provider, den ich… In AWS heißt der dann Cognito und in Azure ist es dann der Azure B2C oder sowas. Also es gibt dann Angebote aus dem Cloud Bereich, die auch OAuth 2.0 natürlich sprechen, aber möglicherweise nicht in dem Umfang wie ich mir das wünschen würde. Das ist so der Bereich des Authorization Servers. Für die Client Seite und die Resource Server Seite ist das weniger attraktiv das zu produktisieren, deshalb findet man da eigentlich eher Dinge im Open Source Bereich. Also tatsächlich Dinge, wo sich Leute hingesetzt haben und gesagt haben: Ach, wahrscheinlich steht da irgend so ein Reverse Proxy davor, der ein Apache Webserver oder nginx ist, man könnte ein Modul schreiben, das in diese Webserver eingebunden wird und die Rolle des Resource Servers abdecken kann oder die Rolle des… Die des Clients ist komplizierter für ein Reverse Proxy abzubilden, aber des Resource Servers. Ich schaue nach, ob das Token kommt in einen Bearer und weise Requests ab, wenn ich das nicht finde, sowas auf dieser Ebene. Verifiziere das Token, all diese Dinge. Für die Client Seite werde ich wahrscheinlich programmiersprachenspezifische Bibliotheken benötigen. Da muss man dann auch schon immer ein bisschen drauf gucken. Es gibt zum Beispiel im Kontext des Keycloak-Ökosystems Bibliotheken, die dann eben eher spezifisch mit Keycloak funktionieren und komplizierte anzupassen wären, wenn man mit anderen Authorization Servern arbeiten möchte. Da gibt es aber einen ganzen Sack voll mit Implementierungen für praktisch alle Plattformen, gibt es fertiges. Implementierungen im weitesten Sinne sind natürlich auch die existierenden APIs, wobei man sehen kann das GitHub, was wir als Entwickler kennen, aber eben auch Google, Facebook, Twitter ihre eigenen APIs alle über OAuth 2.0 ansprechbar machen. Und deshalb gibt es auch, gerade von Google beispielsweise, fertige SDKs damit man mit Google APIs sprechen kann, in deren Kern aber auch einfach OAuth 2.0 Client Bibliotheken, die von Google kommen, stecken.
Christoph Iserlohn Okay, also für den Authorization Server gibt es viele Produkte, sollte man vielleicht nicht selber machen. Für die Clients gibt es dann auch nochmal jeweils Bibliotheken, die wahrscheinlich programmiersprachenspezifisch sind oder Produktspezifisch auch nochmal sind. Das heißt, was muss ich denn jetzt genau als Entwickler denn so dabei tun, wenn ich sowas nutzen will? Nehmen wir mal an, wir benutzen dann so einen Software-as-a-Service Anbieter, um sozusagen den Authorization Server zu betreiben oder der eigene Betrieb macht das. Aber wenn ich jetzt in so einem verteilten Umfeld unterwegs bin, also Micro Service Umfeld sagen wir mal, dann müsste ich das irgendwie ja auch einbinden können bei mir. Was ist denn dann so zu tun für den einzelnen Entwickler? Muss ich das überall machen? Kann ich das irgendwie woanders hinschieben, dass das für mich gemacht wird? Was muss ich noch beachten?
Simon Kölsch Ich würde da schon unterscheiden in welcher Rolle ich da gerade unterwegs bin. Wenn ich einen Resource Server implementiere, ich also praktische eine Anwendung implementiere, die Ressourcen zur Verfügung stellt als solche, muss ich darauf warten, dass ich aufgerufen werde und mir ein Token gegeben wird und ich muss dieses Token verifizieren. Das sind bis dahin Dinge, die nicht zwingend in der Applikation selber gemacht werden müssen, die auch ein Proxy, der vor der Applikation steht, erledigen könnte. Das ist ein durchaus nicht unübliches Pattern, das schon seit sehr langem in Form von Reversed Proxies existiert, das in containerisierten Umgebungen nachher als Sidecar Pattern auftaucht und ich kenne das auch in Kubernetes, der Ingress-Controller, der also vorher zwischen den Browser und meiner Applikation oder den außerhalb des Kubernetes Cluster befindlichen http Client und meiner Anwendung steht, das der Ingress-Controller eine solche Aufgabe übernehmen könnte: Prüfen bei jedem Zugriff, gibt es da eigentlich ein richtiges Token, das reinkommt. Das kann ich also rausgeben. Das bedeutet aber nicht, dass ich dann in der Implementierung des Resource Servers fertig bin, weil dann heißt es nur, ich weiß da ist ein Request mit einem gültigen Token gekommen. Ob diese Token aber tatsächlich die Berechtigung in sich trägt auf diese Resource zuzugreifen, auf die sie zugreifen möchte, dass muss ich schon noch immer selber prüfen und muss sicherstellen, dass ich die Zugriffskontrolle auch erzwinge. Also alles was ich zugesichert bekommen habe ist, das ist ein gültiges Token da. Aber es ist eben die Kontrolle: Was erlaubt dieses gültige Token eigentlich? Die muss ich noch immer selber stattfinden lassen. Die andere Seite ist die, wenn ich Client bin. Wenn ich also auf Ressourcen zugreifen möchte. Da ist das Schwierige, das in einem Sidecar zu erledigen, weil da muss ich eigentlich häufig in den HTTP-Request Dinge noch einschleusen können, muss einen Authorization-Header setzen oder sowas in der Art. Da gibt es Bibliotheken, die ich einbinden kann, die ich konfigurieren kann, bei denen ich sagen kann: Da ist die Discovery URI von dem Authorization Server, hier sind die Credentials. Macht das mal alles für mich und dekoriere meine Requests. Da kenne ich aber jetzt nicht zumindest unbedingt Sidecar-Lösungen, die das erledigen, sondern da ist das eher so, dass ich das auf der… irgendwo, wo ich meine Request implementiere selber noch einstreue. Weil wahrscheinlich eine rausgehende, eine Sidecar, das einen rausgehenden HTTP-Request hat, modifiziert, könnte das auch tun, könnte das auch selber machen. Also so ein Service Mesh Kubernetes, vielleicht tun das auch welche. Ich weiß es gerade nicht.
Christoph Iserlohn Das heißt also die meisten Aufgaben kann ich delegieren als Entwickler an vorhandene Bibliotheken oder an Sidecar, also die Infrastruktur delegieren. Aber der wesentliche Punkt ist, was diese Access Control Mechanismen, die man eigentlich braucht ja, ich hab zwar eine Autorisierung bekommen, aber die muss ja irgendwie geprüft werden und im Zweifelsfall muss das ja verweigert werden oder zugelassen werden. Das ist alles ein Teil, den ich selber implementieren muss und der sozusagen nicht vorgefertigt ist in diesem ganzen OAuth Bibliotheken. Habe ich das so richtig verstanden.
Simon Kölsch Naja, du delegierst deine Zugriffe, das bedeutet du musst dir schon selbst überlegen wie deine Rollenrechte aussehen, wie das verteilt ist, was du denn da eigentlich delegieren möchtest, also der eigentliche Inhalt. Wie sieht denn die spezifische Konfiguration aus? Das sind alles diese Fragen, da kann ich nicht quasi OAuth als ein Produkt installieren und dann ist das alles schon fertig. So die eigentliche Prüfung muss ich selbst machen. Ich muss meine entsprechende Bibliothek raussuchen, ich werde sehr wahrscheinlich nicht selbst OAuth implementieren müssen auf so einer Protokoll Token Flow Ebene. Ich werde nicht den Implicit Flow oder sowas nachprogrammieren müssen, das macht schon zu einem gewissen Teil die Library. Aber trotzdem sollte ich irgendwie verstehen, was da funktioniert, weil spätestens, wenn wir dann halt eben in die Umsetzung kommen, man wird da früher oder später mal debuggen müssen und das ist dann halt nicht mehr ganz so trivial. Also komme ich an der Stelle nicht drumherum, aber den Code, den ich schreiben muss, um so Standard OAuth Flows oder ähnliches abzubilden, das ist eigentlich normalerweise da.
Christoph Iserlohn So, wir sind jetzt sozusagen von der unfertigen Spec am Anfang des Podcasts gereist, bis zu einer Implementierung und was man so als Entwickler alles beachten muss. Also so zum fertigen System. Das wäre vielleicht der richtige Augenblick zu schauen: Was kommt denn da noch in Zukunft? Weil ganz am Anfang hattest du ja schon erwähnt Stefan, bei den Flows, dass ja der eine Flow, der Implicit Flow eigentlich gar nicht mehr benutzt werden sollte. Und meines Wissens nach soll der auch wirklich in der nächsten Iteration der Spec dann auch wirklich… Also es wird nicht mehr nur abgeraten, sondern er soll wirklich hinausfliegen. So ganz konkret geht es um OAuth 2.1, das ist halt die zukünftige Version, die kommen wird. Vielleicht sollen wir nochmal kurz besprechen, was denn da uns in Zukunft alles erwarten wird mit der neuen Spec.
Simon Kölsch Genau. OAuth 2.1 soll kein komplett neues Framework werden oder ein komplett anderes Protokoll oder sowas, sondern OAuth 2.1, da hat sich die OAuth Working Group zusammengesetzt und gesagt: Wir überlegen uns mal, was hat sich in den letzten 8–9 Jahren seitdem wir an OAuth 2.0 arbeiten verändert in der Welt? Was haben wir zwischenzeitig hinzugelernt? Wo können wir Dinge nachschärfen? Und können das in einer Art und Weise tun, ohne dass wir damit Kompatibilitäten an allen möglichen Ecken und Enden brechen? Das Framework als solches bleibt eigentlich erhalten und auch die zusätzlichen Spezifikationen bleiben irgendwie erhalten. Sie werden nur ein Stück weit neu miteinander kombiniert und es wird im Fall des Implicit Flows, das gleiche geht für den Resource Owner Password Grant Flow, das OAuth 2.1 sagt: Die gibt es zwar noch, aber die sollte man nicht mehr benutzen. Sondern dafür sagen sie, dass das pixie, das ich erwähnt habe, zwingend zukünftig bei allen Authorization Code Grant Flow benutzt werden muss und der Implicit Flow wird am Ende ersetzt durch eine Authorization Code Grant Flow, plus PKCE, minus Client Credentials im Endeffekt. Also man weicht ein Stück weit dem Authorization Code Grant Flow aus, nimmt die Kleincredentials raus, fügt aber dafür den zusätzlichen Sicherheitslayer PKCE hinzu. Und dann werden eben so ein paar Dinge noch nachgeschärft. Ich hatte schon gesagt, der Redirect URI an den ein Token einen Client weitergesendet wird, der muss eine Authorization Server hinterlegt werden. Da ist aber nie so besonders klar gesagt worden, wie prüft eigentlich der Authorization Server, ob dieser Redirect URI einer ist, der gültig ist oder nicht, da werden so ein bisschen die Schrauben enger angezogen. Es wird gesagt: Es muss wirklich genau der URI da definiert sein, der da verlangt wird. Irgendwelche Wildcard-Matching-Geschichten erlauben wir einfach nicht mehr zukünftig. Und insgesamt sind eigentlich die Dinge, die aus den Security Current Best Practices kommen jetzt, die dort als meeting options drinstehen, werden einfach jetzt als verpflichtend aufgenommen, wird gesagt: Du musst das jetzt so machen. Das ist eben nicht mehr offengelassen, ob man einen State Parameter sendet, sondern man muss das einfach tun. Und da werden einfach Dinge etwas schärfer festgelegt und auch ein paar Dinge auch durchaus eben weggelagert, die in Spezifikationen drinstanden, wie dass man Token auch als Query Parameter übergeben könnte. Der RFC ist dann zwar immer noch da, aber diese Variante wird als, “sollte man nicht tun”, deklariert. Aber das Ziel ist, dass man OAuth 2.1 implementieren kann, ohne dass man eine OAuth 2.0 Implementierung wegwerfen muss, sondern nur indem man sie etwas weiter absichert und voraussetzt, dass bestimmte Spezifikationen, PKCE in erster Linie mal, zusätzlich implementiert sind.
Christoph Iserlohn Das heißt also, es handelt sich bei OAuth 2.1 dann um eine reine Weiterentwicklung und Verbesserung sozusagen, die man jetzt aus den Praxiserfahrungen mitgenommen hat, um da Best Practices nicht nur als Best Practices zu machen, sondern als verpflichtende Practices sozusagen.
Simon Kölsch Ja.
Christoph Iserlohn Sehr schön! Gibt es denn eigentlich Alternativen zu OAuth? Also mir ist das jetzt noch nicht so vorgekommen, dass trotz mancher Unzulänglichkeiten oder sagen wir mal, Sachen, die einfach offen bleiben dabei, dass es wirklich in Projekten mal Alternativen dazu gibt.
Simon Kölsch Das ist natürlich immer schwer zu sagen: Nö, gibt es nicht. Und dann kramt irgendwer, irgendwo doch nochmal einen Link aus, wo es dann irgendwie so eine Alternative gibt. Ich muss aber sagen: Ich persönlich kenne keine. Es bleibt halt eben ein Framework mit dem ich Zugriff delegiere, habe dann quasi so eine Quasi-Standard für gewisse Teile und ich kenne keine… nichts Vergleichbares, was man an irgendeiner Stelle breit einsetzt, wo man sagen kann: Okay, das geht über “wir haben hier selbst eben Custom was umgesetzt” irgendwie hinaus und geht in eine Richtung Standardisierung. Also eventuell hat Stefan da noch etwas im Kopf, aber…
Stefan Bodewig Für den reinen Delegations-Fall eigentlich nicht. Das, was man eher findet ist für den Bereich, wo OpenID Connect dann OAuth 2.0 erweitert. Also für den Bereich SSO und vielleicht föderiertes Identity Management sogar, dass man da in andere Bereiche reingeht, da gibt es durchaus andere SSO Protokolle. Das dann auch sammelt so, was man vielleicht erwähnen könnte, was vielleicht ein Stück weit in den Delegations-Bereich mitgucken kann. Aber das ist eher auch tatsächlich für den SSO Fall gedacht und nicht für den reinen Delegationsweg, da fällt es mir so als Abfall Produkt raus. Was ich durchaus schon gesehen habe ist, dass man “wir machen da irgendwas Token basiertes”, im Projekt halt selber baut. Dass man nicht ein fertiges Framework hat, sondern man nimmt sich irgendwie diese Jobspezifikationen und baut irgendetwas selbst. Ob das eine gute Idee ist, ist fragwürdig.
Simon Kölsch Also an der Stelle, wenn wir selbst irgendwelche Dinge baut und da OAuth als Inspiration nimmt und plötzlich hat man halt eben ein Shot Token und das nennt man Access Token und dann noch so ein Refresh Token, weil irgendwie will man das Access Token verlängern, sollte man sich a) bewusst sein, dass man da kein OAuth baut, sondern Begrifflichkeiten aus der Spezifikation nimmt, die da halt irgendwie benutzt werden und das quasi ins eigene Projekt überträgt. Aber das bedeutet auch, man sollte da halt ganz genau hinschauen: Wie ist das denn eigentlich umgesetzt? Und habe ich hier einen Mehrwert und ist das halt eben eine gute Idee oder nicht eine gute Idee? Weil ein Vorteil, nur weil man halt eben einzelne Elemente aus der OAuth Spec nimmt, habe ich in dem Moment nicht. Und auch nochmal ganz explizit: Immer dann, wenn ich sowas wie ein Log-In baue mit OAuth, dann ist das falsch. Und genauso wie Stefan das gerade erwähnt hatte, es gibt eine ganze Reihe an Produkten und Alternativen zu OpenID Connect, die kann man sich dann gerne mal angucken und wird dann sehr schnell feststellen: Oh, das ist ganz schön viel. Das hat einen Grund, warum das nochmal so einen ziemlich großen Layer über OAuth 2.0 drüber liegt. Und selbst die OAuth Spec Autoren schreiben selbst: OAuth ist keine Lösung für Authentifizierung. Das ist Access Delegation.
Christoph Iserlohn Mit dem Stichwort gute Ideen habt ihr beide jetzt eine schöne Überleitung zu dem letzten Teil, den wir heute machen wollten, gegeben. Und da wir jetzt gelernt haben, dass OAuth wahrscheinlich relativ alternativlos ist, stellt sich mir halt die Frage und das hatten wir so ein bisschen halt im Vorgespräch gemerkt, dass das auch die Meinung da durchaus auseinander gehen, ob das denn so gut ist mit diesem ganzen OAuth. Also es hat am Anfang ja auch eine große Konfrontation auch gegeben oder Diskussion da drüber, von OAuth 1.0 zu OAuth 2.0. Und das hat Jahre gebraucht, bis das da ist. Der Simon erwähnte gerade, dass viele Begriffe da einfach so übernommen werden. Meines Erachtens ist es auch so, dass die so übernommen werden, weil so viele Unklarheiten da sind. Also ist die Frage: Sollte man das, wenn man so ein Framework entwickelt, so machen? Sollte man überhaupt so ein Framework für sowas entwickeln und nicht direkt eigentlich ein Protokoll, wie es in OAuth 1.0 war? Was ist da denn wohl der richtige Weg? Das ist natürlich immer sehr subjektiv, aber das würde ich gerne noch diskutieren.
Stefan Bodewig Ich glaube, wenn man sich anschaut, wer alles beteiligt gewesen ist an der Spezifikation für OAuth 2.0. Wenn man schaut, unten in den Danksagungen dankt er dann glaube ich die mehreren Dutzende aktiven Mitgliedern der Working Group, die an dieser Spezifikation gearbeitet hat. Und da sind diverse Firmen dabei gewesen, deren Interessen wahrscheinlich auch darin bestanden hat, Produkte, die sie hatten unter dem Label OAuth 2.0 anschließend vertreiben zu können. Also die Spezifikation vielleicht möglichst nicht scharf zu machen, damit man in der Lage ist ohne große Anpassungen die Produkte weiter betreiben oder verkaufen zu können. Halte ich für absolut illusorisch, dass man es hätte schaffen können in dieser Gruppe Konsens zusammen zu bekommen und ein festes Protokoll zu definieren. Also in dem historischen Kontext glaube ich, war es gar nicht möglich, mehr als das zu erreichen, was an Framework dagewesen ist und die Dinge offen zu lassen und sie dann in anderen Spezifikationen zu definieren. Die wahrscheinlich von weniger Leuten geschrieben worden sind. Ich glaube das ist ein ganz großes Problem einfach, die große Menge an Köchen, die versucht haben, einen Brei zu kochen in den OAuth 2.0 Framework. Auf der anderen Seite wäre es wahrscheinlich nicht so verbreitet gewesen, wenn nicht alle großen Player Google, Facebook, Twitter, Microsoft von Anfang an mit daran beteiligt gewesen wären. Ich glaube es wäre erheblich schwieriger geworden die Leute dazu zu bringen diese Spezifikation umzusetzen, wenn sie nicht von vornherein hätten mitsprechen dürfen.
Simon Kölsch Man könnte ja ganz provokant sagen: Bei Specs ist das ja auch immer so, dass da viele Leute zusammensitzen und Dinge versuchen zu Standardisieren. Aber natürlich hat sich bei uns auch einfach so die Landschaft im Internet verändert. Twitter bestimmt irgendwie nicht nur mit diesem Status Message Dienst, was auch immer, irgendwie Kommunikation, sondern so Unternehmen haben eben auch einen ganz großen Einfluss auf die technologische Entwicklung mit dem was wir da so arbeiten. Wenn Google morgen halt eben einen neuen Standard oder ein neues Protokoll einführt und Facebook und Twitter, dann hat das eine ganz andere Reichweite, wie wenn das eben, ich weiß nicht, nur eine Firma ist, die das in einem Teil von einem Produkt benutzt. Also da hat Stefan glaube ich Recht, das hätte nicht so eine breite Akzeptanz, wenn die sich nicht irgendwie zusammengesetzt hätten am Ende. Also wer hat denn OAuth 1.0 implementiert zum Beispiel? Kann man sich dann ja mal angucken. Das war dann auch eher nicht so verbreitet. Also ob das jetzt gut oder schlecht ist, dass wir überall OAuth 2.0 haben heutzutage, das ist eine andere Diskussion. Aber der Verbreitung hat das sicher irgendwie gutgetan.
Christoph Iserlohn Andererseits hat es natürlich auch sehr lange gedauert und Verbreitung hieß ja auch nicht unbedingt, dass die kompatibel sind. Selbst heute ist es ja nicht immer kompatibel, wenn ich mir einen Keyclloak hole und dann vielleicht eine andere Bibliothek als Client Bibliothek benutze, was weiß ich aus dem Spring Umfeld oder es ist auch egal, was dann ist in den Projekten, in denen ich jetzt so gewesen bin, immer das Bangen da: Funktionieren die denn zusammen? Da muss man erstmal immer einen PoC machen und das ist halt für mich zum Beispiel sowas, wo ich sagen würde: Das ist jetzt nicht die Erwartung an so ein weit verbreitetes Protokoll. Beziehungsweise das ist ja gar kein Protokoll, sondern das ist ja nur ein Framework und stellt sich für mich die Frage, ob man solche Frameworks überhaupt über eine RFC definieren müsste oder ob das nicht einfach im Protokoll noch vorbehalten sein sollte. Also da ist der Mehrwert nicht immer ganz klar und andererseits hat es halt auch verhindert, was du gerade gesagt hast, was aber auch eine andere Diskussion ist: Ob es nicht Alternativen geben würde. Also ob es nicht besser wäre, wenn man mehrere Alternativen hätte und sich dann davon eine durchgesetzt hätte oder zwei oder drei, ich weiß das auch nicht, aber…
Simon Kölsch Ja, ich weiß nicht… Für mich die Kritik, die ich vielleicht in Kombination mit OAuth habe, ist gar nicht so sehr an OAuth selbst. Also ja, die Spec ist so ein eigenes Thema für sich und wie da Dinge definiert sind und ist vor allem tierisch komplex. Also man darf da nicht erwarten, dass es ein Thema ist, mit dem man sich mal eine Woche befasst und dann hat man das irgendwie durchdrungen und verstanden. Also mir ist das zumindest nicht gelungen in der Zeit. Sondern wie damit halt eben umgegangen wird. Also was ich in der Projektpraxis wahrnehme ist, man baut neue Software Systeme und sagt dann: Ja, haltet euch mal an Standards. Standards sind gut, wollen wir haben. Also nehmt ihr mal OAuth 2.0 für alles was da irgendwie mit Zugriff zu tun hat und dann implementieren irgendwie 20 Leute OAuth 2.0 oder Teile davon und verstehen bis zum Ende gar nicht so richtig in der Tiefe, was sie da eigentlich tun. Und manchmal wäre es vielleicht gar nicht notwendig so eine Access Delegationsprotokoll einzuführen, sondern könnten wir das eben auf viel pragmatischere Art und Weise trotzdem sicher gut umsetzen und hätte wesentlich weniger Komplexität dabei irgendwie mit im Softwareprodukt drinnen. Also so diese pauschale: Hier nehmt mal OAuth 2.0 plus oft verbunden mit irgendeinem Produkt oder so, sorgt find ich oft für mehr Probleme als es denn eigentlich löst.
Stefan Bodewig Ganz häufig braucht man auch diesen Delegationsfall gar nicht, dass man eigentlich eben nur ein Autorisierungsprotokoll benötigt, aber kein Delegationsprotokoll.
Simon Kölsch Genau. Also OAuth ist für das Internet, ja. Das sind diese Parteien oder diese drei Rollen, der Client, der Benutzer irgendwo und irgendwie Resource Auth Server, die vertrauen sich alle untereinander nicht und das wollen wir irgendwie lösen. Und da ist die Frage, ob wir dieses Problem in so einem Standard Unternehmensumfeld wirklich haben oder ob man das, wie Stefan sagt, diese Delegation an der Stelle gar nicht hat, weil die Third Party der Client dem vertraue ich trotzdem, weil das gehört zu meinem Unternehmen.
Christoph Iserlohn Ja, da ist dann halt wieder das Problem, dass das halt doch in der Praxis weit eingesetzt wird und es auch, wie wir vorhin festgestellt haben, vielleicht wenig Alternativen gibt. Vielleicht liegt es auch daran, weil der Use Case dann einfach auch nicht unbedingt der richtige ist. Also wir werden ja noch in einer weiteren Folge über OpenID Connect sprechen und über SSO. Das ist ja wahrscheinlich auch oft ein Use Case, den die Firmen eigentlich haben wollen. Aber trotzdem, ich fand es bemerkenswert, was du gerade gesagt hast, Simon, dass halt das sehr komplex ist und man kann sich da nicht mal mit so eben beschäftigen und wir haben ja gesehen es gibt x RFCs, die da eine Rolle spielen. Und genau das ist da ein ganz großes Problem, denn eigentlich will ich ja bei allen Sachen, die die Security betreffen und das ist bei der Autorisierung ja auf jeden Fall so, möglichst wenig Komplexität haben und dann die Spec sozusagen anzufangen mit: Wir decken schonmal 25 Use Cases ab, die möglicherweise eine Rolle spielen. Das finde ich halt eigentlich völlig schräg. Also OAuth 2.0 ist ja eigentlich so aus dieser Pragmatik entstanden, da war halt der Use Case da und der wurde auch abgedeckt und so weiter.
Simon Kölsch 1.0 meintest du jetzt?
Christoph Iserlohn Mir kam es zwar jetzt so vor, dass…
Simon Kölsch Eben hast du OAuth 2.0 gesagt, dass das aus der Pragmatik… Du meintest 1.0.
Christoph Iserlohn Ich meinte natürlich OAuth 1.0, ist aus der Pragmatik entstanden, aus dem Use Case, den Twitter da damals sozusagen hatte. Und OAuth 2.0 hat halt schonmal sozusagen präventiv alles Mögliche versucht abzudecken und hat dann halt Jahre gebraucht, also um sozusagen einen nutzbaren Stand zu haben. Beziehungsweise einen Stand, der nutzbar ist mit Produkten von zwei verschiedenen Herstellern. Du hast das so im Vorgespräch auch schön mal erwähnt, dass man eine Feature Matrix braucht für das, was man einsetzen will und dann erstmal abgleichen will: wer unterstützt denn was? Und kann ich das entsprechend machen? Ich hatte das vorher auch erwähnt, dass in vielen Projekten halt erstmal ein PoC gemacht werden muss. Und ich bin da nicht so sicher, ob das… Also ich meine, da ist jetzt sozusagen das Kind schon in den Brunnen gefallen. Also wir werden OAuth jetzt ja auch nicht direkt wieder ablösen durch irgendetwas anderes, durch den weiteren Standard, den dann keiner nutzt. Aber dass man vielleicht in Zukunft immer bei sowas im Hinterkopf haben sollte, dass man vielleicht von der anderen Seite das Pferd aufzäumt, sondern dann sagt: Okay, wir gehen jetzt mal aus der Pragmatik heraus und nicht aus der… Wir haben halt X Use Cases und was Stefan noch erwähnte, 50 Hersteller, die vielleicht ihr Produkt da vermarken wollen. Das wollte ich einfach nochmal erwähnt haben, dass man das vielleicht schaut, dass man das in Zukunft anders macht. Auch wenn wir drei wahrscheinlich überhaupt gar keine Möglichkeiten haben solche Entwicklungen irgendwie zu beeinflussen. So, schönes langes Schlusswort von mir. Wenn ihr nicht noch jetzt etwas ganz Wichtiges habt was euch eingefallen ist, was wir vergessen haben, dann müsstet ihr euch kurz bemerkbar machen. Das ist nicht der Fall. Dann würde ich sagen, schließen wir diesen Podcast hiermit. Dann sage ich vielen Dank, Stefan! Vielen Dank, Simon! Für eure Zeit und für eure ganze Fachexpertise. Ich danke den Zuhörer*innen und wenn ihr Anmerkungen habt, Ergänzungen, Korrekturen oder auch Vorschläge, welche Themen wir in Zukunft in dem Security Podcast behandeln sollen, dann schreibt uns doch eine Mail an [email protected]. Und wenn euch das gefallen hat, könnt ihr uns eine gute Bewertung geben und damit sage ich: Bis zum nächsten Mal! Ciao Stefan, ciao Simon!
Simon Kölsch Macht es gut, ciao!
Stefan Bodewig Tschüss!