Copy the prompt and send it to an AI to generate the OAuth2.0 integration code

OAuth 2.0 Integration Guide

CZL Connect provides the standard OAuth 2.0 Authorization Code flow.
In the CZL Connect admin console, client authentication comes in two types:

  • secret
  • none

A secret client supports both standard parameter-passing methods at the protocol level: client_secret_basic and client_secret_post.
When the client authentication method is none, the authorization code exchange must use PKCE.

Scope

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

Server-side apps can store client_secret safely.
Desktop apps, mobile apps, and browser frontends cannot keep client_secret confidential, so they should use PKCE.

Authentication Methods

secret

A CZL Connect secret client supports both of the following standard OAuth 2.0 methods.

client_secret_basic

The client sends client_id and client_secret through HTTP Basic authentication.

Authorization: Basic BASE64(CLIENT_ID:CLIENT_SECRET)

client_secret_post

The client sends client_id and client_secret in an application/x-www-form-urlencoded request body.

client_id=YOUR_CLIENT_ID
client_secret=YOUR_CLIENT_SECRET

none

The client does not send client_secret.
PKCE is required in this mode.

PKCE

PKCE is for clients that cannot store client_secret securely.
The flow works as follows:

  1. The client generates a high-entropy random string, code_verifier
  2. The client computes code_challenge = BASE64URL(SHA256(code_verifier))
  3. The authorization request includes code_challenge and code_challenge_method=S256
  4. The token request includes code_verifier

CZL Connect currently supports only S256.

Endpoints

EndpointURL
Authorization endpointhttps://connect.czl.net/oauth2/authorize
Token endpointhttps://connect.czl.net/api/oauth2/token
UserInfo endpointhttps://connect.czl.net/api/oauth2/userinfo
User emails endpointhttps://connect.czl.net/api/oauth2/user/emails

Authorization Request

Basic Parameters

ParameterRequiredDescription
response_typeYesAlways code
client_idYesThe client ID of your app
redirect_uriYesThe redirect URI
scopeNoThe requested scope
stateNoClient state parameter; always send it
upstream_providersNoRestricts the available upstream providers, comma-separated
promptNonone requests silent authentication; see "Silent Authentication"
code_challengeRequired with PKCEThe PKCE challenge
code_challenge_methodRequired with PKCEAlways S256

Traditional Client

https://connect.czl.net/oauth2/authorize?
  response_type=code
  &client_id=YOUR_CLIENT_ID
  &redirect_uri=YOUR_REDIRECT_URI
  &scope=read
  &state=RANDOM_STATE_VALUE

Public Client + PKCE

https://connect.czl.net/oauth2/authorize?
  response_type=code
  &client_id=YOUR_CLIENT_ID
  &redirect_uri=YOUR_REDIRECT_URI
  &scope=read
  &state=RANDOM_STATE_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/oauth2/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/oauth2/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/oauth2/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

Example Response

{
  "access_token": "ACCESS_TOKEN",
  "token_type": "bearer",
  "refresh_token": "REFRESH_TOKEN",
  "expires_in": 86400,
  "scope": "read"
}

Refresh Token

secret client: client_secret_post

POST https://connect.czl.net/api/oauth2/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/oauth2/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/oauth2/token
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token
&refresh_token=REFRESH_TOKEN
&client_id=YOUR_CLIENT_ID

UserInfo

Request

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

Response

{
  "id": 1,
  "username": "zhangsan",
  "nickname": "Zhang San",
  "email": "[email protected]",
  "avatar": "https://example.com/avatar.png",
  "groups": ["t0", "t1", "t2", "t3", "t4", "t5", "viewer", "admin"],
  "upstreams": []
}

Fields

FieldDescription
idUser ID
usernameUsername
nicknameUser nickname
emailUser email
avatarUser avatar URL
groupsThe user's groups as an array of strings, including the groups inherited from the user's level
upstreamsUpstream accounts linked to the user

User Emails Endpoint

Request

GET https://connect.czl.net/api/oauth2/user/emails
Authorization: Bearer ACCESS_TOKEN

Response

[
  {
    "email": "[email protected]",
    "verified": true,
    "primary": true,
    "visibility": "public"
  }
]

Restricting Upstream Providers

upstream_providers restricts which upstream providers are available during the authorization flow.

https://connect.czl.net/oauth2/authorize?
  response_type=code
  &client_id=YOUR_CLIENT_ID
  &redirect_uri=YOUR_REDIRECT_URI
  &scope=read
  &state=RANDOM_STATE_VALUE
  &upstream_providers=discourse,github

Common values:

  • discourse
  • github
  • google
  • qq
  • wechat

Silent Authentication (prompt=none)

prompt=none restores the login automatically when a page opens. If the user is already signed in to CZL Connect and has previously authorized your app, the whole flow runs without interaction: the browser redirects briefly and returns to redirect_uri with a new authorization code. If silent authentication cannot complete, CZL Connect shows no login or consent page and redirects back immediately with error parameters. Your app then decides what to do next: stay signed out, or start a normal interactive authorization.

https://connect.czl.net/oauth2/authorize?
  response_type=code
  &client_id=YOUR_CLIENT_ID
  &redirect_uri=YOUR_REDIRECT_URI
  &scope=read
  &state=RANDOM_STATE_VALUE
  &prompt=none

On failure, the redirect to redirect_uri carries error, error_description, and the original state:

errorMeaning
login_requiredThe user is not signed in to CZL Connect
consent_requiredThe user has not yet authorized this app (the first authorization must go through the interactive flow)
interaction_requiredUser interaction is required to continue (for example, the email is unverified or a required upstream account is not linked)
access_deniedThe user is not allowed to access this app, or the app's quota is full

Requirements:

  • Start the request with a top-level full-page navigation (location.href or a server-side 302). Do not use a hidden iframe: the CZL Connect session cookie is SameSite=Lax, so it is not sent inside an iframe and silent authentication always returns login_required
  • Typical use: when your app's local session expires, redirect once with prompt=none, and decide whether to show a "Sign in" button after you receive login_required
  • Do not start prompt=none again right after an error redirect, to avoid a redirect loop
  • prompt=none cannot be combined with other prompt values

Migrating to PKCE

To migrate from the traditional client_secret mode to PKCE, you usually only need to change the following:

  1. Change the client authentication method to none in the CZL Connect admin console
  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 UserInfo endpoint, redirect URI, scope, and authorization endpoint stay the same.

Security Requirements

  • Use client_secret only in server-side apps that can keep secrets confidential
  • Desktop apps, mobile apps, and browser frontends must not embed client_secret
  • Public clients must use PKCE
  • Always generate state on the client and verify it on return
  • Your app must still store access_token and refresh_token securely
  • Only S256 is currently supported