Authentication endpoints¶
Login, logout and the caller's identity.
| Endpoint | Summary |
|---|---|
POST /v1/auth/login |
Log in with a local user |
POST /v1/auth/logout |
End the current session |
GET /v1/auth/providers |
How the sign-in page offers to sign in |
GET /v1/auth/oidc/login |
Start a sign-in with the identity provider |
GET /v1/auth/oidc/callback |
The provider's redirect back after sign-in |
GET /v1/me |
The caller's identity, role and CSRF token |
POST /v1/me/password |
Change the caller's own password |
Log in with a local user¶
POST /v1/auth/login
Accepts: no authentication.
Checks the username and password and starts a session. The response sets the session
cookie kerf_session (HttpOnly; SameSite=Strict; Path=/, plus Secure behind TLS) and
returns the CSRF token the client sends as X-CSRF-Token on every write made with the
session. Every other /v1 endpoint needs a session or a bearer token.
A wrong password and an unknown, disabled or locked user all get the same 401 (code
invalid_credentials), so the answer never tells whether a user exists. After repeated
failures a user is locked for a while; while locked even the right password gets that
401. Attempts are rate limited per username and per client address (the last
X-Forwarded-For entry, else the connection): 429 code rate_limited with
Retry-After and one message for both.
Request body (application/json, required): LoginRequest
Responses
| Status | Description | Body |
|---|---|---|
200 |
Logged in. | Me |
400 |
The request is malformed or fails validation. | Problem |
401 |
Missing or invalid bearer token. | Problem |
429 |
Too many attempts (code rate_limited). |
Problem |
End the current session¶
POST /v1/auth/logout
Accepts: no authentication.
Revokes the session and clears the cookie. A live session needs its X-CSRF-Token
(403 csrf_invalid without it). Without a live session (none, expired or revoked) it
only clears the cookie. Always 204 otherwise; returns no data.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
X-CSRF-Token |
header | string | Required when the request is authenticated with the session cookie. |
Responses
| Status | Description | Body |
|---|---|---|
204 |
Logged out. | |
403 |
The token is not allowed to access this cluster, the role is too low (role_forbidden), or the caller's team bindings do not cover the endpoint or the workload (scope_forbidden, docs/teams.md). |
Problem |
How the sign-in page offers to sign in¶
GET /v1/auth/providers
Accepts: no authentication.
Whether every local user may sign in with a password (local; false = only the
break-glass admin) and the identity provider, when one is configured.
Responses
| Status | Description | Body |
|---|---|---|
200 |
The sign-in options. | AuthProviders |
Start a sign-in with the identity provider¶
GET /v1/auth/oidc/login
Accepts: no authentication.
Redirects the browser to the provider (OpenID Connect authorization code flow with PKCE,
state and nonce) and sets the kerf_oidc cookie (HttpOnly; SameSite=Lax;
Path=/v1/auth/oidc, 10 minutes) that binds the sign-in to this browser. When the provider
cannot be reached it redirects to /login?error=oidc_unavailable instead.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
next |
query | string | Path to return to after sign-in (same site only; anything else gives /). |
Responses
| Status | Description | Body |
|---|---|---|
302 |
To the provider, or to the sign-in page with an error. | |
404 |
Unknown cluster. | Problem |
429 |
Too many attempts (code rate_limited). |
Problem |
The provider's redirect back after sign-in¶
GET /v1/auth/oidc/callback
Accepts: no authentication.
Needs the kerf_oidc cookie of the browser that started the sign-in and its one-time
state. Exchanges the code (with the PKCE verifier), verifies the ID token and its nonce,
maps the groups to a role, creates or updates the user and starts a session (cookie
kerf_session, as POST /v1/auth/login), then redirects to next. On failure it redirects
to /login?error=<code>: oidc_expired (unknown, used or expired state; another browser),
oidc_failed (the provider refused or the exchange failed), oidc_denied (no mapped group
and no default role, or a disabled user), oidc_conflict (the username belongs to a local
user), oidc_unavailable.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
code |
query | string | |
state |
query | string | |
error |
query | string | Set by the provider when the sign-in failed there. |
Responses
| Status | Description | Body |
|---|---|---|
302 |
To next with a session cookie, or to the sign-in page with an error. |
|
404 |
Unknown cluster. | Problem |
The caller's identity, role and CSRF token¶
GET /v1/me
Accepts: session of a user with role viewer or higher or bearer token with role ui.
For a session: the user, the role and the CSRF token. For a bearer token (ui or admin):
the token's role mapped to a user role (ui → viewer, admin → admin) and no CSRF
token (bearer requests need none). The UI uses it to decide what to show.
Responses
| Status | Description | Body |
|---|---|---|
200 |
Identity. | Me |
401 |
Missing or invalid bearer token. | Problem |
403 |
The token is not allowed to access this cluster, the role is too low (role_forbidden), or the caller's team bindings do not cover the endpoint or the workload (scope_forbidden, docs/teams.md). |
Problem |
Change the caller's own password¶
POST /v1/me/password
Accepts: session of a user with role viewer or higher.
Requires the current password. Clears mustChangePassword. Other sessions of the user are
revoked; the current one stays.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
X-CSRF-Token |
header | string | Required when the request is authenticated with the session cookie. |
Request body (application/json, required): PasswordChange
Responses
| Status | Description | Body |
|---|---|---|
204 |
Password changed. | |
400 |
The request is malformed or fails validation. | Problem |
401 |
Missing or invalid bearer token. | Problem |
403 |
The token is not allowed to access this cluster, the role is too low (role_forbidden), or the caller's team bindings do not cover the endpoint or the workload (scope_forbidden, docs/teams.md). |
Problem |
409 |
The change conflicts with the current state (code says how). |
Problem |
429 |
Too many attempts (code rate_limited). |
Problem |