Authentication
Every /v1/admin/* request requires an authenticated session. DVARA supports three authentication modes for the admin surface; they are mutually exclusive and configured at DVARA Flightdeck startup. Pick the mode that matches your identity strategy and issue tokens accordingly.
| Mode | When to use | How to authenticate API calls |
|---|---|---|
| Built-in email/password (default) | Local dev, small teams, no existing IdP | Personal access token (dvara_pat_…) created from Settings → Tokens after a browser login |
| OIDC / JWT | Existing Keycloak, Okta, Auth0, or Azure AD | JWT obtained from the IdP's token endpoint, passed as Authorization: Bearer <jwt> |
| SAML 2.0 | Enterprise SSO — ADFS, Okta SAML, Azure AD SAML | Personal access token created after a browser SAML login (SAML has no automation flow, so PATs bridge the gap) |
All three modes land in the same RBAC engine after authentication, so the role model applies identically regardless of how you signed in.
Personal access tokens (built-in auth and SAML)
A personal access token carries the same roles as the user who created it. Tokens are issued from the DVARA Flightdeck:
- Sign in at
http://localhost:8090/login - Open Settings → Tokens from the user menu in the top-right
- Click New Token, pick a name (e.g.
terraform-prod) and an optional expiry - Copy the
dvara_pat_…value from the confirmation banner — it is shown exactly once and never retrievable again - Use it on every admin API call:
curl -s http://localhost:8090/v1/admin/tenants \
-H "Authorization: Bearer dvara_pat_<your-token>"
Rotate a token by creating a new one, updating your automation's secret store, and revoking the old token from the same Settings → Tokens page. Revocation is immediate and irreversible.
Storing PATs. Treat PATs like provider API keys — store them in a secrets manager (HashiCorp Vault, AWS Secrets Manager, GitHub Actions secrets, HashiCorp Nomad variables), never in source control, and scope them to one automation pipeline each so you can rotate without a coordinated outage across every caller.
OIDC / JWT
When the DVARA Flightdeck is configured with dvara.flightdeck.security.oidc.issuer-uri, the admin API validates every incoming JWT against the issuer's JWKS endpoint. Your automation obtains a token from the IdP using the client credentials grant (or any other grant your IdP exposes) and passes it as a Bearer header:
# 1. Get a token from the IdP
TOKEN=$(curl -s -X POST https://keycloak.example.com/realms/dvara/protocol/openid-connect/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials&client_id=dvara-terraform&client_secret=..." \
| jq -r .access_token)
# 2. Call the admin API with the token
curl -s http://localhost:8090/v1/admin/tenants \
-H "Authorization: Bearer $TOKEN"
Roles come from a JWT claim (default roles, configurable via dvara.flightdeck.security.oidc.role-claim with dot-notation support for nested claims like realm_access.roles). Tenant ID comes from dvara.flightdeck.security.oidc.tenant-claim (default tenant_id). Mixing platform and tenant roles on one token is disallowed and rejected at login time.
The same OIDC properties work with any compliant IdP (Keycloak, Microsoft Entra ID, Okta, Auth0, etc.). For provider-specific setup steps, consult your IdP's OIDC client documentation alongside the property reference in Setup & Login.
SAML 2.0
SAML is a browser-only protocol, so automation pipelines can't authenticate directly. Instead, a human signs into DVARA Flightdeck once via SAML SSO, creates a personal access token from Settings → Tokens, and hands that token to the automation. The PAT carries the SAML user's roles and respects the same RBAC rules as any other session.
For SAML configuration — SP metadata, ACS URL, attribute mapping, auto-provisioning — see the SAML properties block in Setup & Login.
Role-based access control
DVARA enforces URL-pattern RBAC on every /v1/admin/* endpoint. The six built-in roles split into three platform roles and three tenant-scoped roles:
| Role | Scope | Typical capabilities |
|---|---|---|
owner | Platform — full access across every tenant | Tenants, routes, policies, budgets, credentials, compliance reports, everything |
policy-admin | Platform — governance resources | Policies, routes, guardrails, MCP servers, audit, approval queue |
billing-admin | Platform — FinOps resources | Pricing, costs, budgets, chargeback reports |
admin | Tenant — full access within the caller's own tenant | Tenant metadata, API keys, team members |
developer | Tenant — read-heavy within the caller's own tenant | Create API keys, read usage, dry-run policies |
viewer | Tenant — read-only within the caller's own tenant | Dashboards, audit, usage, no writes |
Cross-tenant guard. A tenant-scoped caller that passes another tenant's tenant_id is always rejected with 403 and a TENANT_SCOPE_VIOLATION audit event. Only an omitted tenant_id parameter is silently narrowed to the caller's own tenant. There is no way for a tenant user to read or write another tenant's data, even with a crafted request.
Catch-all default. The RBAC engine requires owner for any admin path not explicitly granted to another role, so new endpoints are locked down by default. If you extend the admin surface with a custom controller, it's unreachable until you add an explicit grant.
Disabling RBAC (not recommended). Setting dvara.flightdeck.security.rbac.enabled=false falls back to authenticated() for every admin endpoint — any valid token grants full access. Only use this in local development or when the admin API is fronted by another access-control layer.
Errors
| Status | Shape | When |
|---|---|---|
401 Unauthorized | {"error": {"type": "authentication_error", "code": "UNAUTHORIZED", "message": "..."}} | No token, expired token, or bad signature |
403 Forbidden | {"error": {"type": "authorization_error", "code": "FORBIDDEN", "message": "..."}} | Token is valid but the caller's role doesn't cover this endpoint |
Clients should handle 401 by refreshing the token (if the IdP supports it) or prompting the user to re-authenticate, and 403 by surfacing the missing role to the caller instead of retrying.
Related
- Setup & Login — configure built-in auth, OIDC, or SAML at DVARA Flightdeck startup
- Multi-Tenancy — full role model and tenant isolation guarantees