Skip to content

Auth API

Endpoints for OIDC authentication and session management. These endpoints are only available after setup is complete (instance state is ready). Calling them before setup returns 409 Conflict with code setup_incomplete.

OIDC Start

Initiate an OIDC authorization code flow. Returns an authorization URL to redirect the user to.

GET /v1/auth/oidc/start

Authentication: None (public)

Query parameters

ParameterRequiredDescription
redirect_uriNoCustom redirect URI (defaults to standard callback)

Response 200 OK

json
{
  "authorization_url": "https://accounts.google.com/o/oauth2/v2/auth?client_id=...&redirect_uri=...&state=...&nonce=...",
  "state": "abc123-csrf-state-token"
}
FieldTypeDescription
authorization_urlstringFull authorization URL to redirect the user to
statestringCSRF state token for validating the callback

The daemon generates a PKCE challenge (S256), CSRF state token, and nonce internally. Pending auth entries expire after 10 minutes.

Error responses

StatusCodeDescription
409setup_incompleteSetup is not yet complete
429too_many_pendingToo many pending auth requests (limit: 1000)
500oidc_not_configuredOIDC configuration is missing
502oidc_discovery_errorFailed to perform OIDC discovery

OIDC Callback

Complete the OIDC authorization code flow. Exchanges the authorization code for tokens, verifies the ID token, and creates a user session.

POST /v1/auth/oidc/callback

Authentication: None (public)

Request body

json
{
  "code": "4/0AX4XfWh...",
  "state": "abc123-csrf-state-token"
}
FieldTypeRequiredDescription
codestringYesAuthorization code from the IdP callback
statestringYesCSRF state token (must match the value from oidc/start)

Response 200 OK

json
{
  "session_token": "user_session_abc123...",
  "expires_at": 1738886400,
  "user": {
    "email": "[email protected]",
    "oidc_subject": "110123456789012345678",
    "user_id": "user_def456",
    "role": "developer",
    "avatar_url": "https://lh3.googleusercontent.com/..."
  }
}
FieldTypeDescription
session_tokenstringUser session token (24-hour TTL)
expires_atintegerSession expiry as Unix epoch (seconds)
userobjectAuthenticated user details

Error responses

StatusCodeDescription
400invalid_stateUnknown or expired OIDC state parameter
400auth_expiredOIDC authorization request expired (10-minute TTL)
403user_not_foundNo user account for this email/identity
409setup_incompleteSetup is not yet complete
500decryption_errorFailed to decrypt stored OIDC client secret
500session_errorFailed to create session
500store_errorDatabase operation failed
502oidc_discovery_errorFailed to perform OIDC discovery
502token_exchange_errorFailed to exchange authorization code
502missing_id_tokenIdP did not return an ID token
502id_token_verification_errorID token verification failed
502missing_emailID token missing email claim

INFO

Users must be invited before they can sign in. If a user authenticates successfully with the OIDC provider but has no account in Oore CI, the callback returns 403 with code user_not_found.


Local Login

Create a loopback-only local session without OIDC.

POST /v1/auth/local/login

Authentication: None (public)

Request body

json
{
  "email": "[email protected]"
}

email is optional when exactly one active user exists.

Response 200 OK

Returns LocalLoginResponse.

Error responses

StatusCodeDescription
400email_requiredMultiple active users exist and email was omitted
403mode_restrictedSetup is incomplete while runtime mode is remote
403local_login_loopback_requiredLocal login attempted from non-loopback source
403user_not_foundNo active user matched the provided email

WARNING

Local login is always loopback-only. Any non-loopback access path must use External Access (runtime_mode=remote) and OIDC.


Logout

Invalidate the current user session.

POST /v1/auth/logout

Authentication: User session (Bearer)

Response 200 OK

json
{
  "ok": true
}

Error responses

StatusCodeDescription
401missing_authAuthorization header not provided
401invalid_sessionSession token is invalid or already expired

Self-hosted mobile CI, built for Flutter.