Security & Auth Model
Admin accounts, sessions, API keys, scopes, and audit.
bigRAG's auth model has two credential types, one scope system, and an immutable audit log. This page is the high-level map; the API shapes live under API Reference → Authentication.
The two credentials
| Credential | Used by | Lifetime | Revocation |
|---|---|---|---|
| Session cookie | admin UI, browser flows | BIGRAG_SESSION_EXPIRY_HOURS (default 7 days) | /v1/auth/logout, /v1/auth/logout-all, or cleanup sweeper |
API key (bigrag_sk_…) | SDKs, backend services, CI | Indefinite unless expires_at set | DELETE /v1/admin/api-keys/{id} or active: false |
First-run setup
A fresh install has no users. The server exposes exactly one unauthenticated admin-capable endpoint: POST /v1/auth/setup. It works once. After the first admin exists, subsequent calls return 409 and every admin endpoint requires auth.
The admin UI walks through this at http://localhost:3000/setup.
Roles
Two roles only. RBAC is intentionally coarse — fine-grained control lives on API keys via scopes.
| Role | Can |
|---|---|
admin | Everything: users, keys, collections, webhooks, audit |
member | Read /v1/auth/me, read/write own /v1/auth/preferences, log out |
member accounts are useful for admin UI users who need a read-only pane of glass.
Browser origin checks
Session-cookie mutating requests must include an Origin header that matches the API origin or one of the configured BIGRAG_CORS_ORIGINS. This protects the direct-CORS admin UI from cross-site request forgery while still allowing API-key clients to use normal bearer authentication.
Session-only endpoints
A session cookie is strictly stronger than an API key. The following endpoints refuse API keys (even admin-scoped ones) to prevent a compromised key from escalating:
/v1/admin/users/**/v1/admin/api-keys/**/v1/admin/audit/**/v1/admin/webhooks/**/v1/admin/embedding-presets/**/v1/auth/preferencesPOST /v1/auth/passwordPOST /v1/auth/logout-all
If you need to automate any of these, proxy through a trusted service that holds a dedicated admin account and uses session auth internally.
Scopes on API keys
Scopes are resource:action pairs. A key without scopes has full access; a key with scopes is restricted to the union of those patterns. * is a wildcard.
collection:read # GET /v1/collections, GET /v1/collections/{name}, stats
collection:write # POST, PUT collections
collection:delete # DELETE collections, truncate
document:upload # POST /v1/collections/{name}/documents, batch upload, upload sessions
document:read # GET documents, chunks, elements, batch get/status, /v1/documents/{id}
document:delete # DELETE documents, batch delete
query:read # POST /query, /batch/query, /collections/{name}/query
chat:read # GET /v1/chat/question-suggestions
chat:write # POST /v1/chat, POST /v1/chat/question-suggestions
vector:write # POST /v1/collections/{name}/vectors/upsert
vector:delete # POST /v1/collections/{name}/vectors/delete
audit:read # GET /v1/usage
*:* # equivalent to no scopesMissing-scope calls return 403 with {"detail": "API key missing required scope: <scope>"}.
Collection-pinned keys apply that pin consistently, including the global document-read helpers under /v1/documents/{id}.
Collections created with tenant_field require that field in upload metadata, raw vector metadata, query filters, and chat filters. Missing tenant constraints return 400 before retrieval.
Audit log
Every state-changing admin action writes a row to audit_log with actor, IP, user-agent, resource, and metadata. Reads don't. Entries are immutable.
- Read:
GET /v1/admin/audit - Filter:
actor,action,resource_type,start_date,end_date - Pipe to SIEM: scrape on a schedule or run
logout-all+ audit export on thesession.*events
The Audit API Reference lists the full action vocabulary.
RAG access log
RAG calls write a non-blocking row to access_log with actor/API-key context when available, method, path, route, status, latency, IP, user-agent, collection context, and safe endpoint metadata. This covers query, batch query, vector mutation, and evaluation calls. Admin UI refreshes, admin reads, collection listing, and other control-plane traffic are excluded. Raw request bodies, prompts, document content, and credentials are not stored.
- Overview:
GET /v1/admin/access/overview - Rows:
GET /v1/admin/access/logs - Retention: cleanup removes access-log rows older than 90 days by default
Passwords
- Argon2id hashed at rest, re-hashed transparently on login when older params are detected
- Minimum 8 characters (enforced at
/setup, user create, and password change) - Changing a password calls
logout-allfor that user - The server refuses to return any hash or key — only
has_password/has_api_keyflags where relevant
Production posture
Run with BIGRAG_ENV=prod — the server refuses to boot if:
BIGRAG_SESSION_COOKIE_SECUREisfalseBIGRAG_HOSTbinds publicly withoutBIGRAG_ALLOW_PUBLIC_BIND_IN_PROD=trueBIGRAG_SESSION_COOKIE_DOMAINis set without trusted proxiesBIGRAG_MASTER_KEYis unset- Postgres is still using the shipped
bigrag:bigragdefault password
See Production for the full hardening checklist.
Anything holding an API key — CI runner, laptop, container image layer — can act as that key until you revoke it. Mint a key per service, set expires_at, and rotate on any suspicion.