> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.id.me/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.id.me/_mcp/server.

# PKCE

> Implement Authorization Code Flow with Proof Key for Code Exchange (PKCE)

Proof Key for Code Exchange (PKCE, [RFC 7636](https://datatracker.ietf.org/doc/html/rfc7636)) is an extension to the OAuth 2.0 Authorization Code Flow that prevents authorization code interception attacks. PKCE is required by [OAuth 2.1](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1) guidance and is strongly recommended for all clients, especially mobile and single-page applications.

> **Info**
>
> PKCE can be used with or without a client secret. Mobile and other public clients can safely perform the flow without a client secret because PKCE ensures only the app instance that initiated the request can complete the token exchange.

## How PKCE works

PKCE adds a dynamically created cryptographic secret to the standard authorization code flow. Before each authorization request, your application generates a random `code_verifier` and derives a `code_challenge` from it. The challenge is sent with the authorization request, and the original verifier is sent with the token exchange, allowing IDMe to verify both came from the same client.

## Prerequisites

Before implementing PKCE, ensure you have:

* A registered IDMe application with a `client_id`
* One or more configured `redirect_uri` values
* Access to the appropriate environment (Sandbox or Production)

> **Tip**
>
> Most OAuth/OIDC client libraries handle PKCE automatically. Check your library's documentation before implementing the steps below manually.

## Step-by-step implementation

#### Retrieve OIDC discovery document

Fetch the discovery document to get all endpoint URLs dynamically.

| Environment | URL                                                              |
| ----------- | ---------------------------------------------------------------- |
| Sandbox     | `https://api.idmelabs.com/oidc/.well-known/openid-configuration` |
| Production  | `https://api.id.me/oidc/.well-known/openid-configuration`        |

#### Generate PKCE pair

Generate a random `code_verifier` — a 43–128 character URL-safe string. Then derive the `code_challenge` by computing the SHA-256 hash of the verifier and Base64-URL encoding the result without padding. Store the `code_verifier` securely for use during the token exchange in step 6.

#### Send authorization request

Redirect the user to the IDMe authorization endpoint. Include the standard OIDC parameters along with the two PKCE-specific parameters.

#### Parameters

| Parameter               | Description                                                  |
| ----------------------- | ------------------------------------------------------------ |
| `client_id`             | Your application's client identifier                         |
| `redirect_uri`          | Your registered redirect URI                                 |
| `response_type`         | Must be `code`                                               |
| `scope`                 | Must include `openid` plus your policy scope                 |
| `nonce`                 | A random value generated per request                         |
| `state`                 | A random value tied to this session for CSRF protection      |
| `code_challenge`        | The SHA-256 hash of your `code_verifier`, Base64-URL encoded |
| `code_challenge_method` | Must be `S256`                                               |

#### User verifies identity

The user is redirected to IDMe to authenticate and complete identity verification. No action is required from your application during this step.

#### Receive authorization code

IDMe redirects the user back to your `redirect_uri` with an authorization `code` and the `state` value appended as query parameters.

> **Critical**
>
> Always verify that the returned `state` matches the value you sent in the authorization request before proceeding. This prevents CSRF attacks.

#### Exchange code for tokens

Send a POST request to IDMe's token endpoint with the `code_verifier` to complete the exchange. IDMe verifies that the `code_verifier` matches the `code_challenge` sent in step 3, confirming the request originated from the same client.

* **Endpoint**: `https://api.id.me/oauth/token`
* **Method**: `POST`
* **Content-Type**: `application/x-www-form-urlencoded`

#### Parameters

| Parameter       | Description                                                 |
| --------------- | ----------------------------------------------------------- |
| `grant_type`    | Must be `authorization_code`                                |
| `code`          | The authorization code from the callback                    |
| `client_id`     | Your application's client identifier                        |
| `redirect_uri`  | Must match the value used in the authorization request      |
| `code_verifier` | The original `code_verifier` generated in step 2            |
| `client_secret` | Optional; include if your application can store it securely |

The response includes an `access_token`, `refresh_token`, and an `id_token` (a signed JWT containing user claims).

#### Get user attributes

Send a GET request to the UserInfo endpoint with the access token to retrieve user attributes.

* **Endpoint**: `https://api.id.me/api/public/v3/userinfo`
* **Method**: `GET`
* **Authorization**: `Bearer {access_token}`

For details on validating and decoding the ID token, see [Integration](/guides/open-id-connect/integration).

## PKCE for mobile applications

PKCE is especially important for mobile clients where the client secret cannot be stored securely. Because PKCE ensures that only the same app instance that initiated the login request can complete the token exchange — even if the authorization code is intercepted — mobile and other public clients can safely perform the flow without a client secret.

For mobile-specific implementation details, see the [Mobile SDK documentation](/guides/mobile-sdk/overview).

> **Note**
>
> When using PKCE without a client secret, omit the `client_secret` parameter from the token exchange request. The `code_verifier` provides the necessary proof of identity.

## Related resources

#### [OIDC integration](/guides/open-id-connect/integration)

Full OIDC integration guide including token validation and payload parsing

#### [Mobile SDK](/guides/mobile-sdk/overview)

Native SDK integration for iOS and Android