---
title: "Generate a PKCE-protected SSO token"
method: GET
path: "/v2/user/generate-pkce-sso-token"
tags: ["User SSO Link"]
---

# Generate a PKCE-protected SSO token

`GET /v2/user/generate-pkce-sso-token`

## Request

- Base URL: `https://your-subdomain.deputy.deputy.com/api`
- URL: `https://your-subdomain.deputy.deputy.com/api/v2/user/generate-pkce-sso-token`
- Auth: API key in header `OAuth`

Generates a short-lived single-use SSO token for the authenticated user, protected by PKCE ([RFC 7636](https://datatracker.ietf.org/doc/html/rfc7636)).

## How it works

1. Your client generates a high-entropy random **code verifier** (43-128 characters, base64url-encoded).
2. Derives a **code challenge** from the verifier:
   - `S256` (recommended): `base64url(SHA-256(verifier))`
   - `plain`: the verifier itself, unchanged (not recommended except for legacy clients).
3. Calls this endpoint with `codeChallenge` and `codeChallengeMethod` as query parameters.
4. Receives back a short-lived `token` and its `expiry` (Unix epoch seconds).
5. Redeems the token together with the original code verifier at the SSO login endpoint — this proves your client originated the request and the token hasn't been intercepted.

## Generating a code verifier + challenge (JS)

```js
// 1. Generate a cryptographically random verifier
const verifier = btoa(String.fromCharCode(...crypto.getRandomValues(new Uint8Array(32))))
  .replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');

// 2. Derive the S256 challenge
const bytes = new TextEncoder().encode(verifier);
const digest = await crypto.subtle.digest('SHA-256', bytes);
const challenge = btoa(String.fromCharCode(...new Uint8Array(digest)))
  .replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');

// 3. Call this endpoint
const res = await fetch(
  `/api/v2/user/generate-pkce-sso-token?codeChallenge=${challenge}&codeChallengeMethod=S256`,
  { headers: { Authorization: `Bearer ${accessToken}` } }
);
const { token, expiry } = (await res.json()).data;

// 4. Store `verifier` in your client; you'll need it to redeem `token`.
```

## Security notes

- **Never log or transmit the code verifier** — it is the secret half of the pair.
- Tokens are single-use and expire quickly; check `expiry` and regenerate as needed.
- Prefer `S256` over `plain`. `plain` is only retained for clients on platforms without SHA-256.

## Query parameters

- `codeChallengeMethod` 'S256' | 'plain', required
- `codeChallenge` string, required

## Response `200`

A successful response.

- UserSSOTokenWithPKCEGetResponse
  - `token` string
  - `expiry` integer

---

[API](https://skmtc.dev/deputy/apis/deputy-v2-api.md) - [All operations](https://skmtc.dev/deputy/apis/deputy-v2-api/llms.txt) - [OpenAPI document](https://skmtc.dev/deputy/apis/deputy-v2-api/revisions/78f0278f4608?raw)
