Skip to main content
Version: 1.8.0

Authenticate gateway calls

Your application needs a workspace identity before DVARA can apply that workspace's policy, PII action, budgets, limits, and audit attribution. The LLM and A2A Gateways use a DVARA workspace API key. The MCP Gateway uses a workspace API key by default and can also accept OAuth 2.1 access tokens when OAuth is enabled.

Send a workspace API key as a bearer token:

Authorization: Bearer gw_<your-key>

The key identifies the workspace on the request path. You do not send a workspace ID in the request body.

From 1.8.5, when a request has no bearer credential, DVARA reads an API key from the x-api-key header instead. That is the header Claude Code and the Anthropic SDKs send to /v1/messages. It is the same key either way, with the same scopes. The x-api-key header does not carry an OAuth access token.

When is a key required?​

SurfaceMissing-key behavior
LLM Gateway /v1/**Always requires a workspace key.
MCP Gateway /mcp/**Requires a workspace key by default. When MCP OAuth is enabled, it accepts OAuth access tokens alongside API keys by default; API keys can then be disabled for this plane.
A2A Gateway /a2a/**Always requires a workspace key. The plane runs in the Enterprise platform, with or without a licence.

The former dvara.llm-gateway.data-plane.require-api-key setting was removed in 1.8.0. Setting it to false refuses startup; setting it to true is tolerated only so an older deployment can start while you remove the dead setting. Missing, invalid, revoked, and expired keys return 401.

For issuer, audience, workspace, scope, PKCE, and client checks, see Authenticate MCP clients with OAuth 2.1.

How do you create a key?​

In the Open Source distribution, use the key-generation command shown in the Open Source quickstart, then put only the generated fingerprint in gateway.yaml.

In the Enterprise platform, open Identity → API Keys in the DVARA Flightdeck. The 1.8 Flightdeck selector can issue keys for the four LLM operation families. The workspace Flightdeck can also create a key, but it does not offer a scope selector: a key created there is unrestricted. The 1.8 UI does not provide a supported workflow for issuing a key narrowed to only MCP or A2A operations.

Copy the plaintext gw_... value when it is created and place it in the caller's secret store. DVARA shows the complete value once. If it is lost, create a replacement; do not try to recover it.

Which key value appears in governance evidence?​

DVARA separates the credential a caller presents from the identifier used for attribution:

ValueWhere it is used
Plaintext gw_... credentialAuthentication only. Keep it in the caller's secret store. DVARA does not write it to rate-limit, usage, cost, audit, or access-log records.
Opaque API-key IDRate limiting after repository resolution, policy and budget matching, token usage, cost attribution, audit payloads, structured access logs, analytics, and exports. The same ID lets you join one request across these surfaces without exposing the credential.
Key name and public prefixHuman-readable display in Flightdeck, such as claims-service (gw_a1b2c3d4). Flightdeck resolves this label from the opaque ID.

The gateway does not retain the plaintext credential after authentication. Refused authentication attempts are written to the structured access log and governance evidence. When a presented credential resolves far enough to an opaque key ID, that ID is included for correlation; the plaintext key never is.

Which scopes should you choose?​

A key with no scopes is unrestricted across the gateway planes available to that workspace. This is the default when you leave every Flightdeck scope unchecked or create a key in the Flightdeck. Once a key has one or more scopes, it can call only the named governed operation families.

ScopePermitted operations
completions:write/v1/chat/completions, /v1/completions, /v1/responses, /v1/messages and /v1/messages/count_tokens (from 1.8.5), and the Enterprise /v1/budget/** family
embeddings:write/v1/embeddings
batches:write/v1/batches/** and /v1/files/**
models:read/v1/models
mcp:readtools/list on the native endpoint, plus resources/* and prompts/* on the server-scoped REST paths, and server/discover (from 1.8.5)
mcp:calltools/call
a2a:readtasks/get, tasks/list, tasks/resubscribe, and push-notification configuration reads
a2a:sendmessage/send, message/stream, tasks/cancel, and push-notification configuration writes or deletion

All eight scopes can be granted from the Flightdeck's key form since 1.8.1. Before that the form offered the four LLM scopes only, so a key meant for MCP or A2A had to be created unscoped.

The two MCP surfaces do not expose the same operations. In 1.8, native Streamable HTTP at /mcp implements tools/list and tools/call; a native resource or prompt request returns JSON-RPC method-not-found. The older server-scoped REST surface under /mcp/{serverId}/... accepts resource and prompt operations, and mcp:read authorizes them.

Scope checks apply only where the table maps an operation family. A canonical /v1 route outside the four LLM families is not narrowed by these scopes. A2A agent-card discovery requires a valid workspace key but is not narrowed by an A2A scope. New MCP or A2A operations that have no mapping are likewise not narrowed until DVARA assigns them to a scope.

Do not invent scope names. The Open Source gateway.yaml validator refuses unknown values at startup. If an unknown value reaches another key store, it grants no governed operation family.

Use separate keys for separate workloads. For example, give an indexing job embeddings:write, while an application that generates answers receives completions:write and models:read. This reduces the effect of a leaked key and makes audit attribution clearer.

How do you verify a scoped key?​

The following request succeeds for a key with models:read:

curl -s http://localhost:8080/v1/models \
-H 'Authorization: Bearer gw_<your-key>'

The response lists the models that DVARA can discover from configured providers. Confirm the same key prefix and workspace on the corresponding request evidence in Flightdeck or your configured audit output.

If you use that key for a chat completion, DVARA returns 403 because the caller authenticated but lacks completions:write:

{
"error": {
"message": "API key is not scoped for this endpoint. It carries [models:read]; this endpoint needs completions:write.",
"type": "permission_error",
"code": "api_key_scope",
"trace_id": "01J8Y4M6N7P8Q9R0S1T2U3V4W5"
}
}

MCP and A2A use the same 403 distinction with plane-specific envelopes:

PlaneTypePublic error code
MCPmcp_errormcp_scope_denied
A2Aa2a_errora2a_scope_denied

Why can a valid path still be rejected?​

DVARA evaluates scopes against canonical /v1 paths. Percent-encoded segments, matrix parameters, repeated separators, backslashes, and . or .. segments are rejected before routing so alternate spellings cannot bypass a scope boundary.

For example:

curl --path-as-is -sS \
'http://localhost:8080/v1/%63hat/completions' \
-H 'Authorization: Bearer gw_<your-key>'

returns 400:

{
"error": {
"message": "Request path is not in canonical form (percent-encoding, matrix parameters, empty or dot segments are not accepted under /v1).",
"type": "invalid_request_error",
"code": "invalid_path",
"trace_id": ""
}
}

Use the canonical route, such as /v1/chat/completions. The trace ID is empty when this early rejection happens before request tracing begins.

What must you check before upgrading to 1.8?​

In 1.7, a nonempty scope list could behave as descriptive metadata. In 1.8 it becomes an authorization boundary.

  1. Inventory every key and its scopes. Check api_keys[].scopes in the Open Source gateway.yaml; in the Enterprise platform, open each workspace's API-key list in Flightdeck.
  2. Compare each workload's real calls with the scope table above. Include model discovery, file upload, batch work, budget estimation, MCP tools, and A2A operations rather than checking chat calls alone.
  3. Create a replacement key with every required scope. If the current 1.8 UI cannot express the required plane scope, keep that key unrestricted rather than assigning a misleading LLM-only scope.
  4. Deploy the replacement secret and test one allowed and one deliberately denied operation before revoking the old key.

Do not clear scopes simply to silence a 403: an empty list widens the key to every available plane. Follow the complete 1.8 upgrade runbook for rollout and rollback checks.

How do you rotate a key?​

Rotation is a create-then-revoke change:

  1. Create a replacement key with the scopes the workload needs, then copy its plaintext value.
  2. Update the calling service's secret and verify a successful governed call under the new key prefix.
  3. Revoke the old key in the Flightdeck.
  4. Send one request with the old key and confirm that DVARA returns 401 with api_key_revoked.

This sequence avoids interrupting in-flight work. Never place a plaintext key in source control, a container image, or a committed configuration export.

What do authentication failures mean?​

HTTPError codeMeaningFix
401api_key_requiredNo key was sent.Send the active workspace key.
401invalid_api_keyThe supplied key does not resolve.Check the complete secret and target environment.
401api_key_revokedThe key was revoked.Replace it with an active key.
401api_key_expiredThe key passed its expiry.Create and deploy a replacement.
403api_key_scopeThe key is valid but lacks the operation's scope.Add the required scope by issuing a replacement key.
400invalid_pathA /v1 path is not in canonical form.Use the documented canonical endpoint path.

Are Flightdeck tokens interchangeable?​

No. Flightdeck uses a browser session or a user personal access token with the dvara_pat_ prefix. Gateway data-plane calls use workspace keys with the gw_ prefix. Sending either credential to the other surface does not grant access.