Skip to content
Last updated

Authorization Code Grant with PKCE Example

PKCE (Proof Key for Code Exchange) is an OAuth 2.0 extension that secures public clients, such as mobile apps and single-page applications (SPAs) that cannot securely store a client secret.

It helps prevent authorization code injection and CSRF attacks by using a one-time-use verifier.

Overview

  • Firstup’s authorization server supports PKCE.
  • Only S256 (SHA-256 hashed) code challenges are accepted.
  • No client secret is needed.
  • Ideal for browser-based and mobile apps.

Best Practices

  • Always use S256 for the code_challenge_method.
  • Store code_verifier and state securely (e.g., local/session storage).
  • Use HTTPS for all endpoints.
  • Always validate the state parameter.
  • Do not reuse code_verifiers.

Step 1: Generate

Generate code_verifier and code_challenge.

JavaScript example:

function generateCodeVerifier(length = 128) {
  const array = new Uint8Array(length);
  window.crypto.getRandomValues(array);
  return btoa(String.fromCharCode.apply(null, array))
    .replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
}

async function generateCodeChallenge(codeVerifier) {
  const encoder = new TextEncoder();
  const data = encoder.encode(codeVerifier);
  const digest = await crypto.subtle.digest('SHA-256', data);
  return btoa(String.fromCharCode(...new Uint8Array(digest)))
    .replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
}

Step 2: Build

Build the authorization URL and redirect the user.

Example URL (ensure all parameters are URL-encoded).

https://auth.socialchorus.com/oauth/authorize?
client_id=YOUR_CLIENT_ID&
redirect_uri=https%3A%2F%2Fyourapp.com%2Fcallback&
scope=openid+profile+feeds.read&
state=YOUR_RANDOM_STATE&
code_challenge=YOUR_CODE_CHALLENGE&
code_challenge_method=S256&
program_id=YOUR_PROGRAM_ID&
response_type=code&
response_mode=query

Required parameters:

ParameterDescription
client_idYour app's Client ID
redirect_uriCall back URI
scopeOne or more scopes (space-delimited, use + for URLs)
stateCSRF nonce
code_challengeSHA-256 hash of the code_verifier
code_challenge_methodMust be S256
program_idYour program ID
response_typecode
response_modequery

Step 3: Handle

Handle the redirect. After user login, the app is redirected to:


https://yourapp.com/callback?code=AUTH_CODE&state=YOUR_RANDOM_STATE

Extract the code and validate the returned state matches the original. If state does not match, terminate the flow.

Step 4: Exchange

Exchange the code for an access token.

Curl example:

curl -X POST https://auth.socialchorus.com/oauth/token \
  -F grant_type=authorization_code \
  -F client_id=YOUR_CLIENT_ID \
  -F code=AUTH_CODE_FROM_REDIRECT \
  -F redirect_uri=https://yourapp.com/callback \
  -F code_verifier=ORIGINAL_CODE_VERIFIER

Sample response:

{
  "access_token": "ACCESS_TOKEN_HERE",
  "refresh_token": "REFRESH_TOKEN_HERE",
  "expires_in": 7200,
  "token_type": "Bearer",
  "scope": "openid public",
  "realm": "program:1"
}

Refreshing Access Tokens

Use this call to get a new access token using the refresh_token:

curl -X POST https://auth.socialchorus.com/oauth/token \
  -F grant_type=refresh_token \
  -F client_id=YOUR_CLIENT_ID \
  -F refresh_token=YOUR_REFRESH_TOKEN