Skip to main content

Authentication

Base path: /auth

GET /auth/:provider/start

Begin an OAuth flow for the given provider (e.g. discord, local).

Auth: None required (public) Tenant: Resolved from x-tenant-id header, tenantId query param, body field, or session

Query Parameters

ParameterTypeRequiredDescription
redirectUristringNoOAuth redirect URI override; falls back to server config
modestringNojson (default) returns JSON with the authorization URL; redirect issues a 302 redirect
postLoginRedirectstringNoRelative path (/…) to redirect to after login completes
tenantIdstringNoTenant identifier (alternative to header)

Response — mode json (200)

{
"authorizationUrl": "https://discord.com/oauth2/authorize?...",
"state": "<opaque>"
}

Response — mode redirect (302)

Redirects the browser to the provider's authorization URL.

Errors

StatusCondition
400Auth provider not configured, missing redirectUri, or provider error
404Auth provider configuration not found for the given tenant/provider

GET /auth/:provider/callback

OAuth callback endpoint. Exchanges the authorization code for tokens, creates or links the user identity, and issues a session.

Auth: None required (called by the OAuth provider) Tenant: Recovered from the OAuth state token

Query Parameters

ParameterTypeRequiredDescription
codestringYesAuthorization code from the OAuth provider
statestringYesOpaque state token issued during /start

Behavior

  1. Validates and consumes the OAuth state token.
  2. Exchanges the authorization code for access/refresh tokens via the provider.
  3. Creates or retrieves a user and identity record.
  4. For Discord providers, grants TenantAdmin to the first user in a tenant with no existing permissions.
  5. Issues a session cookie. If the original /start included a postLoginRedirect, the response is a 302 redirect; otherwise returns JSON.

Response (200)

{
"session": { "sessionId": "...", "user": { "userId": "...", "tenantId": "...", "displayName": "...", "email": "..." }, "permissionKeys": [...] }
}

Response (302)

Redirects to the postLoginRedirect path when one was provided in the original /start call.

Errors

StatusCondition
400Missing code/state, invalid or expired state, provider mismatch, missing tenantId, missing redirectUri, or exchange error
404Auth provider configuration not found

POST /auth/:provider/login

Authenticate with username and password for credential-based providers (e.g. local).

Auth: None required Tenant: Resolved from x-tenant-id header, tenantId query/body, or session

Request Body

FieldTypeRequiredDescription
usernamestringYesLogin username
passwordstringYesLogin password
tenantIdstringNoTenant identifier (alternative to header)

Behavior

  1. Resolves the provider configuration for the tenant.
  2. Delegates authentication to the provider adapter.
  3. Creates or retrieves a user and identity record.
  4. For the local provider, automatically grants the TenantAdmin role to the default admin user.
  5. Issues a session cookie and returns the session object.

Response (200)

{
"session": { "sessionId": "...", "user": { "userId": "...", "tenantId": "...", "displayName": "...", "email": "..." }, "permissionKeys": [...] }
}

Errors

StatusCondition
400Missing username/password, missing tenantId, invalid credentials, or provider error
404Auth provider configuration not found

POST /auth/logout

Log out the current session (JSON response).

Auth: Session cookie (optional — clears whatever session exists)

Request Body

None.

Response (200)

{ "ok": true }

GET /auth/logout

Log out the current session and redirect.

Auth: Session cookie (optional)

Query Parameters

ParameterTypeRequiredDescription
redirectTostringNoSame-origin path to redirect to after logout. Must start with / and must not contain //. Defaults to /.

Response (302)

Clears the session cookie and redirects to the validated redirectTo path (or /).


GET /auth/me

Return the current authenticated session.

Auth: Session cookie required

Response (200)

{
"session": {
"sessionId": "...",
"user": { "userId": "...", "tenantId": "..." },
"permissionKeys": [...]
}
}

Errors

StatusCondition
401No active session (unauthenticated)

POST /auth/tenant

Switch the active tenant for the current session. Re-issues the session with permissions for the new tenant.

Auth: Session cookie required

Request Body

FieldTypeRequiredDescription
tenantIdstringYesTarget tenant identifier

Response (200)

{
"session": { "sessionId": "...", "user": { "userId": "...", "tenantId": "...", "displayName": "...", "email": "..." }, "permissionKeys": [...] }
}

Errors

StatusCondition
400Missing tenantId or error resolving permissions
401Unauthenticated