In our previous articl, we explained the theory behind the Authorization Code with PKCE flow: Authorizing against a server that utilizes PKCE requires a code_challenge in the initial /connect/authorize request and the corresponding code_verifier in the subsequent /connect/token request.

While the PKCE specification supports two methods (SHA-256 (S256) and Plai), Entrypage.io requires the use of SHA-256. This ensures a higher level of security by preventing the verifier from being intercepted in plain text.

Generating a S256 code_challenge

Use the tool below to generate a cryptographically valid code_verifier and its associated code_challenge in the required S256 format. You can also use this tool to construct your HTTP requests for testing purposes:

1. Proof Key

Loading...
Keep this secret. It is required for the final /token exchange.
Loading...
The hashed version sent to the authorize endpoint.

2. Authorize Request

3. Code Exchange

Generating the code_verifier “manually”

To generate a S256 code_verifier, one must follow these steps:

  • Generate Random Bytes: Create a sequence of cryptographically strong random bytes (typically 32 bytes to result in a 43-character string).
  • Base64URL Encode: Convert those bytes into a Base64URL encoded string. This means replacing + with -, / with _, and stripping any trailing = padding characters.
  • Hashing (for the Challenge): To create the associated code_challenge, apply a SHA-256 hash to the verifier string and Base64URL encode the resulting binary hash.

Bash

Use openssl to handle the entropy and the hashing in a shell environment:

# Generate a 32-byte random verifier
export verifier=$(openssl rand -base64 32 | tr -d '=+/' | cut -c1-43)

# Generate the S256 challenge
export challenge=$(echo -n "$verifier" | openssl dgst -sha256 -binary | base64 | tr '+/' '-_' | tr -d '=')

echo "Verifier: $verifier"
echo "Challenge: $challenge"

C#

In .NET, utilize the RandomNumberGenerator for the verifier and the SHA256 class for the challenge:

using System.Security.Cryptography;
using System.Text;

// 1. Generate Verifier
var bytes = new byte[32];
RandomNumberGenerator.Fill(bytes);
var verifier = Convert.ToBase64String(bytes)
    .TrimEnd('=').Replace('+', '-').Replace('/', '_');

// 2. Generate Challenge (S256)
using var sha256 = SHA256.Create();
var challengeBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(verifier));
var challenge = Convert.ToBase64String(challengeBytes)
    .TrimEnd('=').Replace('+', '-').Replace('/', '_');

JavaScript

For browser-based applications, the Web Crypto API is the standard for secure random values and hashing.

// Helper for Base64URL encoding
const base64Url = (buf) => btoa(String.fromCharCode(...new Uint8Array(buf)))
    .replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');

async function generatePKCE() {
    // 1. Generate Verifier
    const verifier = base64Url(window.crypto.getRandomValues(new Uint8Array(32)));

    // 2. Generate Challenge (S256)
    const encoder = new TextEncoder();
    const hash = await window.crypto.subtle.digest('SHA-256', encoder.encode(verifier));
    const challenge = base64Url(hash);

    return { verifier, challenge };
}