Open source / Rust / MIT Field guide / indexed
Field guide / Auth APIReviewable source / main

Auth API

Session authentication for the portal and API: local and Entra ID/OIDC sign-in and sign-out flows, plus pre-login status, session, and role reads. The sign-in endpoints and pre-login reads are deliberately auth-exempt.

14 routes

Response metadata: x-api-version, x-request-id, and traceresponse apply to normal routed responses and are omitted from the per-operation header tables below.

GET/api/auth/entra/authorize-url

public accessno bearer auth required

Begins a browser sign-in.

Persists (state, nonce, pkce_verifier, binding) via the single-use oidc_login_states store, then returns the tenant authorize URL plus the per-browser binding as JSON. The binding is ALSO set as the HttpOnly mode-selected binding cookie for direct same-origin browser callers; the portal server function (which cannot forward upstream Set-Cookie headers) reads the JSON field and sets an identical cookie on its own response. The binding value never reaches page JavaScript either way. Mandatory shared source/global admission precedes PostgreSQL; serialized DB-time cleanup and provider/global quotas precede entropy generation. A 429 carries a bounded Retry-After response header.

Permissions

Access classCredentialScoping
publicNo user or agent bearer token is required. Operation-specific proof, when present, is documented below.No authenticated-principal scope is applied to this operation.

HTTP request

GET https://<your-host>/api/auth/entra/authorize-url

Path parameters

This operation has no path parameters.

Query parameters

This operation has no query parameters.

Request headers

NameTypeRequirementDescription
traceparentstringOptionalOptional correlation input. When the second dash-separated segment has 32 characters, Ryuki reuses it as the request correlation identifier; this is not full W3C validation.

Request body

This operation does not accept a request body.

Response

StatusDescriptionBody
200OKValue

200 response body

Structure: Value.

NameTypeRequirementDescription
authorize_urlJSON valueRequiredValue of authorize_url returned in the response body.
bindingJSON valueRequiredValue of binding returned in the response body.

200 response headers

NameTypeRequirementDescription
Set-CookiestringOptionalAuthentication/session cookie emitted on the successful branch that establishes or clears browser state.

Errors

JSON failures use one of the platform error envelopes and include the request correlation metadata when routing reaches the API middleware. See Errors for the exact shapes, authentication failures, retry guidance, and transport-level exceptions.

Examples

Request

curl --silent --show-error --globoff \
  --request GET \
  'https://<your-host>/api/auth/entra/authorize-url'

Schematic response body

Illustrative shape generated from the extracted field types, not a recorded live response. Values are placeholders; null marks a field whose type could not be resolved.

Success status: 200

{
  "authorize_url": null,
  "binding": null
}

GET/api/auth/entra/callback

public accessno bearer auth required

Completes a browser sign-in.

Flow (mirrors the generic OIDC callback): 1. Gate on auth mode + SSO config, then on DB availability. 2. If the IdP returned ?error=, redirect to /?auth_error=1 (the error text is never forwarded). 3. Require code and state. 4. Consume the state row (single-use, expiry-checked) and verify the per-browser binding cookie. 5. Exchange the code (PKCE public client — no secret). 6. Validate the id_token (RS256 sig + iss/aud/exp/nbf + nonce) and extract identity + roles. 7. Mint the SAME persisted session shape local login mints (aligned row-expiry and cookie Max-Age), set the mode-selected session cookie, and 302-redirect to / (hardcoded — no open-redirect surface).

Permissions

Access classCredentialScoping
publicNo user or agent bearer token is required. Operation-specific proof, when present, is documented below.No authenticated-principal scope is applied to this operation.

HTTP request

GET https://<your-host>/api/auth/entra/callback

Path parameters

This operation has no path parameters.

Query parameters

NameTypeRequirementDescription
codestringOptionalAuthorization code returned by the identity provider; required together with state on the successful callback path.
statestringOptionalSingle-use state returned by the identity provider; required together with code on the successful callback path.
errorstringOptionalIdentity-provider error code. When present, the callback follows the sanitized error-redirect path instead of the code-exchange path.
error_descriptionstringOptionalOptional provider error detail. It is accepted for protocol compatibility but is never forwarded to the browser.

