De complete gids voor het integreren van een OIDC-server in je project
Leer de beste praktijken voor het integreren van een OIDC (OpenID Connect) server in je project en begrijp hoe componenten met elkaar interageren op het podium.
Je kunt te maken krijgen met een situatie waarin je een gecentraliseerd authenticatie- en autorisatiesysteem nodig hebt, ook wel identiteits- en toegangsbeheer (IAM) of identiteitsprovider (IdP) genoemd. Soms voegen mensen een woord toe om de business aan te duiden, zoals Customer IAM en Workforce IAM.
Laten we deze mooie namen even terzijde schuiven. De behoefte aan IAM kan ontstaan omdat je applicatie groeit, of omdat je van plan bent het zware werk vanaf het begin uit te besteden aan een leverancier. Desalniettemin bereik je een punt waarop een identiteitssysteem zal moeten worden geïntroduceerd in je project.
Gezien de populariteit van OAuth 2.0 is OpenID Connect (OIDC) een logische keuze voor veel ontwikkelaars. Aangezien OIDC een authenticatielaag is die boven op OAuth 2.0 is gebouwd, kun je je vertrouwd voelen wanneer je begint te werken met OIDC. Laten we beginnen!
Wat is een OIDC-server en waarom zou ik deze integreren?
Een OIDC-server, of identiteitsprovider, is een gecentraliseerd systeem dat gebruikersauthenticatie en autorisatie beheert. Zoals we bespraken in Waarom je een gecentraliseerd identiteitssysteem nodig hebt voor een multi-app business, heeft een gecentraliseerd identiteitssysteem veel voordelen.
Stel dat je project begint met een eenvoudige webapplicatie, en het heeft ingebouwde authenticatie:
Naarmate je project groeit, moet je een mobiele versie introduceren:
Het zou een slechte ervaring voor gebruikers zijn als ze voor elke applicatie een account moeten aanmaken. Omdat je met een webapplicatie begon, laat je de mobiele applicatie communiceren met de webapplicatie voor authenticatie:
Nu wordt er een nieuwe API-service geïntroduceerd. Aangezien het een service voor betalende gebruikers is, moet je ervoor zorgen dat de gebruiker is geauthenticeerd en geautoriseerd om toegang te krijgen tot de service. Om dit te bereiken, kun je de service via de webapplicatie draaien:
Of gebruik een vorm van token-techniek om de gebruiker te authentiseren en het token te valideren door te communiceren met de webapplicatie in de service. Zo kan de mobiele applicatie de service direct gebruiken:
De zaken worden rommelig. Dus besluit je de authenticatie- en autorisatielogica op te splitsen in een aparte service:
Het refactoringsproces kan pijnlijk zijn. Je zult merken dat de complexiteit exponentieel zal toenemen naarmate je meer applicaties en services aan het project toevoegt. Erger nog, je moet mogelijk meerdere authenticatiemethoden onderhouden zoals wachtwoordloos inloggen, sociale login, SAML, enz.
Daarom kunnen we beter een identiteitsprovider introduceren aan het begin van je plan om je project op te schalen.
Beste praktijken voor het integreren van een OIDC-server
Vind een OIDC-provider
Er zijn veel OIDC-providers beschikbaar op de markt. Je kunt er een kiezen op basis van je vereisten en voorkeuren. Zolang de provider OIDC-compatibel is, zal het dezelfde rol spelen in je project.
Wat betekenen "subject," "client" en "audience" in OIDC?
Om het concept te vereenvoudigen, kunnen we denken aan het subject als de entiteit die toegang aanvraagt tot een audience via een client.
Laten we enkele typische scenario's bekijken:
1. Een gebruiker klikt op de inlogknop van een webapplicatie
In een traditionele en server-side rendering webapplicatie zijn de frontend en backend gekoppeld. Stel dat de webapplicatie zowel frontend als backend bedient:
- Subject: De gebruiker
- Audience: De OIDC-server
- Client: De webapplicatie
Het lijkt misschien contra-intuïtief dat de audience de OIDC-server is. In feite is het de sleutel tot het realiseren van de SSO (Single Sign-On) ervaring voor eindgebruikers. Laten we een vereenvoudigd sequentiediagram bekijken voor authorization code flow:
code
is een eenmalige code die kan worden ingewisseld voor verschillende tokens, zoals toegangstoken, ID-token en ververstoken. Het is oké als je op dit moment niet alle tokens begrijpt. Naarmate we verder gaan, krijg je een beter begrip ervan.
In het bovenstaande geval hoeft de gebruiker niet opnieuw in te loggen wanneer hij overschakelt naar een andere applicatie, omdat de gebruiker (subject) al is geauthentiseerd met de OIDC-server (audience).
2. Een gebruiker gebruikt een single-page applicatie
In een single-page applicatie (of een mobiele applicatie) zijn de frontend en backend gescheiden. Stel dat de backend een API-service is:
- Subject: De gebruiker
- Audience: De API-service
- Client: De single-page applicatie (SPA)
Een vereenvoudigd sequentiediagram met authorization code flow:
Aangezien de API-service niet-interactief is, moet de SPA het toegangstoken gebruiken met de API-service als audience (de aud
in de token).
Waarom is de OIDC-server nog steeds een audience?
Technisch gezien kun je de OIDC-server verwijderen uit de audience-lijst. Aangezien je in de meeste gevallen gebruikersinformatie nodig hebt van de OIDC-server (wat vereist dat de OIDC-server de audience is), is het beter om de OIDC-server altijd op te nemen in de audience-lijst wanneer het gebruikersinteractie betreft.
Wacht, je zegt dat we meerdere audiences kunnen hebben in een authorization request?
Precies! Vergeet niet dat OIDC bovenop OAuth 2.0 is gebouwd, het is mogelijk om RFC 8707: Resource Indicators for OAuth 2.0 in de authorization request te gebruiken om meerdere audiences te specificeren. Het vereist ondersteuning van zowel de grant als de OIDC-server. Logto ondersteunt deze functie van nature.
3. Een machine-to-machine communicatie
Stel dat je een service A hebt die service B moet aanroepen:
- Subject: Service A
- Audience: Service B
- Client: Service A
Een vereenvoudigd sequentiediagram met client credentials grant:
Wanneer service B service A moet aanroepen, worden de rollen eenvoudigweg omgedraaid.
Samenvatting
- Subject: Het kan een gebruiker zijn, een service, of een entiteit die toegang tot de audience nodig heeft.
- Client: Het kan een webapplicatie zijn, een mobiele applicatie, of een entiteit die het verzoek initieert of namens het subject handelt.
- Audience: Het kan een service zijn, een API, of een entiteit die toegang verleent aan het subject.
Wat zijn toegangstokens, ID-tokens, en ververstokens?
Er zijn drie soorten tokens die je kunt tegenkomen bij het werken met OIDC:
- Toegangstoken: Wordt gebruikt om toegang te krijgen tot de audience. Het kan een JWT (JSON Web Token) of een ondoorzichtig token zijn (meestal een willekeurige tekenreeks).
- ID-token: Een OIDC-specifiek token dat gebruikersinformatie bevat. Het is altijd een JWT. De client kan het token decoderen om gebruikersinformatie te verkrijgen.
- Vervrestoken: Wordt gebruikt om een nieuwe set tokens te krijgen wanneer de toegangstoken of ID-token verloopt.
Voor een gedetailleerde uitleg van deze tokens kun je verwijzen naar Understanding refresh tokens, access tokens, and ID tokens in OIDC protocol.
In de bovengenoemde scenario's 1 en 2 verwijst de term authorization request naar een verzoek om een set tokens te verkrijgen via een specifieke grant.
Wanneer alles goed gaat, zal een set tokens worden geretourneerd in de stap "Wissel tokens met code
". De beschikbare tokens in de set hangen af van meerdere factoren, vooral de parameter scope
in de authorization request. Voor de eenvoud gaan we ervan uit dat alle tokens in de set worden geretourneerd. Zodra de toegangstoken verloopt, kan de client de ververstoken gebruiken om een nieuwe set tokens te verkrijgen zonder gebruikerseinteractie.
Voor scenario 3 is het eenvoudiger omdat de client credentials grant alleen een toegangstoken retourneert.
Hoe om te gaan met meerdere audiences in OIDC?
Je merkt misschien op dat er slechts één toegangstoken tegelijk wordt geretourneerd. Hoe kunnen we omgaan met de situatie waarin de client toegang nodig heeft tot meerdere audiences?
Er zijn twee gangbare oplossingen:
Specificeren van resource
in de codewisselverzoek
Wanneer de client de code omwisselt voor tokens, kan deze een resource
parameter specificeren in het verzoek. De OIDC-server zal een toegangstoken retourneren voor de gespecificeerde audience indien van toepassing.
Hier is een niet-normatief voorbeeld:
De OIDC-server zal dan een toegangstoken retourneren voor de API_SERVICE
audience, indien van toepassing.
Gebruik een ververstoken om een nieuw toegangstoken te krijgen
Met RFC 8707 kan de client zelfs meerdere audiences specificeren door de resource
parameter meerdere keren te gebruiken. Nu, als ververstokens beschikbaar zijn in de client, kan de client de audience specificeren in de resource
parameter bij het verversen van de token.
Hier is een niet-normatief voorbeeld:
Het heeft hetzelfde effect als de vorige oplossing. Ondertussen blijven andere verleende audiences beschikbaar in toekomstige tokenverzoeken.
Client credentials grant
Je kunt ook de resource
parameter gebruiken in de client credentials grant om de audience te specificeren. Er is geen probleem met meerdere audiences in deze grant omdat je altijd een nieuw toegangstoken voor een andere audience kunt aanvragen door eenvoudigweg een ander tokenverzoek te sturen.
Bescherm je API-service
De "API-service" in scenario 2 en de "Service B" in scenario 3 hebben één ding gemeen: ze moeten het toegangstoken valideren om te bepalen of het verzoek geautoriseerd is. Afhankelijk van het formaat van het toegangstoken kan het validatieproces variëren.
- Ondoorzichtig token: De API-service moet de OIDC-server bellen om het token te valideren. Een introspectie-eindpunt wordt meestal door de OIDC-server voor dit doel verstrekt.
- JWT: De API-service kan het token lokaal valideren door de handtekening en de claims in het token te controleren. De OIDC-server biedt meestal een JSON Web Key Set (JWKS)-eindpunt (
jwks_uri
) voor de API-service om de openbare sleutel te krijgen om de handtekening te verifiëren.
Als je nieuw bent met JWT, kun je verwijzen naar Wat is JSON Web Token (JWT)?. In feite is het meestal niet nodig om de handtekening te valideren en de claims handmatig te bevestigen, omdat er veel bibliotheken zijn die dit voor je kunnen doen, zoals jose voor Node.js en webbrowsers.
Claims bevestigen
Naast het valideren van de JWT-handtekening, moet de API-service altijd de claims in het token controleren:
iss
: De uitgever van het token. Het moet overeenkomen met de uitgevers-URL van de OIDC-server.aud
: De audience van het token. Het moet overeenkomen met de audience-waarde van de API-service (meestal een geldige URI).exp
: De vervaltijd van het token. De API-service moet het token afwijzen als het is verlopen.scope
: De scopes (toestemmingen) van het token. De API-service moet controleren of de vereiste scope aanwezig is in het token.
Andere claims, zoals sub
(subject) en iat
(uitgegeven op), zijn ook belangrijk in sommige gevallen. Als je aanvullende beveiligingsmaatregelen hebt, controleer dan de claims dienovereenkomstig.
Autorisatie
Een onbeantwoorde vraag blijft daar: Hoe bepalen we of een scope (d.w.z. toestemming) kan worden verleend aan een subject?
De enkele vraag leidt tot een hele nieuwe wereld van autorisatie, die buiten het bestek van dit artikel valt. Kort gezegd zijn er enkele gangbare benaderingen zoals RBAC (Role-Based Access Control) en ABAC (Attribute-Based Access Control). Hier zijn enkele bronnen om je op weg te helpen:
- RBAC en ABAC: De toegangscontrolemodellen die je moet kennen
- RBAC beheersen in Logto: Een uitgebreid praktijkvoorbeeld
Afsluitende opmerkingen
Het introduceren van een OIDC-server in je project is een grote stap. Het kan de beveiliging en schaalbaarheid van je project aanzienlijk verbeteren. Ondertussen kan het enige tijd duren om de concepten en interacties tussen componenten te begrijpen.
Het kiezen van een goede OIDC-provider die voldoet aan je vereisten en voorkeuren kan de complexiteit van het integratieproces aanzienlijk verminderen, omdat de provider meestal het hele pakket biedt, inclusief de OIDC-server, autorisatiemechanismen, SDK's en de enterprise-functies die je mogelijk in de toekomst nodig hebt.
Ik hoop dat deze gids je helpt om de basisprincipes van het integreren van een OIDC-server te begrijpen. Als je op zoek bent naar een om mee te beginnen, zou ik eigenwijs Logto aanbevelen, onze identiteitsinfrastructuur voor ontwikkelaars.