# 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:

| Parameter | Description |
|  --- | --- |
| `client_id` | Your app's Client ID |
| `redirect_uri` | Call back URI |
| `scope` | One or more scopes (space-delimited, use + for URLs) |
| `state` | CSRF nonce |
| `code_challenge` | SHA-256 hash of the `code_verifier` |
| `code_challenge_method` | Must be `S256` |
| `program_id` | Your program ID |
| `response_type` | `code` |
| `response_mode` | `query` |


## 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
```