Request headers

NameTypeRequirementDescription
CookiestringOptionalRequired on the successful code + state callback path: the browser must return the HttpOnly __Host-entra_login_csrf binding cookie set by login initiation. The provider-error redirect path does not require it. Explicit loopback HTTP uses the compatibility name entra_login_csrf.
traceparentstringOptionalOptional correlation input. When the second dash-separated segment has 32 characters, Ryuki reuses it as the request correlation identifier; this is not full W3C validation.

Request body

This operation does not accept a request body.

Response

StatusDescriptionBody
302FoundNo response body

302 response headers

NameTypeRequirementDescription
Cache-ControlstringRequiredThe handler directly marks this response no-store, preventing persistence or idempotency replay of the returned value.
LocationstringRequiredRedirect target selected by the authentication flow.

Errors

JSON failures use one of the platform error envelopes and include the request correlation metadata when routing reaches the API middleware. See Errors for the exact shapes, authentication failures, retry guidance, and transport-level exceptions.

Examples

Request

curl --silent --show-error --globoff \
  --request GET \
  --header 'Cookie: __Host-entra_login_csrf=<browser-binding>' \
  'https://<your-host>/api/auth/entra/callback?code=<code>&state=<state>'

GET/api/auth/local/decision

request access

Auth local decision.

Permissions

Access classCredentialScoping
requestAn authenticated session or API bearer token is required.The access class is enforced first; site and environment scopes narrow resources on scoped operations.

HTTP request

GET https://<your-host>/api/auth/local/decision

Path parameters

This operation has no path parameters.

Query parameters

This operation has no query parameters.

Request headers

NameTypeRequirementDescription
AuthorizationstringOptionalHuman credential alternative: supply one Bearer rys_... session token, ryk_... API token, or validated identity-provider JWT here. Do not combine it with X-Ryuki-Session-Id or the session cookie; conflicting carriers fail closed.
X-Ryuki-Session-IdstringOptionalOpaque rys_... session-token carrier used by the portal for mutations. Administrative session UUIDs cannot authenticate. Supply exactly one credential carrier per request.
traceparentstringOptionalOptional correlation input. When the second dash-separated segment has 32 characters, Ryuki reuses it as the request correlation identifier; this is not full W3C validation.

Request body

This operation does not accept a request body.

Response

StatusDescriptionBody
200OKValue

200 response body

Structure: Value.

NameTypeRequirementDescription
authenticationModestringRequiredValue of authenticationMode returned in the response body.
configuredForProductionbooleanRequiredValue of configuredForProduction returned in the response body.
entraGroupsConfiguredbooleanRequiredValue of entraGroupsConfigured returned in the response body.
requiredProductionProviderstringRequiredValue of requiredProductionProvider returned in the response body.
roleJSON valueRequiredValue of role returned in the response body.
actionstringRequiredValue of action returned in the response body.
allowedbooleanRequiredValue of allowed returned in the response body.
decisionstringRequiredValue of decision returned in the response body.
reasonstringRequiredValue of reason returned in the response body.

Errors

JSON failures use one of the platform error envelopes and include the request correlation metadata when routing reaches the API middleware. See Errors for the exact shapes, authentication failures, retry guidance, and transport-level exceptions.

Examples

Request

curl --silent --show-error --globoff \
  --request GET \
  --header 'Authorization: Bearer <token>' \
  'https://<your-host>/api/auth/local/decision'

Schematic response body

Illustrative shape generated from the extracted field types, not a recorded live response. Values are placeholders; null marks a field whose type could not be resolved.

Success status: 200

{
  "authenticationMode": "<string>",
  "configuredForProduction": false,
  "entraGroupsConfigured": false,
  "requiredProductionProvider": "<string>",
  "role": null,
  "action": "<string>",
  "allowed": false,
  "decision": "<string>",
  "reason": "<string>"
}

POST/api/auth/local/login

public accessno bearer auth required

Auth local login.

Permissions

Access classCredentialScoping
publicNo user or agent bearer token is required. Operation-specific proof, when present, is documented below.No authenticated-principal scope is applied to this operation.

