Authentication
Browser Session Authentication
The Admin UI uses the JWT-based cookie session model. After login, Revisium sets three cookies:
| Cookie | Type | Path | Default lifetime | Purpose |
|---|---|---|---|---|
rev_at | httpOnly JWT access token | / | 30 minutes | Authenticates browser requests to core, generated APIs, and the Admin UI backend |
rev_rt | httpOnly opaque refresh token | /api/auth/ | 7 days | Rotates the browser session through /api/auth/refresh |
rev_session | readable presence flag | / | 7 days | Lets the Admin UI know a session may still be alive; it is not a credential |
rev_session=1 can outlive rev_at. That is expected: the access cookie is short-lived, while the refresh cookie and presence flag use the longer session lifetime. The Admin UI can then refresh the session without storing bearer tokens in localStorage.
Cookie Secure and SameSite attributes are controlled by COOKIE_SECURE and COOKIE_SAMESITE; proxy and credentialed CORS behavior depends on TRUST_PROXY and CORS_ORIGIN. See Deployment authentication.
Login
The login GraphQL mutation still returns an accessToken for API clients, but browser login also sets the auth cookies on the response.
mutation {
login(data: { username: "admin", password: "admin" }) {
accessToken
expiresIn
}
}
Refresh And Logout
Browser session refresh is cookie-driven:
curl -X POST http://localhost:8080/api/auth/refresh \
-H "Cookie: rev_rt=<refresh-cookie>" \
-i
The refresh endpoint reads only the rev_rt cookie; it does not require rev_at to be present or valid. This lets the browser recover after the access cookie expires while rev_session still exists. On success, Revisium rotates the refresh token and returns new Set-Cookie headers for rev_at, rev_rt, and rev_session. Missing, invalid, or expired rev_rt clears the browser session cookies and returns unauthorized.
A retry with the same refresh token inside the default 30-second JWT_REFRESH_GRACE_PERIOD_MS window is treated as a duplicate refresh attempt. Outside that window, Revisium treats the same token as refresh-token reuse, revokes the refresh-token family, clears the browser session cookies, and rejects the request.
Logout revokes the refresh-token family when possible and clears all three cookies:
curl -X POST http://localhost:8080/api/auth/logout \
-H "Cookie: rev_rt=<refresh-cookie>" \
-i
/get-token And issueAccessToken
The Admin UI /get-token page calls the GraphQL issueAccessToken query from the current browser session:
query {
issueAccessToken {
accessToken
}
}
Use this when you are already logged in through cookies but need a short-lived bearer token for a CLI, script, or manual API call. issueAccessToken only works for JWT-authenticated sessions; API-key-authenticated requests cannot mint a user access token.
Bearer Token Authentication
Bearer tokens remain supported for programmatic access. Include the JWT in the Authorization header:
curl -X POST http://localhost:8080/graphql \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <accessToken>" \
-d '{"query": "{ me { id username } }"}'
For long-lived integrations, prefer API keys over copying a browser-issued access token.
Default Credentials
| Deployment | Username | Password |
|---|---|---|
| Docker Compose | admin | Value of ADMIN_PASSWORD env var (default: admin) |
Standalone (with --auth) | admin | admin |
| Cloud | Google/GitHub OAuth |
Do not use default credentials outside local development. Set ADMIN_PASSWORD before the first Docker or self-hosted start, replace standalone admin / admin immediately when --auth is used, and use OAuth or a secrets manager for production where possible.
OAuth 2.1
Used for MCP sessions and AI agent integrations. Clients connect via Streamable HTTP transport and authenticate per-session using the login tool.
MCP Authentication Flow
- Client connects to
/mcp - Session is established with
mcp-session-idheader - Client calls
logintool with username/password - All subsequent tool calls are authenticated for that session
# Manual MCP session (for debugging)
curl -X POST http://localhost:8080/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}'
API Keys
For programmatic access without user sessions. See the dedicated API Keys page.
Two types: Personal (act as you — for local dev/CLI) and Service (standalone identity — for CI/CD and integrations).
Quick start:
# Using X-Api-Key header
curl -H "X-Api-Key: rev_xxxxxxxxxxxxxxxxxxxx" \
http://localhost:8080/api/...
# Using Bearer header
curl -H "Authorization: Bearer rev_xxxxxxxxxxxxxxxxxxxx" \
http://localhost:8080/api/...
Session Security
rev_atis stateless; refresh tokens are stored server-side and rotate on refreshrev_rtis httpOnly and scoped to/api/auth/rev_sessionis readable by the Admin UI but carries only the literal value1- MCP sessions are isolated — each connection has its own auth state
- By default, all API endpoints (except login) require authentication. Public projects allow unauthenticated read access to generated endpoints