In deze blogpost wil ik je een overzicht geven van de OAuth 2 specificatie. Toen ik me hierin begon te verdiepen, verdwaalde ik al snel in alle verschillende aspecten. Om ervoor te zorgen dat jij niet hetzelfde hoeft te doen, zal ik OAuth 2 uitleggen alsof je niet eens een technische achtergrond hebt. Omdat er veel te behandelen valt, laten we er meteen in springen!
Als het gaat om het beveiligen van een applicatie, zijn er 2 kernconcepten die je in gedachten moet houden:authenticatie en autorisatie.
Met authenticatie probeer je de vraag "Wie is iemand?" of "Wie is deze gebruiker?" te beantwoorden. Je moet het bekijken vanuit het perspectief van je applicatie of je server. Ze hebben in principe vreemdelingengevaar. Ze weten niet wie je bent en er is geen manier voor hen om dat te weten tenzij je je identiteit aan hen bewijst.Authenticatie is dushet proces om aan de applicatie te bewijzen dat je bent wie je beweert te zijn.
In een voorbeeld uit de echte wereld is dit het verstrekken van je ID of paspoort aan de politie wanneer ze je aan de kant zetten om jezelf te identificeren. Authenticatie is geen onderdeel van de standaard OAuth 2 specificatie. Er is echter een uitbreiding op de specificatie genaamdOpen ID Connect die dit onderwerp behandelt.
Autorisatie is de keerzijde van authenticatie. Zodra een gebruiker heeft bewezen wie hij is,moet de applicatie uitzoeken wat een gebruiker mag doen. Dat is in wezen wat het autorisatieproces doet.
Een eenvoudige manier om hierover na te denken is het volgende voorbeeld. Als je een leraar bent op een school, heb je toegang tot informatie over de leerlingen in je klas. Als je echter de directeur van de school bent, heb je waarschijnlijk toegang tot de gegevens vanalle leerlingen van de school. Je hebt een grotere toegang vanwege je functie.
Om OAuth 2 volledig te begrijpen, moet je je bewust zijn van de volgende 4 actoren die de specificatie vormen:
Zoals eerder leggen we het uit met een heel eenvoudig voorbeeld om te zien hoe het echt werkt.
Laten we zeggen dat je een jas hebt. Omdat je de eigenaar bent van die jas, ben je deeigenaar van de bron en de jas is debron die je wilt beschermen. Je wilt het jasje opbergen in een kluisje om het veilig te bewaren. Het kastje zal fungeren als deResource Server. Je bent geen eigenaar van de Resource Server, maar hij bewaart je spullen voor je. Omdat je wilt voorkomen dat het jasje door iemand anders wordt gestolen, moet je een slot op het kastje zetten. Dat slot is deautorisatieserver. Deze regelt de beveiligingsaspecten en zorgt ervoor dat alleen jij toegang hebt tot de jas of mogelijk iemand anders die jij toestemming geeft. Als je wilt dat je vriend je jasje uit het kastje haalt, dan kan die vriend gezien worden als deClient of Applicatie actor in de OAuth flow. DeClient handelt altijd namens de gebruiker.
Het volgende concept waar je veel over zult horen is tokens. Er zijn verschillende soorten tokens, maar ze zijn allemaal heel eenvoudig te begrijpen. De 2 soorten tokens die je het meest tegenkomt zijnaccess tokens en refresh tokens.
Als het gaat om toegangsmunten, heb je misschien wel eens gehoord van JWT-tokens, tokens aan toonder of opake tokens. Dat zijn eigenlijk alleen maar implementatiedetails die ik in dit artikel niet ga behandelen.
In essentie is een toegangstoken iets dat je aan de resource server geeft om toegang te krijgen tot de items die hij voor je bewaart. Je kunt toegangsmunten bijvoorbeeld zien als papieren kaartjes die je op de kermis koopt. Als je in een attractie wilt stappen, laat je je ticket zien aan de persoon in het hokje en die laat je instappen. Je maakt een ritje en na afloop verloopt je ticket. Belangrijk om te weten is datwie het token heeft, eigenaar is van het token. Wees er dus heel voorzichtig mee. Als iemand anders je token in handen krijgt, kan hij of zij namens jou toegang krijgen tot je items!
Refresh tokens lijken erg op access tokens. In wezen gebruik je ze om meer toegangsmunten te krijgen. Toegangsmunten hebben meestal een korte levensduur, maar verversingsmunten hebben vaak een langere vervaldatum. Om terug te komen op ons kermisvoorbeeld, een verversingstoken zou de creditcard van je ouders kunnen zijn die kan worden gebruikt om meer kermiskaartjes te kopen die je kunt uitgeven aan attracties.
Het volgende concept dat we behandelen zijn scopes. Een scope is in feite een beschrijving van dingen die een persoon kan doen in een applicatie. Je kunt het zien als een functie in het echte leven (bijvoorbeeld een directeur of leraar op een middelbare school). Bepaalde scopes geven je meer rechten dan andere.
Ik weet dat ik zei dat ik niet in technische details zou treden, maar als je bekend bent met Spring Security, dan kun je scopes vergelijken met wat Spring Security rollen noemt. Een scope komt één op één overeen met het concept van een rol.
De OAuth specificatie specificeert niet hoe een scope eruit moet zien, maar vaak zijn het punt-gescheiden Strings zoalsblog.write. Google daarentegen gebruikt URL's als scope. Als voorbeeld: om alleen-lezen toegang tot iemands agenda toe te staan, geven ze de scopehttps://www.googleapis.com/auth/calendar.readonly.
Types van toekenningen zijn typisch waar dingen verwarrend beginnen te worden voor mensen. Laten we beginnen met het tonen van de meest gebruikte grant types:
Client Credentials is een type toekenning dat vaak wordt gebruikt als 2 back-end diensten op een veilige manier met elkaar moeten communiceren.
De volgende is het grant typeAuthorization Code, wat waarschijnlijk het moeilijkste grant type is om volledig te begrijpen. Je gebruikt dit type grant wanneer je gebruikers wilt laten inloggen via een browsergebaseerd aanmeldformulier. Als je ooit de knop 'Log in met Facebook ' of 'Log in met Google' op een website hebt gebruikt, dan heb je zonder het te weten al een autorisatiecodestroom ervaren!
De volgende is het toestemmingscodetype , dat vrij nieuw is in de OAuth 2-scene. Het wordt meestal gebruikt op apparaten met beperkte invoermogelijkheden, zoals een TV. Als je bijvoorbeeld wilt inloggen op Netflix, in plaats van je gebruikersnaam en wachtwoord op te geven, verschijnt er een link met een code die je moet invullen met de mobiele app.
HetRefresh grant type gaat meestal hand in hand met de Authorization Code flow. Omdat toegangstokens een korte levensduur hebben, wil je niet dat je gebruikers telkens moeten inloggen als het toegangstoken verloopt. Dus is er deze refresh flow die refresh tokens gebruikt om nieuwe access tokens te verkrijgen wanneer ze bijna verlopen zijn.
De laatste 2 toekenningsvormen zijnWachtwoord en Impliciet. Deze toekenningsvormen zijn minder veilige opties die niet worden aanbevolen bij het bouwen van nieuwe applicaties. We zullen ze kort behandelen in de volgende sectie, waarin de bovenstaande toekenningsvormen in meer detail worden uitgelegd.
Een autorisatiestroom bevat een of meer stappen die moeten worden uitgevoerd om een gebruiker te autoriseren door het systeem. Er zijn 4 autorisatiestromen die we zullen bespreken:
De Client Credentials stroom is de eenvoudigste stroom om te implementeren. Het werkt ongeveer hetzelfde als hoe een traditionele gebruikersnaam/wachtwoord login werkt.Gebruik deze flow alleen als je de client/applicatie kunt vertrouwen, omdat de client credentials worden opgeslagen binnen de applicatie. Gebruik dit niet voor single page apps (SPA's) of mobiele apps, omdat kwaadwillende gebruikers de app kunnen deconstrueren om de credentials te bemachtigen en deze te gebruiken om toegang te krijgen tot beveiligde bronnen. In de meeste use cases wordt deze flow gebruikt om veilig te communiceren tussen 2 back-end systemen.
Hoe werkt de Client Credentials stroom? Elke applicatie heeft een client ID en secret die geregistreerd zijn op de autorisatieserver. De applicatie presenteert deze aan de autorisatieserver om een toegangstoken te krijgen en gebruikt het om de beveiligde bron van de resource server te krijgen. Als op een bepaald moment het toegangstoken verloopt, herhaalt hetzelfde proces zich om een nieuw token te krijgen.
De Password flow lijkt erg op de Client Credentials flow, maar is erg onveilig omdat er een 3e actor bij betrokken is, namelijk een daadwerkelijke eindgebruiker. In plaats van een veilige client die we vertrouwen die een ID en geheim aan de autorisatie provider presenteert, hebben we nu een gebruiker die met een client 'praat'. In een Password flow geeft de gebruiker zijn persoonlijke gegevens aan de client. De client gebruikt deze gegevens om toegangstokens te krijgen van de autorisatieserver. Dit is de reden waarom een Password flow niet veilig is, omdatwe er absoluut zeker van moeten zijn dat we kunnen vertrouwen dat de client de credentials niet misbruikt voor kwaadaardige redenen.
Uitzonderingen waarbij deze flow nog steeds gebruikt zou kunnen worden zijn commandoregelapplicaties of bedrijfswebsites waarbij de eindgebruiker de client-apps moet vertrouwen die hij dagelijks gebruikt. Maar afgezien hiervan wordt het niet aanbevolen om deze flow te implementeren.
Dit is de stroom die je zeker wilt begrijpen, omdat het de stroom is die het meest wordt gebruikt bij het beveiligen van applicaties met OAuth 2. Deze stroom is iets gecompliceerder dan de eerder besproken stromen. Het is belangrijk om te begrijpen datdeze flow vertrouwelijk, veilig en browsergebaseerd is.
De flow werkt door veel HTTP redirects te maken, daarom is een browser een belangrijke speler in deze flow. Er is ook een back-channel verzoek (zo genoemd omdat de gebruiker niet betrokken is bij dit deel van de stroom) waarbij de client of applicatie rechtstreeks met de autorisatieserver praat. In deze flow moet de gebruiker meestal de scopes of rechten goedkeuren die aan de applicatie worden toegekend. Een voorbeeld hiervan is een applicatie van derden die vraagt of je toegang mag krijgen tot je Facebook-profielfoto nadat je bent ingelogd met de knop 'Aanmelden met Facebook'.
Laten we de Autorisatiecode-flow toepassen op ons voorbeeld 'jas in de kast' om een beter begrip te krijgen.
Onze jas ligt in de kast en we willen hem uitlenen aan een vriend. Onze vriend gaat naar het (hightech) kluisje. Het kastje belt ons, want wij zijn de Resource Owner. Deze oproep is een van die redirects waar we het eerder over hadden. Op dit punt maken we een beveiligde verbinding met het kastje, dat fungeert als een autorisatieserver. We kunnen nu veilig onze referenties geven om toestemming te geven om het slot te ontgrendelen. De autorisatieserver verstrekt vervolgens een tijdelijke code, de OAuth-code, aan onze vriend. De vriend gebruikt vervolgens die OAuth-code om een toegangscode te verkrijgen om het kastje te openen en mijn jas te pakken.
Deimpliciete flow is in principe hetzelfde als de autorisatiecode flow, maar dan zonder de tijdelijke OAuth code. Dus na het inloggen stuurt de autorisatieserver direct een toegangstoken terug zonder dat er een back-channelverzoek nodig is. Dit is minder veilig, omdat het token onderschept kan worden via een man-in-the-middle aanval.
OAuth 2 kan er in eerste instantie ontmoedigend uitzien vanwege alle verschillende actoren die erbij betrokken zijn. Hopelijk begrijp je nu beter hoe ze met elkaar samenwerken. Met deze kennis in je achterhoofd is het veel gemakkelijker om de technische details te begrijpen als je je er eenmaal in begint te verdiepen.