Web App with Authorization Code and PKCE

1. Discover configuration

const issuer = 'https://account.example.com'
const configuration = await fetch(
  `${issuer}/.well-known/openid-configuration`,
).then((response) => response.json())

Cache discovery metadata for a bounded period and refresh it normally. Do not hardcode a JWKS key.

2. Create state, nonce, and PKCE

Generate cryptographically random state, nonce, and code_verifier values. Store them in a secure, short-lived transaction bound to the browser session. Derive code_challenge as base64url-encoded SHA-256 of the verifier.

3. Redirect to authorization

const url = new URL(configuration.authorization_endpoint)
url.search = new URLSearchParams({
  client_id: 'YOUR_CLIENT_ID',
  redirect_uri: 'https://app.example.com/api/auth/callback',
  response_type: 'code',
  scope: 'openid profile email offline_access',
  state,
  nonce,
  code_challenge: codeChallenge,
  code_challenge_method: 'S256',
  ui_locales: 'fa en',
  ui_theme: 'dark',
}).toString()

window.location.assign(url)

The hosted Raha Account pages own login, signup, MFA, account selection, and consent.

4. Handle the callback

Reject the callback if state does not exactly match the stored transaction. Exchange the code from your backend:

curl -X POST "$TOKEN_ENDPOINT" \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  --data-urlencode 'grant_type=authorization_code' \
  --data-urlencode 'client_id=YOUR_CLIENT_ID' \
  --data-urlencode 'code=RETURNED_CODE' \
  --data-urlencode 'redirect_uri=https://app.example.com/api/auth/callback' \
  --data-urlencode 'code_verifier=ORIGINAL_CODE_VERIFIER'

Validate the ID token signature and claims, including iss, aud, exp, and nonce. Keep refresh tokens and confidential-client secrets on the server.

5. End the session

Use the discovery document's end-session endpoint with id_token_hint, an allow-listed post_logout_redirect_uri, and optional state. Raha Account supports front-channel and back-channel client logout notifications where configured.

Was this page helpful?