Proof Key for Code Exchange(PKCE) is an extension to the Authorization Code flow to prevent Cross Site Request Forgery(CSRF) and Authorization code injection attacks. (Refer to https://datatracker.ietf.org/doc/html/rfc7636)
User access to the client application.
Client application creates a cryptographically random string as a secret key (code_verifier) that only it knows and creates a base64url encoded hash of the secret key(code_challenge).
Client application returns the code_challenge and creates a frontend session to the user's browser.
Browser calls /authorize API with the code_challenge.
The AuthZ server returns the authcode.
Client application calls /token API with the code_verifier and authcode.
The AuthZ server will ensure that the code_verifier has the same hash as the code_challenge before issuing the access_token.
i) Create code_verifier
Create a code_verifier, which is the cryptographically random string that will eventually be sent to Token API to request for access_token.Copy to clipboard
// Dependency: Node.js crypto module (https://nodejs.org/api/crypto.html#crypto_crypto)
Â
function base64URLEncode(str) {
return str.toString('base64')
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=/g, '');
}
Â
// The client generates a random string of bytes and saved into a persistent session store
let codeVerifier = base64URLEncode(crypto.randomBytes(32));
i) Create code_challenge
Using the code_verifier, generate a code_challenge that will be sent in the /authorize API. Copy to clipboard
code_challenge should be generated from the raw bytes of the code_verifier and not the hex encoded string.
Example: 'helloworld' code_verifier should produce 'k2oYXKqiZrucvpgengXLeM1zKwsygOuURBK7b4-PB68' as code_challenge
// Dependency: Node.js crypto module (https://nodejs.org/api/crypto.html#crypto_crypto)
Â
function base64URLEncode(str) {
return str.toString('base64')
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=/g, '');
}
Â
// The client hashes these bytes and encodes them for use in a url
let codeChallenge = base64URLEncode(crypto.createHash('sha256').update(codeVerifier).digest());