HTTP request

POST https://<your-host>/api/auth/local/login

Path parameters

This operation has no path parameters.

Query parameters

This operation has no query parameters.

Request headers

NameTypeRequirementDescription
Content-TypestringRequiredRequired by the resolved Axum Json<T> request extractor; send application/json.
traceparentstringOptionalOptional correlation input. When the second dash-separated segment has 32 characters, Ryuki reuses it as the request correlation identifier; this is not full W3C validation.

Request body

JSON structure: LocalLoginRequest.

NameTypeRequirementDescription
usernamestringRequiredValue of username in the JSON request body.
passwordstringRequiredValue of password in the JSON request body.

Response

No successful response schema was extracted for this operation.

Error responses use the platform ApiError body (error, message, optional detail).

Errors

JSON failures use one of the platform error envelopes and include the request correlation metadata when routing reaches the API middleware. See Errors for the exact shapes, authentication failures, retry guidance, and transport-level exceptions.

Examples

Request

curl --silent --show-error --globoff \
  --request POST \
  --header 'Content-Type: application/json' \
  --data '{"username":"<string>","password":"<string>"}' \
  'https://<your-host>/api/auth/local/login'

POST/api/auth/local/logout

public accessno bearer auth required

Auth local logout.

Permissions

Access classCredentialScoping
publicNo user or agent bearer token is required. Operation-specific proof, when present, is documented below.No authenticated-principal scope is applied to this operation.

HTTP request

POST https://<your-host>/api/auth/local/logout

Path parameters

This operation has no path parameters.

Query parameters

This operation has no query parameters.

Request headers

NameTypeRequirementDescription
traceparentstringOptionalOptional correlation input. When the second dash-separated segment has 32 characters, Ryuki reuses it as the request correlation identifier; this is not full W3C validation.

Request body

This operation does not accept a request body.

Response

No successful response schema was extracted for this operation.

Errors

JSON failures use one of the platform error envelopes and include the request correlation metadata when routing reaches the API middleware. See Errors for the exact shapes, authentication failures, retry guidance, and transport-level exceptions.

Examples

Request

curl --silent --show-error --globoff \
  --request POST \
  'https://<your-host>/api/auth/local/logout'

GET/api/auth/local/me

request access

Auth local me.

Permissions

Access classCredentialScoping
requestAn authenticated session or API bearer token is required.The access class is enforced first; site and environment scopes narrow resources on scoped operations.

HTTP request

GET https://<your-host>/api/auth/local/me

Path parameters

This operation has no path parameters.

Query parameters

This operation has no query parameters.

Request headers

NameTypeRequirementDescription
AuthorizationstringOptionalHuman credential alternative: supply one Bearer rys_... session token, ryk_... API token, or validated identity-provider JWT here. Do not combine it with X-Ryuki-Session-Id or the session cookie; conflicting carriers fail closed.
X-Ryuki-Session-IdstringOptionalOpaque rys_... session-token carrier used by the portal for mutations. Administrative session UUIDs cannot authenticate. Supply exactly one credential carrier per request.
traceparentstringOptionalOptional correlation input. When the second dash-separated segment has 32 characters, Ryuki reuses it as the request correlation identifier; this is not full W3C validation.

Request body

This operation does not accept a request body.

Response

StatusDescriptionBody
200OKValue

For 200, the known response body type is Value. Its field schema is unavailable, so no JSON shape is inferred.

Error responses use the platform ApiError body (error, message, optional detail).

Errors

JSON failures use one of the platform error envelopes and include the request correlation metadata when routing reaches the API middleware. See Errors for the exact shapes, authentication failures, retry guidance, and transport-level exceptions.

Examples

Request

curl --silent --show-error --globoff \
  --request GET \
  --header 'Authorization: Bearer <token>' \
  'https://<your-host>/api/auth/local/me'

GET/api/auth/local/roles

request access

Auth local roles.

Permissions

Access classCredentialScoping
requestAn authenticated session or API bearer token is required.The access class is enforced first; site and environment scopes narrow resources on scoped operations.

HTTP request

GET https://<your-host>/api/auth/local/roles

