Client Management
An OIDC client (also called a Relying Party) represents an application that delegates authentication to YorAuth. You must register a client before initiating any authorization flows. Each client has a unique client_id, an encrypted client_secret, a list of allowed redirect URIs, and a set of permitted scopes.
Client secrets are server-side credentials. Store your client_secret securely and never include it in client-side code. Token exchange (/oidc/token) must happen from a server. Use PKCE for public clients. See Security Best Practices.
Dashboard API
Client management is available through the dashboard API at:
/api/dashboard/applications/{applicationId}/oidc-clients
These routes require Sanctum cookie authentication (dashboard session).
List Clients
GET /api/dashboard/applications/{applicationId}/oidc-clients
Returns all OIDC clients for the application, ordered by creation date (newest first).
Response:
{
"data": [
{
"id": "01932c4d-...",
"client_id": "oidc_AbCdEfGhIjKlMnOpQrStUvWxYz012345",
"name": "My Web App",
"description": "Production web application",
"logo_url": "https://yourapp.com/logo.png",
"redirect_uris": [
"https://yourapp.com/auth/callback"
],
"allowed_scopes": ["openid", "profile", "email"],
"is_active": true,
"branding": {
"name": "My Web App",
"logo_url": null,
"color": "#1a73e8",
"background": "#ffffff"
},
"created_at": "2026-02-01T12:00:00+00:00",
"updated_at": "2026-02-01T12:00:00+00:00"
}
]
}
Create a Client
POST /api/dashboard/applications/{applicationId}/oidc-clients
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Human-readable client name (max 255 chars) |
redirect_uris | array | Yes | One or more allowed redirect URIs (must be valid URLs) |
description | string | No | Optional description (max 1000 chars) |
logo_url | string | No | URL to the client's logo |
allowed_scopes | array | No | Scopes this client may request. Defaults to ["openid", "profile", "email"]. Allowed values: openid, profile, email, offline_access |
curl -X POST https://api.yorauth.com/api/dashboard/applications/{applicationId}/oidc-clients \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-b "sanctum_session=your-session-cookie" \
-d '{
"name": "My Web App",
"redirect_uris": [
"https://yourapp.com/auth/callback"
],
"allowed_scopes": ["openid", "profile", "email", "offline_access"],
"description": "Production web application"
}'
const response = await fetch(
`https://api.yorauth.com/api/dashboard/applications/${applicationId}/oidc-clients`,
{
method: 'POST',
credentials: 'include',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
},
body: JSON.stringify({
name: 'My Web App',
redirect_uris: ['https://yourapp.com/auth/callback'],
allowed_scopes: ['openid', 'profile', 'email', 'offline_access'],
description: 'Production web application',
}),
}
);
const { data } = await response.json();
// data.client_secret is only returned on creation — store it securely
console.log(data.client_id, data.client_secret);
Response (201 Created):
{
"data": {
"id": "01932c4d-...",
"client_id": "oidc_AbCdEfGhIjKlMnOpQrStUvWxYz012345",
"client_secret": "64-character-random-secret",
"name": "My Web App",
"description": "Production web application",
"redirect_uris": ["https://yourapp.com/auth/callback"],
"allowed_scopes": ["openid", "profile", "email", "offline_access"],
"is_active": true,
"branding": { ... }
}
}
The client_secret is only returned once, at creation time. Store it securely (e.g., as an environment variable). If you lose it, use the rotate-secret endpoint to generate a new one.
Update a Client
PUT /api/dashboard/applications/{applicationId}/oidc-clients/{clientId}
All fields are optional — only send fields you want to change.
Request body (partial update supported):
| Field | Type | Description |
|---|---|---|
name | string | New display name |
redirect_uris | array | Replace the full list of redirect URIs |
description | string | Update description |
logo_url | string | Update logo URL |
allowed_scopes | array | Replace the allowed scopes list |
is_active | boolean | Enable or disable the client |
Response (200 OK): Returns the updated client object (same format as list, without client_secret).
Delete a Client
DELETE /api/dashboard/applications/{applicationId}/oidc-clients/{clientId}
Response: 204 No Content
Deleting a client does not immediately revoke existing tokens, but future token exchanges and refresh operations for that client will fail because the client no longer exists.
Rotate Client Secret
Use this endpoint if your client_secret has been compromised or needs periodic rotation.
POST /api/dashboard/applications/{applicationId}/oidc-clients/{clientId}/rotate-secret
No request body required.
Response (200 OK):
{
"data": {
"client_secret": "new-64-character-random-secret"
}
}
Rotating the secret immediately invalidates the previous secret. Update your application's environment variable before rotating to avoid downtime, or rotate with a brief overlap by updating your application first.
Update Client Branding
Customize the appearance of the hosted login and consent screens for this client.
PUT /api/dashboard/applications/{applicationId}/oidc-clients/{clientId}/branding
Request body:
| Field | Type | Description |
|---|---|---|
brand_name | string | Display name on the login screen |
brand_logo_url | string (URL) | Logo shown on login/consent screens |
brand_color | string | Primary color hex code (e.g. #1a73e8) |
brand_background | string | Background color hex code (e.g. #ffffff) |
Branding cascades: client-level settings override application-level settings, which override YorAuth defaults.
V1 API (JWT Auth)
For server-side management using a JWT access token with the oidc:manage permission:
GET /api/v1/applications/{applicationId}/oidc/clients
POST /api/v1/applications/{applicationId}/oidc/clients
GET /api/v1/applications/{applicationId}/oidc/clients/{clientId}
PUT /api/v1/applications/{applicationId}/oidc/clients/{clientId}
DELETE /api/v1/applications/{applicationId}/oidc/clients/{clientId}
These endpoints have the same request/response structure as the dashboard API, with the exception that secret rotation and branding updates are only available through the dashboard API.
curl -X POST https://api.yorauth.com/api/v1/applications/{applicationId}/oidc/clients \
-H "Authorization: Bearer your-api-key" \
-H "Content-Type: application/json" \
-d '{
"name": "My App",
"redirect_uris": ["https://yourapp.com/callback"]
}'
const response = await fetch(
`https://api.yorauth.com/api/v1/applications/${applicationId}/oidc/clients`,
{
method: 'POST',
headers: {
'Authorization': 'Bearer your-api-key',
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: 'My App',
redirect_uris: ['https://yourapp.com/callback'],
}),
}
);
Client Fields Reference
| Field | Description |
|---|---|
id | Internal UUID — use this as {clientId} in management API calls |
client_id | Public client identifier — use this in authorization requests (prefix oidc_) |
client_secret | Secret used to authenticate at the token endpoint (only returned on creation/rotation) |
redirect_uris | Exact URI matching — trailing slashes and query strings must match exactly |
allowed_scopes | Scopes that users may be asked to grant for this client |
is_active | Inactive clients are rejected at the authorization endpoint |
Error Responses
| Code | HTTP | Description |
|---|---|---|
OIDC_CLIENT_NOT_FOUND | 404 | Client does not exist or does not belong to this application |
| Validation errors | 422 | Field-level validation failures |