Skip to main content

Server authentication & tenancy

This page covers inbound authentication for a hosted flux server: who may call it, how bearer tokens are validated, and how tenants are isolated. Authentication establishes caller identity; authorization of what that caller may do remains with the safety envelope.

Authentication modes

A flux server runs in one of three modes:

ModeHow a caller proves identityNotes
OpenNothingRefused on a non-loopback bind — you cannot accidentally expose an unauthenticated server to the network
Shared secretA bearer token compared in constant timeSimple single-tenant setups
PrincipalA bearer token validated by OIDC introspectionMulti-tenant, identity-provider-backed

Both authenticated modes reject a request that carries duplicate Authorization headers (a request-smuggling guard), and the bearer is length- and charset-checked before any work happens.

Principal mode (OIDC)

In principal mode, flux validates each bearer token against your identity provider using RFC 7662 token introspection, then projects the returned claims into a caller identity at a single mapping point. The security properties that matter:

  • Trust ceiling. A token presented over the network can never mint more than Verified trust. The elevated Privileged / System levels are reachable only by the local machine owner, never derived from a claim.
  • Only real access tokens pass. Introspection requires active: true and rejects non-access token types — a leaked refresh, logout, or id token can't be replayed as a working bearer.
  • No oracles. Every rejection returns a byte-constant WWW-Authenticate challenge and a constant body; a 401 never leaks why it failed. Any diagnostic detail is log-only.
  • Hardened introspection call. The introspection client never follows redirects (so a compromised endpoint can't replay your live bearer to a Location), caps the response size, and requires HTTPS unless explicitly told otherwise.
  • Cached by token hash. Validated results are cached keyed by SHA-256 of the token — raw bearers never sit in a map — with positive and negative results segregated so a garbage-token flood can't evict live sessions.

Tenant isolation with realms

Multi-tenant flux keeps callers apart with realms. Every caller resolves to a realm key in one of two disjoint namespaces:

  • acct:<account> — for a caller carrying a tenant/account claim,
  • user:<principal> — for an account-less caller.

Because the namespaces can't overlap, an identity provider that emitted account = "user:victim" still can't collide with a principal literally named victim. Sessions are tagged with their realm, and every /sessions/:id/* route is wrapped by a guard that returns the same constant 404 for a session in another realm as for one that doesn't exist — so a caller can't even probe which session ids are in use in another tenant.

account is a tenancy/storage key only — the authorization policy never consults it. Account- conditional access works through a reserved, authenticator-only group, not by treating the account as a policy input.

Hardened deployment profile

For a server holding credentials for many tenants, combine principal mode with the Vault credential-store backend: callers are authenticated per request and clamped to Verified, tenants are isolated into disjoint realms, and per-customer tokens live in Vault rather than a file on the pod. Bind and permission settings live in Configuration.