OIDC clients¶
An OIDC client is the OAuth2 / OpenID Connect face of an application — it defines how a relying party obtains tokens from the realm's issuer.
What it is¶
OIDC clients speak OAuth2 and OpenID Connect against the realm issuer (https://<host>/realms/<realm>). Each client is either:
- Confidential — holds a client secret and authenticates at the token endpoint (server-side apps, backends).
- Public — has no secret and must use PKCE (SPAs, mobile, native apps).
Grant types¶
Clients can be enabled for any of:
authorization_code(with PKCE) — interactive loginrefresh_token— long-lived sessionsclient_credentials— service-to-service (uses a service account)password— resource owner password (legacy; avoid for new apps)device— device authorization grant for input-constrained devicesCIBA— Client-Initiated Backchannel Authenticationtoken-exchange(RFC 8693) — exchange a token for another, including on-behalf-of delegation where an agent acts for a user (see Agent authorization)
Key settings¶
The newer per-client settings (JWK Set by value, signed userinfo, request URIs, session management, login initiation, logo/policy/terms links, and the opt-in implicit and hybrid flows) are on OIDC client settings and OpenID Connect flows.
- Redirect URIs — exact-match callback URLs for the code flow.
- Web origins — allowed CORS origins; these are enforced at runtime, not cosmetic.
- Scopes — the client scopes this client may request.
- Per-client keys / JWKS — client-specific signing keys or a registered JWKS URL for
private_key_jwt. The JWKS URL must behttps(http://localhost/http://127.0.0.1only in thedevprofile); the token endpoint fetches it through the egress guard without following redirects, and a client stored with anhttpJWKS URL cannot authenticate outsidedev. - Service accounts — the identity used for
client_credentials; can hold its own roles. - Authorization Services (UMA) — fine-grained resource/policy/permission model for resource-server authorization.
- Advanced token settings — token lifetimes, subject-claim override, audience handling, and resource indicators (RFC 8707) to narrow a token's audience to a specific resource server.
- Agent binding — an OIDC client can be the issuance binding for an agent (non-human identity); the agent authenticates through this client (e.g.
client_credentialsor a workload JWT) and its tokens gain thenhimarker and lifecycle gate.
Warning
Public clients must use PKCE. Never embed a client secret in a browser app, SPA, or mobile binary — register it as a public client instead.
In the console¶
OIDC clients live under Manage, either via the parent application or the clients list. Clients are always shown by their application/client display name, never by a raw UUID.
Common tasks¶
- Register a client — open Applications → Create (or Clients → Create), pick confidential or public, and add redirect URIs and web origins.
- Enable grant types — turn on only the flows the client actually uses.
- Assign scopes — attach the client scopes that define which claims appear in tokens.
- Configure a service account — for
client_credentials, enable the service account and assign it roles. - Enable Authorization Services — define resources, policies, and permissions for UMA-style authorization.
- Rotate the secret / keys — regenerate the client secret or rotate per-client keys when needed.
- Who may act for users here (the client's Credentials tab) — the RFC 8693 token-exchange allow-list: the clients that may exchange a user's token for one whose
audienceis this client, shown in plain words ("Customer portal may act for its users at Orders API"). The default is none. The console warns about an allowed client that lacks thetoken-exchangegrant, or that no longer exists.
Tip
Dynamic Client Registration is supported at /connect/register for programmatic, on-the-fly client creation per RFC 7591.
Manage over the API¶
All client management is available under /admin/realms/{realm}/clients. The examples below assume you have set $HELIX_URL / $REALM and logged in — see Authenticating to the API.
List clients¶
[
{ "clientId": "helix-cli", "name": "HelixIAM CLI", "publicClient": true, "grantTypes": ["authorization_code","refresh_token","urn:ietf:params:oauth:grant-type:device_code"], … },
{ "clientId": "helix-console", "name": "Helix Admin Console", "publicClient": true, "grantTypes": ["authorization_code"], … }
]
Create a confidential client¶
publicClient: false mints a client secret, returned once in the create response.
# Refresh CSRF after any GET, then POST (see the auth guide for the helper)
CSRF=$(awk '($6=="__Host-XSRF-TOKEN"||$6=="XSRF-TOKEN")&&$7~/^r1\./{t=$7} END{print t}' cookies.txt)
curl -s -b cookies.txt \
-H "Content-Type: application/json" \
-H "X-XSRF-TOKEN: $CSRF" \
-d '{
"clientId": "acme-web",
"name": "Acme Web",
"publicClient": false,
"grantTypes": ["authorization_code", "refresh_token"],
"redirectUris": ["https://app.example.com/callback"],
"webOrigins": ["https://app.example.com"]
}' \
"$HELIX_URL/admin/realms/$REALM/clients"
{
"id": "19d467c0-fe42-46e2-a708-eb2c450cb17a",
"clientId": "acme-web",
"name": "Acme Web",
"publicClient": false,
"secret": "CyISWxzvGCkhqUld5Pm-GCVtcYvCtSu3",
"grantTypes": ["authorization_code", "refresh_token"],
"redirectUris": ["https://app.example.com/callback"],
"webOrigins": ["https://app.example.com"],
"scopes": []
}
Save the secret now
The secret is shown only in the create (and secret-rotation) response. Store it in your secret manager immediately. A public client ("publicClient": true) has no secret and must use PKCE.
Update or delete a client¶
Use the returned id for subsequent calls:
# Update (e.g. add a redirect URI) — PUT the full desired state
curl -s -b cookies.txt -X PUT \
-H "Content-Type: application/json" -H "X-XSRF-TOKEN: $CSRF" \
-d '{ "clientId": "acme-web", "redirectUris": ["https://app.example.com/callback", "https://app.example.com/silent-renew"] }' \
"$HELIX_URL/admin/realms/$REALM/clients/19d467c0-fe42-46e2-a708-eb2c450cb17a"
# Delete — returns 204 No Content
curl -s -b cookies.txt -X DELETE -H "X-XSRF-TOKEN: $CSRF" \
"$HELIX_URL/admin/realms/$REALM/clients/19d467c0-fe42-46e2-a708-eb2c450cb17a"
Full endpoint set¶
Method & path (under /admin/realms/{realm}) |
Purpose |
|---|---|
GET /clients · POST /clients |
List / create clients |
GET · PUT · DELETE /clients/{id} |
Read / update / delete a client |
GET · PUT /clients/{clientId}/token-exchange |
The clients allowed to exchange tokens for this client ({"allowedClients": [...]}; clientId is the OAuth client id) |
GET · POST /clients/{id}/authz/resources |
UMA resources |
GET · POST /clients/{id}/authz/policies |
UMA policies |
GET · POST /clients/{id}/authz/permissions |
UMA permissions |
POST /realms/{realm}/connect/register (protocol endpoint, initial access token) |
Dynamic Client Registration |
See the API reference for the complete schema of every field.