PKCE (prononcer « pixy » ) est un acronyme pour "Proof Key for Code Exchange" (clé de preuve pour l’échange de code).
Voir RFC 7636 : Flux de code d’autorisation avec clé de vérification pour l’échange de code (Proof of Key for Code Exchange, PKCE)
Utilité de PKCE pour les applications mobiles / natives
Lors de l’authentification, les applications mobiles / natives ( sans back-end [1] ) peuvent utiliser le flux de code d’autorisation, mais elles requièrent une sécurité supplémentaire, car elles ne peuvent stocker en toute sécurité le secret du client qui pourrait être révélé par reverse-engineering (le secret client est lié à l’application et est identique pour tous les utilisateurs et appareils).
Les applications sans back-end peuvent utiliser un schéma d’URL personnalisé pour capturer les redirections (par exemple, MyApp ://). Ceci peut être détourné par une application malveillante, résidant sur le même user-agent, pour recevoir un code d’autorisation.
Pour pallier ce problème, OAuth 2.0 et OpenID Connect fournissent un complément au flux de code d’autorisation utilisant une clé de vérification pour l’échange de code (PKCE).
Flux de code d’autorisation + PKCE
Une application cliente mettant en œuvre le flux de code d’autorisation avec PKCE doit être du type "publique" c’est à dire être enregistrée sur le serveur avec un secret null.
L’application cliente publique crée une valeur de chaîne aléatoire (unique et ne contenant pas d’information), le code_verifier. Lorsque l’application cliente initie la demande de code d’autorisation, au lieu du secret, elle envoie au contrôleur Authorize le hash du code_verifier sous le paramètre code_challenge.
Une fois que l’utilisateur s’est authentifié et que le code d’autorisation est renvoyé à l’application cliente, celle-ci demande les jetons en échange du code d’autorisation, en incluant le paramètre code_verifier.
Si les codes correspondent, l’authentification est terminée et un access_token est renvoyé.
Création du code_challenge
Dans la demande du code d’autorisation, l’application doit transmettre le code_challenge et la méthode de codage "code_challenge_method" [2].
Partant d’une chaîne aléatoire ’code_verifier’, on obtient le code_challenge en appliquant un hachage SHA256 et un codage URL base64. Il faut également passer code_challenge_method = ’S256’
PHP
- // Prepare PKCE code_challenge
- $code_verifier = substr( str_shuffle("abcdefghijklmnopqrstuvwxyz0123456789ABCDEFabcdefghijklmnopqrstuvwxyz0123456789ABCDEFabcdefghijklmnopqrstuvwxyz0123456789ABCDEF"), 0, 50);
- $code_challenge = strtr(rtrim(base64_encode(hash('sha256', $code_verifier, true)), '='), '+/', '-_');
- $_SESSION['code_verifier'] = encrypt($code_verifier);
- ...
Javascript
- function base64URLEncode(str) {
- return str.toString('base64')
- .replace(/\+/g, '-')
- .replace(/\//g, '_')
- .replace(/=/g, '');
- }
- var code_verifier = crypto.randomBytes(50);
- var code_challenge = base64URLEncode(code_verifier );
- ...
Constante de configuration ENFORCE_PKCE
Si la constante de configuration ENFORCE_PKCE est fixée à true, tous les clients doivent appliquer PKCE.
Si false, PKCE est appliqué seulement aux clients interrogeant Authorize avec le paramètre code_challenge.
Cette constante est fixée à False par défaut.
Erreur ’missing_code_challenge’
Si la constante de configuration ENFORCE_PKCE est fixée à true ou si le client interroge Authorize avec le paramètre code_challenge, et que le client ne fournit pas le code challenge ainsi que la méthode de codage dans la demande de code d’autorisation, le contrôleur Authorise répond avec un code 400 et le message ’missing_code_challenge’, ’This application requires you provide a PKCE code challenge’.
Appel au contrôleur Token
Lorsque l’application cliente appelle le contrôleur Token pour obtenir les jetons, elle passe le paramètre code_verifier et le client ID dans le corps de la requête POST ( au lieu de passer le client ID et le secret dans le header par la méthode d’authentification HTTP Basic ).
Exemple en PHP :
- $code_verifier = decrypt(@$_SESSION['code_verifier']);
- 'client_id' => $client_id,
- 'grant_type' => 'authorization_code',
- 'code' => $code,
- 'code_verifier' => $code_verifier,
- );
- //curl_setopt($h, CURLOPT_USERPWD, "{$client_id}:{$client_secret}");
- ...
Erreur ’code_verifier_missing’
Si le client a interrogé Authorize avec un code_challenge (quelque soit la valeur de la constante de configuration ENFORCE_PKCE), et que le client ne fournit pas le paramètre ’code_verifier’ dans la demande de jeton, le contrôleur Token répond avec un code 400 et le message ’code_verifier_missing’, "The PKCE code verifier parameter is required’.