Table of Contents
You can generate code_verifier
and code_challenge
for OIDC authorization as follows. The following codes are also on Gist.
JavaScript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
// This code works on the Web Browser, because it uses Web Crypto API. const codeVerifierLength = 43; let codeVerifier = ''; const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~'; for (let i = 0; i < codeVerifierLength; i++) { codeVerifier += characters.charAt(Math.floor(Math.random() * characters.length)); } async function generateCodeChallenge(codeVerifier) { let digest = await crypto.subtle.digest( "SHA-256", new TextEncoder().encode(codeVerifier) ); return btoa(String.fromCharCode(...new Uint8Array(digest))). replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_'); } const codeChallenge = await generateCodeChallenge(codeVerifier); console.log(`Code Verifier : ${codeVerifier}`); console.log(`Code Challenge: ${codeChallenge}`); |
F#
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
open System open System.Linq let codeVerifierLength = 43 let random = Random() let chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~" let codeVerifier = Enumerable.Repeat(chars, codeVerifierLength). Select(fun s -> s.[random.Next(s.Length)]) |> String.Concat let codeChallenge = codeVerifier |> System.Text.Encoding.UTF8.GetBytes |> System.Security.Cryptography.SHA256.Create().ComputeHash |> System.Convert.ToBase64String |> fun x -> x.Replace("=", "").Replace("+", "-").Replace("/", "_") printfn "Code Verifier : %s" codeVerifier printfn "Code Challenge: %s" codeChallenge |
Python
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
import base64 import hashlib import random import string code_verifier_length = 43 code_verifier = ''.join(random.choice(string.ascii_letters + string.digits + '-._~')\ for i in range(code_verifier_length)) code_challenge = base64.urlsafe_b64encode(hashlib.sha256(code_verifier.encode()).digest()).\ decode().replace("=", "").replace("+", "-").replace("/", "_") print("Code Verifier :", code_verifier) print("Code Challenge:", code_challenge) |
Ruby
1 2 3 4 5 6 7 8 9 10 11 12 |
require 'digest' require 'base64' code_verifier_length = 43 o = ([('a'..'z'), ('A'..'Z'), ('0'..'9')].map(&:to_a) + %w[- _ . ~]).flatten code_verifier = (0...code_verifier_length).map { o[rand(o.length)] }.join code_challenge = Base64.urlsafe_encode64(Digest::SHA256.digest(code_verifier)). delete('=').gsub('+', '-').gsub('/', '_') puts "Code Verifier : #{code_verifier}" puts "Code Challenge: #{code_challenge}" |
Shell Script
1 2 3 4 5 6 7 |
CODE_VERIFIER_LENGTH=43 CODE_VERIFIER=`cat /dev/urandom | LC_CTYPE=C tr -dc 'a-zA-Z0-9\-._~' | fold -w $CODE_VERIFIER_LENGTH | head -n 1` CODE_CHALLENGE=`echo -n $CODE_VERIFIER | openssl dgst -sha256 -binary | openssl base64 -A | tr -d '=' | tr '/+' '_-'` echo "Code Verifier :" $CODE_VERIFIER echo "Code Challenge:" $CODE_CHALLENGE |
PKCE, Proof Key for Code Exchange
Coder verifier and code challenge are elements that are used in PKCE mechanizm. PKCE is a security enhancement for OAuth 2.0 and OpenID Connect (OIDC) authorization flows. It is primarily used to protect against authorization code interception attacks.
Here’s how it works.
Authorization Code Flow
- In the standard OAuth 2.0 authorization code flow, a client application requests an authorization code from the authorization server.
- The authorization code is then exchanged for an access token.
- However, this flow is vulnerable to interception attacks, especially in mobile or single-page applications.
PKCE to the Rescue
- PKCE introduces an additional step before exchanging the authorization code for an access token.
- The client generates a random code verifier and computes its hashed value (the code challenge).
- The code verifier is sent to the authorization server during the initial authorization request.
- The server stores the code challenge associated with the authorization code.
- When the client exchanges the authorization code for an access token, it must also send the original code verifier.
- The server verifies that the code verifier matches the stored code challenge.
Why Is PKCE Important?
- PKCE prevents attackers from intercepting the authorization code and using it to obtain an access token.
- Even if an attacker captures the authorization code, they won’t have the corresponding code verifier.
- This makes it much harder to perform token theft.
Usage
- PKCE is recommended for all public clients (e.g., mobile apps, single-page apps) that use the authorization code flow.
- Confidential clients (e.g., server-side applications) can also use PKCE for added security.
Remember, PKCE is like a secret handshake between your app and the authorization server, ensuring that only the intended recipient can complete the authorization process.