Het kiezen van een SSO-strategie: SAML vs OAuth2
De kans is groot dat je wel eens op een applicatie (mobiele app of web app) hebt ingelogd door op een ‘Log in met Facebook’ knop te klikken. Als u Spotify, Rdio of Pinterest gebruikt, dan weet u waar ik het over heb.
Als gebruiker maakt het u waarschijnlijk niet uit hoe SSO werkt. Je wilt gewoon een applicatie gebruiken en mag dankbaar zijn voor een soepelere ervaring en dat je minder logins en wachtwoorden hoeft te onthouden.
Om een gebruiker een single sign on ervaring te bieden moet een ontwikkelaar een SSO oplossing implementeren. In de loop der jaren zijn er veel pogingen gedaan om SSO te realiseren, maar dit artikel gaat zich richten op een vergelijking tussen SAML en OAuth2 – een recent onderzoek dat wij hebben uitgevoerd (gelukkig zonder kleerscheuren, maar met een hoop informatie).
Onze behoefte aan SSO
We werken aan een platform dat verschillende client applicaties zal hebben. Sommige van deze applicaties zullen web-based zijn, andere zullen native zijn, zoals mobiele apps.
Dit platform zal toegankelijk zijn voor een paar verschillende clients (eigendom van verschillende organisaties).
Het platform is een front-end voor een groot bedrijfssysteem dat al beschikt over identiteitsgegevens van de mensen die ermee werken. In plaats van elke client applicatie zijn eigen gebruikersdatabase met gebruikersnamen en wachtwoorden te laten onderhouden, lijkt het beter om SSO te gebruiken.
Single sign on zou het bedrijfssysteem in staat stellen om alle gebruikersgegevens veilig op te slaan en te bezitten. Het platform kan een vertrouwensrelatie opbouwen met de authenticatieserver van de onderneming en client-applicaties kunnen worden gebouwd om de vertrouwde authenticatieserver te gebruiken om gebruikers te authenticeren.
Het was ons doel om een SSO-strategie en -implementatie te vinden die aan deze behoeften kon voldoen.
Enter SAML 2.0
We hebben oorspronkelijk gekeken naar SAML 2.0, een set open standaarden, waarvan er één specifiek is ontworpen voor SSO.
De SAML 2.0 specificatie (voortaan SAML) biedt een Web Browser SSO Profile dat beschrijft hoe single sign on kan worden bereikt voor web apps. Er zijn drie hoofdrolspelers in SAML:
SAML en OAuth2 gebruiken vergelijkbare termen voor vergelijkbare concepten. Ter vergelijking staat de formele SAML-term vermeld met het OAuth2-equivalent tussen haakjes.
-
Service Provider (Resource Server) – dit is de web-server waarop u probeert toegang te krijgen tot informatie.
-
Client – dit is de manier waarop de gebruiker interactie heeft met de Resource Server, zoals een webapp die via een webbrowser wordt aangeboden.
-
Identity Provider (Autorisatieserver) – dit is de server die eigenaar is van de identiteiten en geloofsbrieven van de gebruiker. De gebruiker verifieert zich bij deze server.
De meest voorkomende SAML-flow wordt hieronder weergegeven:
Hier volgt een fictief scenario dat bovenstaand diagram beschrijft:
-
A – een gebruiker opent zijn web-browser en gaat naar MyPhotos.com, waar al zijn foto’s worden opgeslagen. MyPhotos.com regelt de verificatie niet zelf.
-
B – om de gebruiker te verifiëren stelt MyPhotos.com een SAML Authnrequest op, ondertekent het, versleutelt het optioneel en codeert het. Daarna wordt de webbrowser van de gebruiker doorgestuurd naar de Identidy Provider (IdP) om de authenticatie uit te voeren. De IdP ontvangt het verzoek, decodeert het, ontcijfert het indien nodig en verifieert de handtekening.
-
C – Met een geldig Authnrequest presenteert de IdP de gebruiker een inlogformulier waarin deze zijn gebruikersnaam en wachtwoord kan invoeren.
-
D- Zodra de gebruiker heeft ingelogd, genereert de IdP een SAML-token dat identiteitsinformatie over de gebruiker bevat (zoals zijn gebruikersnaam, e-mail, enz.). De Id neemt het SAML-token en stuurt de gebruiker terug naar de dienstverlener (MyPhotos.com).
-
E – MyPhotos.com verifieert het SAML-token, ontcijfert het indien nodig en haalt er identiteitsinformatie over de gebruiker uit, zoals wie hij is en wat zijn eventuele rechten zijn. MyPhotos.com logt de gebruiker nu in op zijn systeem, vermoedelijk met een soort cookie en een sessie.
Aan het eind van het proces kan de gebruiker als ingelogde gebruiker met MyPhotos.com communiceren. De gegevens van de gebruiker zijn nooit doorgegeven aan MyPhotos.com, alleen aan de Identity Provider.
Er zijn meer details te vinden in het bovenstaande diagram, maar dit is op hoofdlijnen wat er gebeurt.
Toen we voor het eerst kennismaakten met SAML, kwam de term “SAML token” steeds weer terug. Het is eigenlijk geen term in de SAML spec, maar mensen bleven hem gebruiken, en de betekenis was ongrijpbaar.
Nu blijkt dat de term “SAML token” een informele manier is om naar de SAML Assertion te verwijzen, vaak gecomprimeerd, gecodeerd, mogelijk versleuteld, en het ziet er meestal uit als kletskoek. En een SAML Assertion is gewoon een XML node met bepaalde elementen.
SAML’s Native App Limitation
SAML ondersteunt de concepten van bindings. Dit zijn in wezen de middelen waarmee de Identity Provider de gebruiker terugleidt naar de Service Provider. Bijvoorbeeld, in stap D hierboven wordt de gebruiker teruggestuurd naar MyPhotos.com, maar hoe?
De twee relevante types van bindingen zijn de HTTP Redirect en de HTTP POST binding zoals gedefinieerd in de SAML 2.0 spec. De HTTP Redirect binding zal een HTTP Redirect gebruiken om de gebruiker terug te sturen naar de Service Provider, in het geval van ons voorbeeld: MyPhotos.com.
De HTTP Redirect binding is prima voor korte SAML berichten, maar het wordt afgeraden deze te gebruiken voor langere berichten zoals SAML assertions. Uit wikipedia:
Langere berichten (bijvoorbeeld berichten die ondertekende SAML-asserties bevatten) moeten via andere bindingen worden verzonden, zoals de HTTP POST Binding.
De aanbevolen manier om een HTTP POST te gebruiken heeft zijn eigen eigenaardigheden. De SAML-specificatie beveelt bijvoorbeeld aan dat stap D hierboven een HTML-formulier weergeeft waarbij de actie terugverwijst naar de Service Provider.
Je kunt de gebruiker op een andere knop laten klikken om dat formulier te verzenden of je kunt JavaScript gebruiken om het verzenden van het formulier te automatiseren. Waarom moet er een formulier worden ingediend? Naar mijn mening laat SAML 2.0 zijn leeftijd zien (circa 2005), omdat het formulier hier alleen bestaat zodat een HTTP POST gebruikt kan worden om het SAML token terug te sturen naar de Service Provider.
Dit is een probleem als de client geen web-gebaseerde applicatie is, maar een native applicatie, zoals een mobiele app. Laten we bijvoorbeeld zeggen dat we de MyPhotos iPhone-app hebben geïnstalleerd. We openen de app, en hij wil dat we ons authenticeren bij de Identity Provider. Zodra we ons hebben geauthenticeerd, moet de Identity Provider het SAML token terugsturen naar de MyPhotos-app.
De meeste mobiele applicaties kunnen worden gestart via een aangepaste URI, zoals “my-photos://authenticate”, en vermoedelijk stuurt de Identity Provider het formulier dat het SAML token bevat naar die URL. Onze MyPhotos-app wordt gestart, maar we zijn niet ingelogd. Wat is er aan de hand?
Mobiele apps hebben geen toegang tot de HTTP POST body. Ze hebben alleen toegang tot de URL die wordt gebruikt om de applicatie te starten. Dit betekent dat we het SAML token niet kunnen lezen.
Op Android: een applicatie starten vanaf een url met behulp van Intents.
Op iOS: een applicatie starten door een custom URI schema te registreren.
Geen SAML token, geen geauthenticeerde gebruiker.
Working Around SAML’s HTTP POST Binding
De beperking van de HTTP POST binding voor native mobiele apps kan worden omzeild. Je kunt bijvoorbeeld embedded web views gebruiken, waarin je aangepaste code schrijft om het hele authenticatieproces te volgen. Helemaal aan het eind van het proces schraap je de HTML van de pagina en haalt daar het SAML-token uit.
Een tweede workaround is om een proxyserver te implementeren die de HTTP POST kan ontvangen, het SAML-token eruit kan halen, en dan een URL kan maken die het SAML-token bevat (bijvoorbeeld: “myphotos://authenticate/?SAMLRequest=asdfsdfsdf”) De proxyserver kan dan een HTTP Redirect gebruiken om het apparaat de MyPhotos-app te laten openen. En omdat het SAML-token deel uitmaakt van de URL, kan de MyPhotos-app het eruit halen en gebruiken om in te loggen.
Een derde workaround zou zijn om de aanbeveling in de specificatie om de HTTP Redirect-binding niet te gebruiken, te negeren. Dat is erg verleidelijk, maar het is moeilijk om het gevoel van je af te schudden dat je je in een mijnenveld begeeft, in de hoop dat je niet één verkeerde stap zet.
Een andere benadering, waarbij workarounds helemaal worden vermeden, is om niet op SAML te vertrouwen, maar naar een andere benadering te kijken, zoals OAuth 2.0.
Enter OAuth 2.0
In tegenstelling tot SAML, is OAuth 2.0 (voortaan OAuth2), een specificatie waarvan de inkt nog maar net is opgedroogd (circa eind 2012). Het heeft het voordeel dat het recent is en rekening houdt met hoe de wereld in de afgelopen acht jaar is veranderd.
Mobiele apparaten en native applicaties zijn tegenwoordig gangbaar op manieren die SAML in 2005 niet kon voorzien.
De basisspelers met OAuth2 zijn:
SAML en OAuth2 gebruiken vergelijkbare termen voor vergelijkbare concepten. Ter vergelijking is de formele OAuth2-term opgesomd met het SAML-equivalent tussen haakjes.
-
Resource Server (Service Provider) – dit is de webserver waarop u probeert toegang te krijgen tot informatie.
-
Client – dit is de manier waarop de gebruiker interactief is met de Resource Server. Dit kan een browsergebaseerde webapp zijn, een native mobiele app, een desktop-app, een server-side app.
-
Authorization Server (Identity Provider) – dit is de server die eigenaar is van de identiteiten en geloofsbrieven van de gebruiker. De gebruiker verifieert en autoriseert zich bij deze server.
Op een hoog niveau verschilt de OAuth2-stroom niet veel van de eerdere SAML-stroom:
Laten we eens door hetzelfde scenario lopen dat we eerder met SAML hebben doorlopen:
-
A – een gebruiker opent zijn webbrowser en gaat naar MyPhotos.com, waar al zijn foto’s worden opgeslagen. MyPhotos.com regelt de authenticatie niet zelf, dus wordt de gebruiker doorgestuurd naar de autorisatieserver met een verzoek om autorisatie. De gebruiker krijgt een aanmeldingsformulier te zien en wordt gevraagd of hij of zij de Resource Server (MyPhotos.com) toestemming wil geven om namens hem of haar te handelen. De gebruiker meldt zich aan en wordt teruggeleid naar MyPhotos.com.
-
B – de client ontvangt als onderdeel van de omleiding een code waarmee toestemming wordt verleend en geeft deze code vervolgens door aan de client.
-
C – de klant gebruikt deze code om een token aan te vragen bij de autorisatieserver.
-
D – als de code voor de autorisatieserver geldig is, dan verleent de autorisatieserver een token. Het toegangstoken wordt vervolgens door de client gebruikt om bronnen aan te vragen bij de Resource Server (MyPhotos.com).
-
E – MyPhotos.com ontvangt het verzoek om een bron en ontvangt het toegangstoken. Om er zeker van te zijn dat het een geldig token is, stuurt het het token rechtstreeks naar de autorisatieserver om het te valideren. Als het token geldig is, stuurt de Authorization Server informatie over de gebruiker terug.
-
F – nadat het verzoek van de gebruiker is gevalideerd, stuurt MyPhotos.com de gevraagde bron terug naar de gebruiker.
Dit is de meest voorkomende OAuth2-stroom: de autorisatiecode-stroom. OAuth2 biedt nog drie andere flows (of wat ze authorization grants noemen) die werken voor iets andere scenario’s, zoals single page javascript apps, native mobiele apps, native desktop apps, traditionele web apps, en server-side applicaties waarbij een gebruiker niet direct betrokken is, maar die jou toestemming heeft gegeven om namens hem iets te doen.
Het grote voordeel van OAuth2 flows is dat de communicatie van de autorisatieserver terug naar de client en de resourcingserver verloopt via HTTP Redirects met de token-informatie als queryparameters. OAuth2 gaat er ook niet van uit dat de Client een web-browser is, terwijl het standaard SAML Web Browser SSO Profile dat wel doet.
Native mobiele applicaties zullen gewoon out of the box werken. Geen workarounds nodig.
OAuth2’s Favoriete Zin: Out of Scope
De OAuth2 specificatie schrijft niet voor hoe de communicatie tussen de Resource Server en de Authorization Server werkt in een heleboel situaties, zoals het valideren van een token. Het zegt ook niets over welke informatie over de gebruiker moet worden geretourneerd of in welk formaat.
Er zijn nogal wat plekken waar de OAuth2 specificatie stelt dat dingen “buiten de scope van deze specificatie vallen.” Dit heeft geleid tot kritiek op de OAuth2 spec, omdat het veel dingen overlaat aan de implementatie, wat zou kunnen leiden tot incompatibele implementaties op een bepaald punt.
OAuth2, is nog steeds erg jong, en het heeft al wijdverspreide adoptie met de wil van Google, Facebook, Salesforce, en Twitter om er een paar te noemen. De ware schoonheid van OAuth2 is echter zijn eenvoud. In feite vult het OpenID Connect Basic Profile, dat voortbouwt op OAuth2, enkele gebieden in die de OAuth2 spec zelf niet definieert.
OAuth2: Standaard geen digitale handtekening nodig
OAuth2 vereist standaard geen ondertekening van berichten. Als je dat wilt toevoegen, voel je vrij, maar out of the box, de spec werkt zonder. Het schrijft wel voor dat alle verzoeken over SSL/TLS moeten gaan.
Dit heeft in het verleden voor commotie gezorgd:
- OAuth 2.0 (zonder handtekeningen) is slecht voor het web
- OAuth 2.0 en de weg naar de hel
- OAuth 2.0 is slecht voor het web
- .0 en de weg naar de hel
Het werken met OAuth2 en OAuth1 in het verleden, kan ik zeggen dat OAuth2 veel eenvoudiger is dan OAuth1 (en plezieriger om mee te werken). Interoperabiliteit en automatische ontdekking van services kunnen in de toekomst nuttig zijn, maar op dit moment is het niet iets waar we naar op zoek zijn.
We zullen misschien gevraagd worden om berichten te ondertekenen zodra het security team van de onderneming de definitieve audit van de OAuth2 implementatie doet, maar voor nu past OAuth2 op een meer gestandaardiseerde manier bij onze huidige doelen dan SAML. Het is ook veel eenvoudiger.
Als elke applicatie een beveiligde web-server heeft, dan werkt het ondertekenen prima, maar als dat niet het geval is, wordt het probleem genuanceerder. Hoe sla je je sleutels veilig op in de browser voor browser-gebaseerde JS apps of in native mobiele apps?
Als je iOS en Android apps gaat decompileren, zinkt je hart. Je sleutels zijn echt niet zo veilig als je het apparaat niet kunt bezitten en beveiligen.
OAuth2 is voor autorisatie, niet voor authenticatie
De “auth” in OAuth staat inderdaad voor “autorisatie” en niet voor “authenticatie”. De pedant in u lacht misschien. Je hebt me te pakken!
Maar – ja, er is altijd een maar! Ook al is de term OAuth vrij recent, het feit dat “auth” autorisatie betekende lijkt een beetje anachronistisch. Het wordt al gebruikt om SSO in het wild te bereiken (dankzij Facebook, Twitter, Salesforce en Google en duizenden sites die ze gebruiken voor het authenticeren en autoriseren van gebruikers).
De grootste klacht die ik heb gezien is het gebrek aan voorschrift en de overvloedige “out of scope” toepassingen in de OAuth2 spec. Het feit dat het OpenID Connect Basic Profile direct bovenop OAuth2 is gebouwd, zou genoeg moeten zijn om de mythe te ontkrachten dat OAuth2 niet voor authenticatie kan worden gebruikt.
Wat een woord zes jaar geleden betekende, is veel minder belangrijk dan wat het vandaag de dag kan omvatten.
Samenvatting
SAML heeft één eigenschap die OAuth2 mist: het SAML token bevat de identiteitsinformatie van de gebruiker (vanwege ondertekening). Met OAuth2 krijg je die informatie niet uit de doos, en in plaats daarvan moet de Resource Server een extra ronde maken om het token te valideren met de Authorization Server.
Aan de andere kant, met OAuth2 kun je een access token op de Authorization Server ongeldig maken, en deze uitschakelen van verdere toegang tot de Resource Server.
Beide benaderingen hebben mooie features en beide zullen werken voor SSO. We hebben beide concepten bewezen in meerdere talen en verschillende soorten applicaties. Uiteindelijk lijkt OAuth2 beter te passen bij onze behoeften (omdat er geen bestaande SAML-infrastructuur is die we kunnen gebruiken).
OAuth2 biedt een eenvoudiger en meer gestandaardiseerde oplossing die al onze huidige behoeften dekt en het gebruik van workarounds voor interoperabiliteit met native applicaties vermijdt.
Als dit zich begint te ontvouwen en we met verschillende beveiligingsteams werken, zullen we zien in hoeverre dit standhoudt.
Tot nu toe, zo goed.