Skip to content

Security architecture ​

How Dwara authenticates, authorizes, and protects requests. For operator-facing configuration, see Security and Authorization. This page covers the runtime architecture: the authn dispatch order, the authz evaluation model, secret resolution, and the TLS layers.

Security is applied in two phases of the request pipeline:

  • Phase 1, before the upstream call: authentication, consumer resolution, authorization, IP ACL, and rate limiting.
  • Phase 1/2 boundary: the request body is validated against route limits and the route action is dispatched.

TLS is handled at the listener and upstream layers; see Connection and TLS for that architecture. This page covers the HTTP-layer security machinery.

Authentication ​

Dwara supports five authentication families, dispatched in a fixed precedence order by the CompositeAuthenticator:

Precedence ​

The order is fixed and deliberate:

  1. API key — X-API-Key header. Cheapest check, most common.
  2. Basic — Authorization: Basic ... header.
  3. Bearer — Authorization: Bearer ... header. JWT is tried first, then OIDC. If a JWT provider is configured and rejects the token, OIDC is tried as a fallback.
  4. HMAC request signing — X-Dwara-Signature header with a canonical-request digest.
  5. mTLS client certificate — the verified client certificate from the TLS handshake, available as an ambient credential. Consulted only when no header credential was presented.

A request may carry at most one credential family. The first family that matches a configured authenticator wins; later families are not tried. A request with no matching credential is anonymous (no consumer resolved), and authorization then decides whether anonymous access is allowed for the route.

mTLS client certificate auth ​

The TLS listener verifies the client certificate against client_ca_file before the HTTP layer runs. The verified certificate is inserted into request extensions as ClientCertificate. The HTTP authn layer then resolves it in two stages:

  1. Gateway-level map — if mtls_consumer_map is configured and non-empty, the subject CN is checked first, then the colon-separated fingerprint.
  2. Per-consumer credentials — falls back to per-consumer mtls credentials in the registry, matched by subject CN then SHA-256 fingerprint.

See mTLS authentication for configuration.

JWT JWKS key rotation ​

JWT verification fetches the provider's JWKS and caches it. Rotation is handled with a dual-validity window:

  • The cache refreshes when older than refresh_secs.
  • Unknown-kid fetches (rotation signal) are throttled to min(5s, refresh_secs) to avoid hammering the provider.
  • On a successful fetch, the old set moves to retired with a timestamp. Retired keys remain valid for retired_key_grace_secs, giving a dual-validity window so tokens signed just before rotation still verify.

Authorization ​

Authorization is policy-scoped at five levels, evaluated most-specific-first with deny-anywhere-wins:

Evaluation rules ​

  • Most-specific-first: consumer policies are evaluated before route, route before service, service before listener, listener before global.
  • Deny-anywhere-wins: a Deny at any level overrides any Allow at any level.
  • Dry-run / monitor mode: a policy can be configured in dry-run mode, where a Deny is logged but not enforced. The dwara_policy_dry_run_total{phase,route} counter tracks how many requests would have been denied.

Policy engines ​

Dwara supports two policy engines, selectable per policy:

  • CEL — inline expressions evaluated against the request context (consumer, route, method, path, headers, JWT claims).
  • Cedar — Cedar policy documents evaluated against the same context.

Both engines see the same request context; the choice is per-policy based on authoring preference.

IP ACL and GeoIP ​

IP ACL and GeoIP gates run alongside authorization:

  • IP ACL — allow/deny lists of CIDRs, evaluated at the listener or route level.
  • GeoIP gate — allow/deny by country, using the client IP (after PROXY-protocol resolution if present).

See Authorization for configuration.

Secret resolution ​

Secrets (API keys, JWT signing keys, mTLS client keys, HMAC secrets) are resolved at config compile time, not at request time. The request path never resolves secrets dynamically — this keeps the hot path free of secret-store I/O and failure modes.

Reference formResolution
Inline valueUsed as-is.
${ENV:NAME}Read from the environment at compile time.
${file:/path}Read from the file at compile time.
${vault:...} / ${kms:...}Resolved via the SecretSource extension trait (Enterprise).

Resolved secrets live in the compiled snapshot. Logs, access records, and error envelopes never include secret values — they use redacted placeholders. A config reload re-resolves all secrets, so a vault rotation is picked up on the next reload without restarting the gateway.

See Config, state, and extensions for the extension trait model and Secrets for configuration.

TLS layers ​

TLS is covered in detail in Connection and TLS. The security-relevant summary:

  • Listener TLS — termination or passthrough, with optional client certificate verification (client_ca_file).
  • Upstream TLS — separate trust store, optional mTLS client certificate, optional certificate pinning.
  • FIPS — startup provider/self-test, cipher restrictions, and health attestation in Enterprise (ent) builds.
  • Post-quantum TLS — hybrid key-exchange wiring, experimental, in the default OSS build.

See also ​