Path parameters

This operation has no path parameters.

Query parameters

This operation has no query parameters.

Request headers

NameTypeRequirementDescription
AuthorizationstringOptionalHuman credential alternative: supply one Bearer rys_... session token, ryk_... API token, or validated identity-provider JWT here. Do not combine it with X-Ryuki-Session-Id or the session cookie; conflicting carriers fail closed.
X-Ryuki-Session-IdstringOptionalOpaque rys_... session-token carrier used by the portal for mutations. Administrative session UUIDs cannot authenticate. Supply exactly one credential carrier per request.
traceparentstringOptionalOptional correlation input. When the second dash-separated segment has 32 characters, Ryuki reuses it as the request correlation identifier; this is not full W3C validation.

Request body

This operation does not accept a request body.

Response

StatusDescriptionBody
200OKValue

200 response body

Structure: Value.

NameTypeRequirementDescription
authenticationModestringRequiredValue of authenticationMode returned in the response body.
configuredForProductionbooleanRequiredValue of configuredForProduction returned in the response body.
entraGroupsConfiguredbooleanRequiredValue of entraGroupsConfigured returned in the response body.
requiredProductionProviderstringRequiredValue of requiredProductionProvider returned in the response body.
actionsarray<JSON value>RequiredValue of actions returned in the response body.
capabilityPolicystringRequiredValue of capabilityPolicy returned in the response body.
rolesJSON valueRequiredValue of roles returned in the response body.

Errors

JSON failures use one of the platform error envelopes and include the request correlation metadata when routing reaches the API middleware. See Errors for the exact shapes, authentication failures, retry guidance, and transport-level exceptions.

Examples

Request

curl --silent --show-error --globoff \
  --request GET \
  --header 'Authorization: Bearer <token>' \
  'https://<your-host>/api/auth/local/roles'

Schematic response body

Illustrative shape generated from the extracted field types, not a recorded live response. Values are placeholders; null marks a field whose type could not be resolved.

Success status: 200

{
  "authenticationMode": "<string>",
  "configuredForProduction": false,
  "entraGroupsConfigured": false,
  "requiredProductionProvider": "<string>",
  "actions": [],
  "capabilityPolicy": "<string>",
  "roles": null
}

POST/api/auth/login

public accessno bearer auth required

Auth login.

Permissions

Access classCredentialScoping
publicNo user or agent bearer token is required. Operation-specific proof, when present, is documented below.No authenticated-principal scope is applied to this operation.

HTTP request

POST https://<your-host>/api/auth/login

Path parameters

This operation has no path parameters.

Query parameters

This operation has no query parameters.

Request headers

NameTypeRequirementDescription
traceparentstringOptionalOptional correlation input. When the second dash-separated segment has 32 characters, Ryuki reuses it as the request correlation identifier; this is not full W3C validation.

Request body

This operation does not accept a request body.

Response

StatusDescriptionBody
200OKValue

For 200, the known response body type is Value. Its field schema is unavailable, so no JSON shape is inferred.

Error responses use the platform ApiError body (error, message, optional detail).

Errors

JSON failures use one of the platform error envelopes and include the request correlation metadata when routing reaches the API middleware. See Errors for the exact shapes, authentication failures, retry guidance, and transport-level exceptions.

Examples

Request

curl --silent --show-error --globoff \
  --request POST \
  'https://<your-host>/api/auth/login'

POST/api/auth/logout

public accessno bearer auth required

The Entra/mock logout path.

B4: takes ONLY the request headers (no Json(body)), so a client-supplied session_id can never terminate a victim's session. The caller's own id is resolved from their credential surface and only that session is deleted. Idempotent: an expired/missing session still returns 200.

Permissions

Access classCredentialScoping
publicNo user or agent bearer token is required. Operation-specific proof, when present, is documented below.No authenticated-principal scope is applied to this operation.

HTTP request

POST https://<your-host>/api/auth/logout

Path parameters

This operation has no path parameters.

Query parameters

This operation has no query parameters.

Request headers

NameTypeRequirementDescription
traceparentstringOptionalOptional correlation input. When the second dash-separated segment has 32 characters, Ryuki reuses it as the request correlation identifier; this is not full W3C validation.

