Copy the prompt and send it to an AI to generate the OIDC integration code

OIDC Integration Guide

CZL Connect provides OpenID Connect on top of the OAuth 2.0 Authorization Code flow.
It supports Discovery, JWKS, id_token, PKCE, and multiple client authentication methods.

Protocol Scope

OIDC adds identity authentication on top of OAuth 2.0.
For your app, the main differences are:

  • scope must include openid
  • The token response includes an id_token
  • You can fetch the configuration from the Discovery endpoint
  • You can fetch the signing public keys from the JWKS endpoint

Client Authentication Methods

Client typeRecommended authentication method
Server-side web appsecret
Desktop appnone + PKCE
Mobile appnone + PKCE
SPA / browser frontendnone + PKCE

A secret client in the CZL Connect admin console supports both standard OIDC/OAuth 2.0 parameter-passing methods: client_secret_basic and client_secret_post.
When the client authentication method is none, the authorization code exchange must use PKCE.

Discovery

Endpoint

EndpointURL
Discoveryhttps://connect.czl.net/.well-known/openid-configuration

Example

GET https://connect.czl.net/.well-known/openid-configuration

Response

{
  "issuer": "https://connect.czl.net",
  "authorization_endpoint": "https://connect.czl.net/oidc/authorize",
  "token_endpoint": "https://connect.czl.net/api/oidc/token",
  "userinfo_endpoint": "https://connect.czl.net/api/oidc/userinfo",
  "introspection_endpoint": "https://connect.czl.net/api/oidc/introspect",
  "jwks_uri": "https://connect.czl.net/api/oidc/jwks",
  "response_types_supported": ["code", "id_token", "code id_token"],
  "subject_types_supported": ["public"],
  "id_token_signing_alg_values_supported": ["RS256"],
  "scopes_supported": ["openid", "profile", "email"],
  "grant_types_supported": ["authorization_code", "refresh_token"],
  "response_modes_supported": ["query", "fragment"],
  "code_challenge_methods_supported": ["S256"],
  "token_endpoint_auth_methods_supported": ["client_secret_basic", "client_secret_post", "none"]
}

Authorization Request

Parameters

ParameterRequiredDescription
response_typeYesAlways code
client_idYesThe client ID
redirect_uriYesThe redirect URI
scopeYesMust include openid
stateNoState parameter; always send it
nonceNoRecommended; protects against replay attacks
promptNonone requests silent authentication and behaves as described in "Silent Authentication" in the OAuth 2.0 guide
code_challengeRequired with PKCEThe PKCE challenge
code_challenge_methodRequired with PKCEAlways S256

With prompt=none, if authorization cannot complete silently, CZL Connect redirects back to redirect_uri with error (login_required, consent_required, interaction_required, and so on) and state, and shows no interactive page. Start the request with a top-level full-page navigation, not an iframe (the session cookie is SameSite=Lax and is not sent inside an iframe). The supported values are listed in prompt_values_supported in Discovery.

Traditional Client

https://connect.czl.net/oidc/authorize?
  response_type=code
  &client_id=YOUR_CLIENT_ID
  &redirect_uri=YOUR_REDIRECT_URI
  &scope=openid profile email
  &state=RANDOM_STATE_VALUE
  &nonce=RANDOM_NONCE_VALUE

Public Client + PKCE

https://connect.czl.net/oidc/authorize?
  response_type=code
  &client_id=YOUR_CLIENT_ID
  &redirect_uri=YOUR_REDIRECT_URI
  &scope=openid profile email
  &state=RANDOM_STATE_VALUE
  &nonce=RANDOM_NONCE_VALUE
  &code_challenge=YOUR_CODE_CHALLENGE
  &code_challenge_method=S256

Token Request

Exchange an Authorization Code for Tokens

secret client: client_secret_post

POST https://connect.czl.net/api/oidc/token
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code
&code=AUTHORIZATION_CODE
&client_id=YOUR_CLIENT_ID
&client_secret=YOUR_CLIENT_SECRET
&redirect_uri=YOUR_REDIRECT_URI

secret client: client_secret_basic

POST https://connect.czl.net/api/oidc/token
Content-Type: application/x-www-form-urlencoded
Authorization: Basic BASE64(YOUR_CLIENT_ID:YOUR_CLIENT_SECRET)

grant_type=authorization_code
&code=AUTHORIZATION_CODE
&redirect_uri=YOUR_REDIRECT_URI

none + PKCE

POST https://connect.czl.net/api/oidc/token
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code
&code=AUTHORIZATION_CODE
&client_id=YOUR_CLIENT_ID
&redirect_uri=YOUR_REDIRECT_URI
&code_verifier=YOUR_CODE_VERIFIER

Response

{
  "access_token": "ACCESS_TOKEN",
  "id_token": "ID_TOKEN_JWT",
  "token_type": "bearer",
  "expires_in": 3600,
  "refresh_token": "REFRESH_TOKEN",
  "scope": "openid profile email"
}

ID Token

Example

{
  "jti": "UNIQUE_TOKEN_ID",
  "iss": "https://connect.czl.net",
  "sub": "1",
  "aud": "YOUR_CLIENT_ID",
  "exp": 1640995200,
  "iat": 1640991600,
  "nbf": 1640991600,
  "nonce": "RANDOM_NONCE_VALUE",
  "at_hash": "ACCESS_TOKEN_HASH",
  "name": "zhangsan",
  "email": "[email protected]",
  "email_verified": true,
  "picture": "https://example.com/avatar.png",
  "groups": ["t0", "t1", "t2", "t3", "t4", "t5", "viewer", "admin"]
}

Fields

FieldDescription
issIssuer
subUnique user identifier
audIntended client
expExpiration time
iatIssued-at time
nbfNot-before time
nonceThe nonce from the client's request
at_hashAccess token hash
groupsThe user's groups as an array of strings, including the groups inherited from the user's level

UserInfo

Request

GET https://connect.czl.net/api/oidc/userinfo
Authorization: Bearer ACCESS_TOKEN

Refresh Token

secret client: client_secret_post

POST https://connect.czl.net/api/oidc/token
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token
&refresh_token=REFRESH_TOKEN
&client_id=YOUR_CLIENT_ID
&client_secret=YOUR_CLIENT_SECRET

secret client: client_secret_basic

POST https://connect.czl.net/api/oidc/token
Content-Type: application/x-www-form-urlencoded
Authorization: Basic BASE64(YOUR_CLIENT_ID:YOUR_CLIENT_SECRET)

grant_type=refresh_token
&refresh_token=REFRESH_TOKEN

none

POST https://connect.czl.net/api/oidc/token
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token
&refresh_token=REFRESH_TOKEN
&client_id=YOUR_CLIENT_ID

Migrating to PKCE

To migrate from the traditional client_secret mode to PKCE, change the following:

  1. Change the client authentication method to none
  2. Add code_challenge and code_challenge_method=S256 to the authorization request
  3. Remove client_secret from the token request
  4. Add code_verifier to the token request

The scope, Discovery URL, JWKS URL, and UserInfo URL stay the same.

Validation Requirements

Your app must validate the following:

  • The id_token signature
  • iss
  • aud
  • exp
  • nonce

Security Requirements

  • scope must include openid
  • Use client_secret only in server-side apps that can keep secrets confidential
  • Public clients must use PKCE
  • Only S256 is currently supported
  • Desktop apps, mobile apps, and browser frontends must not embed client_secret