Wat is PKCE: van basisconcepten tot diepgaand begrip
Dit artikel legt uit hoe PKCE (Proof Key for Code Exchange) de OAuth 2.0 autorisatiecode-stroom beveiligt door te voorkomen dat kwaadaardige applicaties autorisatiecodes onderscheppen, en neemt je mee van basisconcepten naar een uitgebreid begrip.
Proof Key for Code Exchange (PKCE) is een uitbreiding van de Authorization Code-flow, oorspronkelijk ontworpen om de autorisatiecode-stroom in mobiele apps te beveiligen. Nu wordt het aanbevolen om ook te worden gebruikt door enkelvoudige-pagina-apps. Vanaf OAuth 2.1 wordt PKCE verplicht gesteld voor alle soorten clients, inclusief public clients en confidential (private) clients.
In dit artikel helpen we je begrijpen waarom PKCE is gemaakt en hoe het jouw applicaties beschermt, waardoor je een diepgaand begrip van PKCE krijgt.
Waarom is PKCE nodig?
In de OAuth 2.0 autorisatiecode-stroom vragen gebruikers om in te loggen via een applicatie. De authenticatieserver leidt gebruikers naar een authenticatiepagina. Na gebruikersauthenticatie retourneert de server een autorisatiecode naar de applicatie, die deze code vervolgens gebruikt om een toegangstoken van de authenticatieserver aan te vragen.
Deze stroom kent een aanzienlijk beveiligingsrisico: de autorisatiecode kan worden onderschept door kwaadaardige programma's. Dit is vooral zorgwekkend op mobiele apparaten, waar andere apps dezelfde redirect-URI kunnen registreren en de autorisatiecode kunnen onderscheppen.
Het onderscheppingsproces wordt weergegeven in het onderstaande diagram:
Stap (1): De app voert een auth-aanvraag uit via een beveiligde API die niet kan worden onderschept. In deze stap levert de aanvrager ook een redirect-URI.
Stap (2): De aanvraag wordt vervolgens doorgestuurd naar de OAuth 2.0-autorisatieserver. Omdat OAuth het gebruik van TLS vereist, is deze communicatie beveiligd door TLS en kan deze niet worden onderschept.
Stap (3): De autorisatieserver retourneert de autorisatiecode.
Stap (4.a): de autorisatiecode wordt via de redirect-URI die in stap (1) is opgegeven aan de aanvrager geretourneerd. In deze stap, als de kwaadaardige app zichzelf registreert als een verwerker voor de redirect-URI, kan de kwaadaardige app de autorisatiecode onderscheppen. Met de autorisatiecode kan de aanvaller een toegangstoken aanvragen en verkrijgen in stappen (5.a) en (6.a).
Zoals hierboven getoond, kunnen aanvallers in de OAuth 2.0-autorisatiecode-stroom de autorisatiecode gebruiken om toegangstokens te verkrijgen als de autorisatiecode wordt onderschept. Daarom hebben we een mechanisme nodig om onderschepping van de autorisatiecode te voorkomen, wat heeft geleid tot de creatie van PKCE.
Hoe werkt PKCE?
Zoals hierboven vermeld, als we willen voorkomen dat we worden aangevallen, moeten we ervoor zorgen dat alleen de app die de aanvraag heeft ingediend het toegangstoken kan aanvragen en verkrijgen. Hier komt PKCE in beeld.
PKCE lost dit probleem op door het concept van een "proof key" in te voeren.
Wanneer een autorisatiecode wordt aangevraagd, genereert de applicatie eerst een willekeurige codeverifier en slaat deze lokaal op. Het zet deze codeverifier vervolgens om in een code challenge met behulp van specifieke algoritmen. De applicatie stuurt zowel de code challenge als de gebruikte methode voor de code challenge naar de authenticatieserver tijdens de autorisatiecode-aanvraag.
De codeverifier is een willekeurig gegenereerde tekenreeks, en de code challenge wordt afgeleid van de codeverifier door middel van conversie. Twee conversiemethoden worden ondersteund:
plain
: Gebruikt de code verifier direct als de code challenge
S256
: Past SHA-256 hashing toe op de code verifier, gevolgd door Base64URL-codering. Omdat de hash-uitvoer niet kan worden omgekeerd om de code verifier te verkrijgen, en omdat deplain
methode mogelijk kwetsbaar is voor man-in-the-middle aanvallen tijdens transmissie, wordt om veiligheidsredenen sterk aanbevolen omS256
te gebruiken.
Na gebruikersauthenticatie retourneert de authenticatieserver de autorisatiecode aan de applicatie. Bij het aanvragen van een toegangstoken stuurt de applicatie zowel de autorisatiecode als de code verifier naar de authenticatieserver. De server transformeert de "code verifier" met behulp van de eerder ontvangen "code challenge methode" en vergelijkt het resultaat met de eerder ontvangen "code challenge" om de bezitting van de "code verifier" door de client te verifiëren.
Stap (1-3): De app maakt en registreert een geheim dat de "code verifier" wordt genoemd en leidt een omgezette versie "code challenge" af, die wordt verstuurd in het OAuth 2.0 Authorisatie Verzoek samen met de transformatie methode "code challenge methode".
Stap (3-6): De Auth Server reageert zoals gebruikelijk maar registreert "code challenge" en de "code challenge methode".
Stap (7.a): De app verzendt vervolgens de autorisatiecode naar het token-eindpunt zoals gebruikelijk, maar voegt het gegenereerde "code verifier" geheim van stap (1) toe.
Stap (8.a-9.a): De autorisatieserver transformeert "code verifier" naar "code challenge" en vergelijkt het met "code challenge" van stap (1-3). Toegang wordt geweigerd als ze niet gelijk zijn.
In dit geval, zelfs als de kwaadaardige app de autorisatiecode heeft onderschept in stap (6.b), kan deze deze niet verzilveren voor een toegangstoken, omdat deze niet in het bezit is van het "code_verifier" geheim, en omdat de "code verifier" wordt verzonden via TLS, kan deze niet worden onderschept.
Samenvatting
Dit artikel legt uit hoe PKCE werkt en waarom het noodzakelijk is voor de bescherming van de autorisatiecode-stroom. Door een proof key mechanisme toe te voegen, voorkomt PKCE dat kwaadaardige applicaties autorisatiecodes onderscheppen en misbruiken. Hopelijk helpt deze uitleg je om PKCE in detail te begrijpen.