Request body

This operation does not accept a request body.

Response

No successful response schema was extracted for this operation.

Errors

JSON failures use one of the platform error envelopes and include the request correlation metadata when routing reaches the API middleware. See Errors for the exact shapes, authentication failures, retry guidance, and transport-level exceptions.

Examples

Request

curl --silent --show-error --globoff \
  --request POST \
  'https://<your-host>/api/auth/logout'

GET/api/auth/oidc/callback

public accessno bearer auth required

OIDC authorization-code callback handler.

Full flow (matches the spec):

  1. Gate on oidc.enabled.
  2. Gate on DB availability.
  3. If the IdP returned ?error=, redirect to /?auth_error=1.
  4. Require code and state.
  5. Consume the state row (single-use, expiry-checked).
  6. Exchange the code for an id_token.
  7. Validate the id_token (sig + claims + nonce).
  8. Mint a session row.
  9. Set the session cookie and redirect to /.

Permissions

Access classCredentialScoping
publicNo user or agent bearer token is required. Operation-specific proof, when present, is documented below.No authenticated-principal scope is applied to this operation.

HTTP request

GET https://<your-host>/api/auth/oidc/callback

Path parameters

This operation has no path parameters.

Query parameters

NameTypeRequirementDescription
codestringOptionalAuthorization code returned by the identity provider; required together with state on the successful callback path.
statestringOptionalSingle-use state returned by the identity provider; required together with code on the successful callback path.
errorstringOptionalIdentity-provider error code. When present, the callback follows the sanitized error-redirect path instead of the code-exchange path.
error_descriptionstringOptionalOptional provider error detail. It is accepted for protocol compatibility but is never forwarded to the browser.

Request headers

NameTypeRequirementDescription
CookiestringOptionalRequired on the successful code + state callback path: the browser must return the HttpOnly __Host-oidc_login_csrf binding cookie set by login initiation. The provider-error redirect path does not require it. Explicit loopback HTTP uses the compatibility name oidc_login_csrf.
traceparentstringOptionalOptional correlation input. When the second dash-separated segment has 32 characters, Ryuki reuses it as the request correlation identifier; this is not full W3C validation.

Request body

This operation does not accept a request body.

Response

StatusDescriptionBody
302FoundNo response body

302 response headers

NameTypeRequirementDescription
Cache-ControlstringRequiredThe handler directly marks this response no-store, preventing persistence or idempotency replay of the returned value.
LocationstringRequiredRedirect target selected by the authentication flow.
Set-CookiestringOptionalAuthentication/session cookie emitted on the successful branch that establishes or clears browser state.

Errors

JSON failures use one of the platform error envelopes and include the request correlation metadata when routing reaches the API middleware. See Errors for the exact shapes, authentication failures, retry guidance, and transport-level exceptions.

Examples

Request

curl --silent --show-error --globoff \
  --request GET \
  --header 'Cookie: __Host-oidc_login_csrf=<browser-binding>' \
  'https://<your-host>/api/auth/oidc/callback?code=<code>&state=<state>'

GET/api/auth/oidc/login

public accessno bearer auth required

Initiate oidc login.

Permissions

Access classCredentialScoping
publicNo user or agent bearer token is required. Operation-specific proof, when present, is documented below.No authenticated-principal scope is applied to this operation.

HTTP request

GET https://<your-host>/api/auth/oidc/login

Path parameters

This operation has no path parameters.

Query parameters

This operation has no query parameters.

Request headers

NameTypeRequirementDescription
traceparentstringOptionalOptional correlation input. When the second dash-separated segment has 32 characters, Ryuki reuses it as the request correlation identifier; this is not full W3C validation.

Request body

This operation does not accept a request body.

Response

StatusDescriptionBody
302FoundNo response body

302 response headers

NameTypeRequirementDescription
LocationstringRequiredRedirect target selected by the authentication flow.
Set-CookiestringOptionalAuthentication/session cookie emitted on the successful branch that establishes or clears browser state.

Errors

