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
| Parameter | Type | Required | Description |
|---|---|---|---|
| redirectUri | string | No | OAuth redirect URI override; falls back to server config |
| mode | string | No | json (default) returns JSON with the authorization URL; redirect issues a 302 redirect |
| postLoginRedirect | string | No | Relative path (/…) to redirect to after login completes |
| tenantId | string | No | Tenant 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
| Status | Condition |
|---|---|
| 400 | Auth provider not configured, missing redirectUri, or provider error |
| 404 | Auth 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
| Parameter | Type | Required | Description |
|---|---|---|---|
| code | string | Yes | Authorization code from the OAuth provider |
| state | string | Yes | Opaque state token issued during /start |
Behavior
- Validates and consumes the OAuth state token.
- Exchanges the authorization
codefor access/refresh tokens via the provider. - Creates or retrieves a user and identity record.
- For Discord providers, grants
TenantAdminto the first user in a tenant with no existing permissions. - Issues a session cookie. If the original
/startincluded apostLoginRedirect, 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
| Status | Condition |
|---|---|
| 400 | Missing code/state, invalid or expired state, provider mismatch, missing tenantId, missing redirectUri, or exchange error |
| 404 | Auth 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
| Field | Type | Required | Description |
|---|---|---|---|
| username | string | Yes | Login username |
| password | string | Yes | Login password |
| tenantId | string | No | Tenant identifier (alternative to header) |
Behavior
- Resolves the provider configuration for the tenant.
- Delegates authentication to the provider adapter.
- Creates or retrieves a user and identity record.
- For the
localprovider, automatically grants theTenantAdminrole to the default admin user. - Issues a session cookie and returns the session object.
Response (200)
{
"session": { "sessionId": "...", "user": { "userId": "...", "tenantId": "...", "displayName": "...", "email": "..." }, "permissionKeys": [...] }
}
Errors
| Status | Condition |
|---|---|
| 400 | Missing username/password, missing tenantId, invalid credentials, or provider error |
| 404 | Auth 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
| Parameter | Type | Required | Description |
|---|---|---|---|
| redirectTo | string | No | Same-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
| Status | Condition |
|---|---|
| 401 | No 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
| Field | Type | Required | Description |
|---|---|---|---|
| tenantId | string | Yes | Target tenant identifier |
Response (200)
{
"session": { "sessionId": "...", "user": { "userId": "...", "tenantId": "...", "displayName": "...", "email": "..." }, "permissionKeys": [...] }
}
Errors
| Status | Condition |
|---|---|
| 400 | Missing tenantId or error resolving permissions |
| 401 | Unauthenticated |