Bij het ontsluiten van een landschap met interne en externe gebruikers, is het belangrijk veiligheid zeer serieus te nemen. In het geval van een API Gateway is het noodzakelijker dat de authenticatie en de autorisatie gekoppeld aan de toegang naar deze gateway goed is geconfigureerd. In deze blog vergelijken we drie manieren om dit te bereiken, namelijk: API keys, HTTP Basic Authentication en OAuth. We bespreken deze drie en kijken ook naar de voor- en nadelen per methodes.
API keys
Het gebruik van API keys is een manier om toegang tot een API te verifiëren op tenant, gebruiker of applicatie niveau. Hierbij wordt niet verwezen naar een werkelijke gebruiker, maar wordt dus gebruik gemaakt van de API key (Authenticatie). In een API request wordt de key toegevoegd, zodat deze gebruikt kan worden om de requestor te identificeren en de request te autoriseren (Autorisatie). De key kan tevens worden gebruikt voor rate-limiting, het bijhouden van statistieken en andere, soortgelijke acties of principes. Er zijn verschillende manieren waarop een API met een API key kan omgaan. Sommige API’s vereisen query parameters, sommige gebruiken de “header authorize” variant en er zijn gevallen waarin het gebruik van parameters in de body of elders noodzakelijk is. Onderstaand een voorbeeld van Google Cloud API.
Voordelen:
- Eenvoudig: Hoewel de meeste providers verschillende methoden gebruiken, is het toevoegen van een key aan API request vrij eenvoudig.
Nadelen:
- Moeilijke identificatie: De API key identificeert alleen de applicatie en niet perse de gebruiker van de toepassing.
- Moeilijk om de key geheim te houden: Voor server-to-server communicatie is het mogelijk om de sleutel verbergen met TLS en de toegang te beperken tot gebruik in backend-scenario’s. Echter zijn er vele verschillende type clients die de API’s willen consumeren, dit zorgt ervoor dat het lastig is de keys te verbergen.
HTTP Basic Auth
HTTP Basic Auth is een eenvoudige methode, waarbij een HTTP request door middel van een gebruikersnaam en wachtwoord wordt geverifieerd. Deze techniek maakt gebruik van een header genaamd “Authorization”, hier is een base64 gecodeerde weergave van de gebruikersnaam en het wachtwoord in opgenomen. Afhankelijk van de use case kan HTTP Basic Auth de gebruiker van de toepassing of de applicatie zelf verifiëren.
In het geval dat HTTP Basic Auth voor een API Gateway wordt ingezet, dan wordt deze header waarde “Authorization” bij elk verzoek verzonden. Deze situatie is vergelijkbaar met het gebruik van API keys, waarbij de credentials worden gebruikt ter verificatie van de toepassing.
Net als bij de API Keys kunnen deze inloggegevens naar derden lekken. De kans dat credentials herleidbaar zijn in logging data is kleiner, doordat deze in een header worden verzonden. In het geval van een query- of pad parameter waarin een API Key zou zitten is deze kans groter.
Het gebruik van HTTP Basic Auth voor het verifiëren van gebruikers wordt meestal niet aanbevolen, omdat het verzenden van de gebruiker credentials voor elk verzoek als een “bad practice” wordt beschouwd. Als HTTP Basic Auth slechts voor één aanvraag wordt gebruikt, moet de toepassing nog steeds gebruikers credentials verzamelen. De gebruiker heeft geen middelen om te weten voor welke applicatie ze worden gebruikt en de enige manier om de toegang in te trekken, is door het wachtwoord te wijzigen.
Voordelen:
- Gestandaardiseerd: HTTP Basic Auth is een gestandaardiseerde manier om credentials te verzenden. De header heeft altijd dezelfde structuur en de componenten zijn eenvoudig te implementeren.
- Eenvoudig in gebruik: daarmee kan het zorgdragen voor authenticatie van applicaties in server-to-server omgevingen.
Nadelen:
Wanneer een gebruiker is geverifieerd, moet de toepassing het wachtwoord bewaren. Vanuit het perspectief van de gebruiker is het niet inzichtelijk op welke wijze de applicatie het wachtwoord persisteert. Er is voor de gebruiker geen andere manier om de toegang in te trekken dan door het wachtwoord te wijzigen. De wachtwoorden zijn lange termijn tokens en als een “aanvaller” een wachtwoord heeft bemachtigd, dan blijft dit veelal onopgemerkt. Wanneer deze authenticatie wordt gebruikt om de gebruiker te verifiëren dan is multi-factor authenticatie niet meer mogelijk.
Token gebaseerde authenticatie met OAuth 2.0
Een op tokens gebaseerde architectuur is gebaseerd op een principe, waarin alle services een token ontvangen als bewijs dat de toepassing de service mag aanroepen. Het token wordt uitgegeven door een derde partij die kan worden vertrouwd door zowel de toepassing als de service. Momenteel is het meest populaire protocol voor het verkrijgen van deze tokens OAuth 2.0, gespecificeerd in RFC 6749.
OAuth specificeert een manier van werken, waarbij een toepassing of gebruiker om toegang tot services kan vragen en een token kan ontvangen als bewijs dat toegang is verleend. Om uit te leggen hoe OAuth werkt, schetsen we de volgende fictieve use-case:
Gebruiker Alice heeft een account bij een dienst waar ze de actuele binnentemperatuur van haar woning kan melden. Alice wil tevens een applicatie van derden toegang geven om de temperatuurgegevens te lezen, zodat zij de temperaturen in een grafiek kunnen plotten en om verwijzingen naar gegevens van andere services te ondersteunen. De (temperatuur) service levert een API Gateway, waarin applicaties van andere partijen gemakkelijk toegang hebben tot de data en in dit geval de temperatuurgegevens. Maar hoe maken we alleen de gegevens van Alice beschikbaar voor de applicatie?
De inloggegevens managen:
Met behulp van “Basic Authentication” kan de applicatie de gebruikersnaam en het wachtwoord van Alice voor de temperatuurservice verzamelen en deze gebruiken om de gegevens van de service op te vragen. De temperatuurservice kan vervolgens de gebruikersnaam en het wachtwoord verifiëren en de gevraagde gegevens retourneren.
Zoals we echter eerder hebben benoemd, zijn er een paar problemen met deze aanpak:
- De gebruiker moet de toepassing vertrouwen met de credentials.
De gebruiker heeft geen middelen om te weten waarvoor de credentials worden gebruikt. - De enige manier voor de gebruiker om de toegang in te trekken, is door het wachtwoord te wijzigen.
- De aanvraag is niet geauthenticeerd.
- De omvang van de toegang kan niet worden gecontroleerd.
De gebruiker heeft de volledige toegang tot het account weggegeven. - Twee factor authenticatie kan niet worden gebruikt.
Het resultaat hiervan is dat er een behoefte is gecreëerd voor services om “applicatie specifieke wachtwoorden” te gebruiken, dit zorgt voor extra wachtwoorden voor uw account die door applicaties kunnen worden gebruikt.
Dit elimineert de noodzaak om het daadwerkelijke wachtwoord weg te geven, maar het betekent meestal tevens dat volledige toegang tot het account wordt weggegeven. Aan de kant van de serviceprovider kan er logica worden opgenomen rond het combineren van specifieke wachtwoorden voor het geven van toegang tot bepaalde onderdelen met API Keys, wat ook de toegang zou kunnen beperken, maar hiervoor is veel maatwerk vereist. Dit brengt ons op een meer recentere en tevens betere manier van authenticatie, OAuth.
De OAuth manier
Laten we eens kijken hoe we dit probleem kunnen oplossen met behulp van een OAuth 2 strategie. Voor een betere verificatie moet de temperatuurservice een autorisatieserver publiceren die verantwoordelijk is voor het uitgeven van tokens. Met deze autorisatieserver kunnen toepassingen van derden zich registreren en referenties ontvangen voor hun toepassing om namens gebruikers toegang te kunnen aanvragen.
Om toegang aan te vragen, kan de applicatie vervolgens de browser van de gebruiker naar de autorisatieserver verwijzen met parameters:
Deze request brengt de gebruiker naar de autorisatieserver van de temperatuurservice, waar de autorisatieserver Alice kan verifiëren met elke beschikbare methode. Omdat dit in de browser gebeurt, zijn meerdere factoren mogelijk en zijn de enigen die de gegevens zien de temperatuurservice en de eigenaar van het account.
Zodra Alice zich heeft geverifieerd, kan de autorisatieserver vragen om toestemming voor de derde partij. In dit voorbeeld wordt de read_temperature scope gevraagd, zodat de autorisatieserver een specifieke vraag kan stellen. Zodra Alice accepteert kan de client zichzelf verifiëren. Een token wordt uitgegeven als bewijs dat Alice de gedelegeerde toegang heeft geaccepteerd en het wordt teruggestuurd naar de derde partij applicatie. Nu kan de derde partij applicatie de API aanroepen met behulp van het ontvangen token. Het token wordt samen met het verzoek verzonden door het als volgt toe te voegen aan de Authorization header met het keyword Bearer:
Na ontvangst van de request kan de service het token valideren en zien dat Alice de applicatie toestemming heeft gegeven om de lijsten met temperaturen van haar account te lezen en de gegevens naar de applicatie te retourneren.
Token validatie
Het uitgegeven token kan op twee manieren worden geretourneerd, hetzij door een verwijzing naar de tokengegevens terug te geven of door de waarde van het token rechtstreeks terug te geven. Voor het referentie token moet de service een verzoek naar de autorisatieserver sturen om het token te valideren en de bijbehorende gegevens te retourneren. Dit proces wordt “introspection” genoemd en een voorbeeld response ziet er uit als volgt:
In deze response kunnen we zien dat de gebruiker Alice de applicatie third_party_graphs toegang heeft verleend tot haar account, met daarin de scope van read_temperatures. Op basis van deze informatie kan de service beslissen of het request moet worden toegestaan of moet weigeren.
De client_id kan ook worden gebruikt voor statistieken en rate-limiting van de toepassing. Merk op dat we alleen de gebruikersnaam van het account in het voorbeeld hebben gekregen, maar omdat de autorisatieserver de verificatie doet, kan het ook extra claims retourneren in dit antwoord (zoals accounttype, adres, schoenmaat, enz.) Claims zijn parameters waarmee de service een goed geïnformeerde autorisatiebeslissing kan nemen.
Voor het retourneren van de waarde wordt meestal een JSON Web Token (JWT) gebruikt. Dit token kan worden ondertekend of gecodeerd, zodat de service het token kan verifiëren door simpelweg de openbare sleutel van de vertrouwde autorisatieserver te gebruiken. Lees hier over meerdere mogelijkheden en alternatieven omtrent het inzetten van verschillende token types.
We zien in de OAuth methode duidelijke verschillen ten opzichte van Basic Authentication:
- Alice gaf alleen aan de vertrouwde site haar credentials.
- Multi factor authenticatie kan nog steeds gebruikt worden.
- Alice kan de toegang van de applicatie gemakkelijk wijzigen, zonder dat er een wachtwoord wijziging nodig is.
- Alice kan de derde partij applicatie toegang verlenen aan specifieke informatie rondom haar account.
- Claims ten opzichte van de gebruiker kunnen direct worden gehonoreerd ten tijde van de request en er zijn hiervoor geen extra checks benodigd.
- De “authenticatie flow” is volledig gestandardiseerd.
In de bovenstaande use case is alleen de gebruikers stroom beschreven, maar OAuth specificeert natuurlijk alternatieve stromen voor het verkrijgen van tokens in server naar server omgevingen. Als men meer informatie over het de verschillende smaken van verwerkingen en flows die optimaal ondersteund worden met Oauth dan is het volgende artikel erg interresant; 8 types of oauth flows.
Welke manier is nu beter?
Aangezien OAuth 2 is ontwikkeld in een tijd waarin steeds meer gebruik wordt gemaakt van API’s, zijn de meeste use cases waarin de API Key of Basic Authentication worden overwogen en meegenomen binnen het protocol. Derhalve wordt het gebruik van OAuth 2 geprefereerd ten opzichte van API Keys en Basis Authentication.
Voor kleine en specifieke scenario’s kan het toepasselijk zijn om een API Key of zelfs Basic Authentication te gebruiken, maar iedereen die een systeem opbouwt en van plan is om dit systeem te schalen zal willen en moeten kijken naar een op tokens gebaseerde architectuur, bijvoorbeeld een Neo Security Architecture.
De beste manier om de beveiliging van je API gateway te regelen is dus afhankelijk van je use-case. Heb je een kleiner en meer specifieke case dan gebruik je een API key of Basic Authentication. Maar bij een grote use case waar beveiliging cruciaal is, dan is de meest logische manier van beveiliging OAuth 2.
Hopelijk weet je na het lezen van deze blog wat meer over beveiliging binnen je API gateway. Mocht je nu nog meer willen weten of heb je een interessant vraagstuk waar we je mee kunnen helpen? Neem dan contact met ons op!
Door Leo Bekhuis, Software Developer @ eMagiz