JSON failures use one of the platform error envelopes and include the request correlation metadata when routing reaches the API middleware. See Errors for the exact shapes, authentication failures, retry guidance, and transport-level exceptions.

Examples

Request

curl --silent --show-error --globoff \
  --request GET \
  'https://<your-host>/api/auth/oidc/login'

GET/api/auth/roles

public accessno bearer auth required

Auth roles.

Permissions

Access classCredentialScoping
publicNo user or agent bearer token is required. Operation-specific proof, when present, is documented below.No authenticated-principal scope is applied to this operation.

HTTP request

GET https://<your-host>/api/auth/roles

Path parameters

This operation has no path parameters.

Query parameters

This operation has no query parameters.

Request headers

NameTypeRequirementDescription
traceparentstringOptionalOptional correlation input. When the second dash-separated segment has 32 characters, Ryuki reuses it as the request correlation identifier; this is not full W3C validation.

Request body

This operation does not accept a request body.

Response

StatusDescriptionBody
200OKValue

For 200, the known response body type is Value. Its field schema is unavailable, so no JSON shape is inferred.

Errors

JSON failures use one of the platform error envelopes and include the request correlation metadata when routing reaches the API middleware. See Errors for the exact shapes, authentication failures, retry guidance, and transport-level exceptions.

Examples

Request

curl --silent --show-error --globoff \
  --request GET \
  'https://<your-host>/api/auth/roles'

GET/api/auth/session

public accessno bearer auth required

Auth session.

Permissions

Access classCredentialScoping
publicNo user or agent bearer token is required. Operation-specific proof, when present, is documented below.No authenticated-principal scope is applied to this operation.

HTTP request

GET https://<your-host>/api/auth/session

Path parameters

This operation has no path parameters.

Query parameters

This operation has no query parameters.

Request headers

NameTypeRequirementDescription
traceparentstringOptionalOptional correlation input. When the second dash-separated segment has 32 characters, Ryuki reuses it as the request correlation identifier; this is not full W3C validation.

Request body

This operation does not accept a request body.

Response

StatusDescriptionBody
200OKValue

For 200, the known response body type is Value. Its field schema is unavailable, so no JSON shape is inferred.

Errors

JSON failures use one of the platform error envelopes and include the request correlation metadata when routing reaches the API middleware. See Errors for the exact shapes, authentication failures, retry guidance, and transport-level exceptions.

Examples

Request

curl --silent --show-error --globoff \
  --request GET \
  'https://<your-host>/api/auth/session'

GET/api/auth/status

public accessno bearer auth required

Auth status.

Permissions

Access classCredentialScoping
publicNo user or agent bearer token is required. Operation-specific proof, when present, is documented below.No authenticated-principal scope is applied to this operation.

HTTP request

GET https://<your-host>/api/auth/status

Path parameters

This operation has no path parameters.

Query parameters

This operation has no query parameters.

Request headers

NameTypeRequirementDescription
traceparentstringOptionalOptional correlation input. When the second dash-separated segment has 32 characters, Ryuki reuses it as the request correlation identifier; this is not full W3C validation.

Request body

This operation does not accept a request body.

Response

StatusDescriptionBody
200OKValue

200 response body

Structure: Value.

NameTypeRequirementDescription
tenant_configuredJSON valueRequiredValue of tenant_configured returned in the response body.
client_configuredJSON valueRequiredValue of client_configured returned in the response body.
enabledJSON valueRequiredValue of enabled returned in the response body.
instanceJSON valueRequiredValue of instance returned in the response body.

Errors

JSON failures use one of the platform error envelopes and include the request correlation metadata when routing reaches the API middleware. See Errors for the exact shapes, authentication failures, retry guidance, and transport-level exceptions.

Examples

Request

curl --silent --show-error --globoff \
  --request GET \
  'https://<your-host>/api/auth/status'

Schematic response body

Illustrative shape generated from the extracted field types, not a recorded live response. Values are placeholders; null marks a field whose type could not be resolved.

Success status: 200

{
  "tenant_configured": null,
  "client_configured": null,
  "enabled": null,
  "instance": null
}
Last updated 2026-07-16 · Generated from the API route registrations.