Authorization path
Redirect users to ZKAuth, complete identity verification, and receive a single-use authorization code.
OAuth authorization code integration for ZKAuth, aligned with live backend behavior and written for engineering teams shipping secure production flows.
Redirect users to ZKAuth, complete identity verification, and receive a single-use authorization code.
Perform backend-only code exchange at the token endpoint with strict validation and credential protection.
Verify JWT signature and claims, bind `sub` to local user records, then issue your own app session.
Provide these values before client onboarding:
Provisioning output (admin-managed or self-service):
| Actor | Role |
|---|---|
| User | Authenticates and approves consent |
| Client Frontend | Redirects browser to authorization endpoint |
| ZKAuth Identity | Performs identity checks and issues authorization code |
| Client Backend | Exchanges code for token and creates app session |
ZKAuth supports both enterprise admin-controlled provisioning and authenticated client-side self-service registration for application owners.
Security/Admin teams can create and rotate OAuth clients centrally from admin tooling and distribute credentials to app teams.
Client operators can login to the client dashboard and register their own OAuth app profile under their authenticated identity scope.
https://auth.zkauth.tech/api/oauth/authorize
Browser redirect endpoint (code flow)
https://api.zkauth.tech/api/oauth/token
Server-to-server code exchange
https://api.zkauth.tech/.well-known/jwks.json
Key discovery for JWT verification
Send client_id, redirect_uri, response_type=code, state, and optional PKCE params. Public clients require PKCE.
ZKAuth Identity UI handles login, checks session/cookies, and confirms authorization intent before issuing code.
Validate state exactly and extract the short-lived single-use authorization code.
POST grant_type=authorization_code, code, redirect_uri, client_id, client_secret, and code_verifier when PKCE is used.
Verify RS256 signature using JWKS, validate iss/aud/exp, link subject to local user, and issue your own app session.
| Parameter | Required | Notes |
|---|---|---|
| client_id | Yes | Issued by ZKAuth admin |
| redirect_uri | Yes | Must exactly match registered URI |
| response_type | Yes | Must be `code` |
| state | Yes | CSRF protection token from client |
| scope | Optional | Requested profile scope set |
| code_challenge | Public: Yes | PKCE S256 challenge |
| code_challenge_method | With PKCE | Use `S256` |
`POST /api/oauth/token` with JSON payload:
{
"grant_type": "authorization_code",
"code": "AUTH_CODE",
"redirect_uri": "https://client-app.com/auth/callback/zkauth",
"client_id": "YOUR_CLIENT_ID",
"client_secret": "YOUR_CLIENT_SECRET",
"code_verifier": "PKCE_VERIFIER_IF_USED"
}Response:
{
"access_token": "eyJhbGciOiJSUzI1NiIs...",
"token_type": "Bearer",
"expires_in": 900
}const authUrl = new URL('https://auth.zkauth.tech/api/oauth/authorize');
authUrl.searchParams.set('client_id', process.env.NEXT_PUBLIC_ZKAUTH_CLIENT_ID!);
authUrl.searchParams.set('redirect_uri', 'https://client-app.com/auth/callback/zkauth');
authUrl.searchParams.set('response_type', 'code');
authUrl.searchParams.set('state', state);
authUrl.searchParams.set('code_challenge', codeChallenge);
authUrl.searchParams.set('code_challenge_method', 'S256');
window.location.href = authUrl.toString();const tokenResp = await axios.post('https://api.zkauth.tech/api/oauth/token', {
grant_type: 'authorization_code',
code,
redirect_uri: 'https://client-app.com/auth/callback/zkauth',
client_id: process.env.ZKAUTH_CLIENT_ID,
client_secret: process.env.ZKAUTH_CLIENT_SECRET,
code_verifier
});
const accessToken = tokenResp.data.access_token;const claims = jwt.verify(accessToken, publicKey, {
algorithms: ['RS256'],
issuer: 'https://api.zkauth.tech',
audience: process.env.ZKAUTH_CLIENT_ID
});
// Stable user anchor
const zkauthSub = claims.sub;Start with protocol flow, align security assumptions, then execute rollout against this guide.