Control-Plane Authentication
This document describes the authentication and authorization options currently implemented in control-plane/service as of July 17, 2026.
Overview
Section titled “Overview”The control-plane supports these runtime auth modes:
auth-disabled(no authentication; development/testing mode).- OIDC browser session auth (currently Google OIDC via login/callback).
- OIDC bearer auth for tools/CLI (ID token in
Authorization: Bearer ...). - Auth Service bearer auth for Governance Studio integrations (delegated token validation).
- Hybrid mode: browser session auth + either bearer verification mode enabled together.
Auth Modes
Section titled “Auth Modes”1) Auth Disabled
Section titled “1) Auth Disabled”Set:
-auth-enabled=false
Behavior:
- Requests are treated as an admin principal internally.
- No cookie session or bearer token is required.
- Intended for local/dev scenarios only.
Important caveat:
POST /v1/agent-registration-tokensrequires an authenticated subject (sub) to mint registration tokens. Inauth-disabledmode, no subject exists, so this endpoint returns unauthorized.
2) Browser Session OIDC (Google)
Section titled “2) Browser Session OIDC (Google)”Set:
-auth-enabled=true-auth-google-enabled=true-auth-state-secret=...-auth-google-client-id=...-auth-google-client-secret=...-auth-google-redirect-url=...- optional
-auth-google-issuer-url=...(defaults tohttps://accounts.google.com) - optional
-auth-google-scopes=openid,profile,email
Flow:
GET /v1/auth/providersGET /v1/auth/login?provider=googleGET /v1/auth/callback/google- Server creates cookie session + CSRF cookie.
Session details:
- Default cookie names:
- session:
guardian_session - csrf:
guardian_csrf
- session:
- Default session max age:
12h - Default idle timeout:
2h - Mutating endpoints require CSRF (header
X-CSRF-Tokenmust match CSRF cookie).
3) Bearer OIDC for CLI/Tools
Section titled “3) Bearer OIDC for CLI/Tools”Set:
-auth-enabled=true-auth-bearer-enabled=true-auth-bearer-issuer-url=...-auth-bearer-client-id=...- optional
-auth-bearer-scopes=openid,profile,email
Flow:
- Tool calls
GET /v1/auth/device-config. - Tool discovers OIDC metadata from issuer (
/.well-known/openid-configuration). - Tool obtains OIDC ID token (device flow or equivalent).
- Tool calls control-plane with
Authorization: Bearer <id_token>.
Verification model:
- Bearer token is verified against issuer JWKS and expected audience (
client_id). - This path expects an OIDC ID token.
- Bearer principal is mapped to role
member(notadmin). - CSRF is not required for bearer-authenticated requests.
4) Auth Service Bearer for Governance Studio
Section titled “4) Auth Service Bearer for Governance Studio”Set:
-auth-enabled=true-auth-bearer-enabled=true-auth-bearer-mode=auth_service-auth-bearer-auth-service-base-url=...
The Auth Service base URL may be omitted when
-adapter-auth-service-base-url is already configured. The bearer verifier uses
the adapter URL as its fallback. If neither URL is available, control-plane
fails configuration validation at startup.
Flow:
- Governance Studio sends its user token in
Authorization: Bearer <token>. - Control-plane forwards the token to Auth Service with
POST /api/v1/auth/validate?include_claims=true. - Auth Service validates the token and returns the resolved user, organization roles, and enriched claims.
- Control-plane constructs the bearer principal and applies its normal endpoint authorization rules.
Verification model:
- Token signature, issuer, expiry, and other validity decisions are delegated to Auth Service rather than performed through local OIDC discovery.
- The subject is read using the Auth Service-compatible fallback order:
subject,sub,userId, thenuser_id. - Only the enriched claim
https://governance.eqtylab.io/has_admin_access=truegrants anadminrole hint. Organization roles such asorganization_ownerare tenant-scoped and do not grant Gateway platform administration. Other validated users default tomember. - A matching user stored in the control-plane auth store takes precedence over the role hint, including stored role overrides and disabled-user status.
- Successful validations and definitive token rejections are cached for 30 seconds. Transient Auth Service failures are not cached and fail closed.
- CSRF is not required for bearer-authenticated requests.
GET /v1/auth/device-configreturns404because delegated tokens do not use the control-plane OIDC device-flow configuration.
This mode is opt-in. Omitting -auth-bearer-mode keeps the default oidc
behavior and its issuer/client validation, so standalone deployments continue
to verify bearer tokens locally.
5) Hybrid Mode (Recommended for UI + CLI)
Section titled “5) Hybrid Mode (Recommended for UI + CLI)”Enable both:
auth.google.enabled=trueauth.bearer.enabled=true
Choose the bearer verifier independently:
- omit
auth.bearer.modeor set it tooidcfor standalone OIDC verification; - set
auth.bearer.mode=auth_servicefor delegated Governance Studio tokens.
Use cases:
- Console users authenticate via browser session.
- Tools and integrated clients authenticate through the selected bearer mode.
Authorization Model
Section titled “Authorization Model”admin: full control-plane access, including user management and agent revoke/restore.member: scoped agent visibility and onboarding operations.
Endpoint Matrix (Auth Enabled)
Section titled “Endpoint Matrix (Auth Enabled)”GET /health: public.GET /v1/auth/providers: public (auth config discovery).GET /v1/auth/device-config: public when OIDC bearer auth is enabled and issuer/client metadata is configured; returns404inauth_servicemode.GET /v1/auth/login: public (starts browser auth flow).GET /v1/auth/callback/{provider}: public (OIDC callback).POST /v1/auth/logout: authenticated principal.- cookie session calls require CSRF.
GET /v1/me: authenticated principal.GET /v1/users: admin only.PATCH /v1/users/{id}: admin only.- cookie session calls require CSRF.
POST /v1/agent-registration-tokens: authenticated principal.- cookie session calls require CSRF.
- bearer calls do not require CSRF.
GET /v1/agents: authenticated principal.- admin: all agents.
- member: filtered to agents bound to the caller subject.
GET /v1/agents/{id}: authenticated principal.- admin: full access.
- member: only if caller has active binding.
GET /v1/projects/{project_uuid}/agents: project-scoped agent list.- Governance Studio project: requires a bearer token authorized by Auth Service for
view_project_dataon the bound Governance project. - operator project: admin only.
- Auth Service authorization failures and outages fail closed; an outage returns
503 Service Unavailable.
- Governance Studio project: requires a bearer token authorized by Auth Service for
GET /v1/projects/{project_uuid}/agents/{agent_id}: project-scoped agent detail by Gateway agent ID or membership subject DID.- uses the same Governance Studio
view_project_dataor operator-admin authorization as the project list. - returns only identities derived from membership evidence for the requested project; local key detail is restricted to the matching membership subject DID.
- uses the same Governance Studio
- Project-agent runtime reads under
/v1/projects/{project_uuid}/agents/{agent_id}:audit-exchanges,audit-exchanges/timeseries, audit detail, and request/response body routes;plugin-events;state-cids,state-cids/{state_cid}/blob, and parent-boundstate-cids/{state_cid}/blobs/{cid}.- require
view_project_data, a locally resolved Gateway agent, and Gateway-known membership evidence for the requested project. Historical access remains available when that known evidence is expired, revoked, or invalid. - return only records whose authoritative audit
project_urnequalsurn:uuid:{project_uuid}and whose localagent_idmatches. Candidate-only, empty-project, and legacy rows are excluded. - state and plugin records join to audit records with the server-generated
exchange_key; correlation IDs are returned only as tracing metadata. - the child-blob route returns a blob only when the authorized state attestation directly references that CID. There is no flat project CID endpoint.
POST /v1/agents/{id}/revoke: admin only (CSRF required for cookie session).POST /v1/agents/{id}/restore: admin only (CSRF required for cookie session).GET /v1/agents/{id}/status-events: admin only.
Registration Token Behavior
Section titled “Registration Token Behavior”Endpoint: POST /v1/agent-registration-tokens
Request:
agent_name(required)agent_handle(optional, deterministic handle)agent_idis rejected (managed by control-plane)
Behavior:
- Subject (
sub) is taken from authenticated principal external subject. - If
agent_handleis provided, deterministicagent_idis generated. - Otherwise,
agent_idincludes a random suffix. - Token TTL is currently 15 minutes.
- Response
commandis a template usingVIPER_PROVISIONING_TOKENplaceholder (raw token is returned only inregistration_token).
Config Reference
Section titled “Config Reference”Core Flags / Env
Section titled “Core Flags / Env”-auth-enabled/CONTROL_PLANE_AUTH_ENABLED-auth-registration-token-secret/CONTROL_PLANE_AUTH_REGISTRATION_TOKEN_SECRET-auth-registration-token-issuer/CONTROL_PLANE_AUTH_REGISTRATION_TOKEN_ISSUER-auth-allowed-email-domains/CONTROL_PLANE_AUTH_ALLOWED_EMAIL_DOMAINS-auth-bootstrap-admin-email/CONTROL_PLANE_AUTH_BOOTSTRAP_ADMIN_EMAIL-auth-cookie-domain/CONTROL_PLANE_AUTH_COOKIE_DOMAIN-auth-cookie-secure/CONTROL_PLANE_AUTH_COOKIE_SECURE-auth-session-max-age/CONTROL_PLANE_AUTH_SESSION_MAX_AGE-auth-session-idle-timeout/CONTROL_PLANE_AUTH_SESSION_IDLE_TIMEOUT-auth-ui-base-url/CONTROL_PLANE_AUTH_UI_BASE_URL
Browser OIDC (Google) Flags / Env
Section titled “Browser OIDC (Google) Flags / Env”-auth-google-enabled/CONTROL_PLANE_AUTH_GOOGLE_ENABLED-auth-state-secret/CONTROL_PLANE_AUTH_STATE_SECRET-auth-google-issuer-url/CONTROL_PLANE_AUTH_GOOGLE_ISSUER_URL-auth-google-client-id/CONTROL_PLANE_AUTH_GOOGLE_CLIENT_ID-auth-google-client-secret/CONTROL_PLANE_AUTH_GOOGLE_CLIENT_SECRET-auth-google-redirect-url/CONTROL_PLANE_AUTH_GOOGLE_REDIRECT_URL-auth-google-scopes/CONTROL_PLANE_AUTH_GOOGLE_SCOPES
Bearer Authentication Flags / Env
Section titled “Bearer Authentication Flags / Env”-auth-bearer-enabled/CONTROL_PLANE_AUTH_BEARER_ENABLED-auth-bearer-mode/CONTROL_PLANE_AUTH_BEARER_MODEoidc(default): verify locally through OIDC discovery and JWKS.auth_service: delegate validation to Auth Service.
-auth-bearer-issuer-url/CONTROL_PLANE_AUTH_BEARER_ISSUER_URL-auth-bearer-client-id/CONTROL_PLANE_AUTH_BEARER_CLIENT_ID-auth-bearer-scopes/CONTROL_PLANE_AUTH_BEARER_SCOPES-auth-bearer-auth-service-base-url/CONTROL_PLANE_AUTH_BEARER_AUTH_SERVICE_BASE_URL
issuer-url, client-id, and at least one scope are required when bearer auth
is enabled in oidc mode. The Auth Service base URL is required in
auth_service mode unless adapter-auth-service-base-url supplies it.
Helm Values (deploy/charts/guardian-stack)
Section titled “Helm Values (deploy/charts/guardian-stack)”Auth values:
controlPlane.auth.enabledcontrolPlane.auth.registrationTokenSecretcontrolPlane.auth.registrationTokenIssuercontrolPlane.auth.google.*controlPlane.auth.bearer.enabledcontrolPlane.auth.bearer.mode(oidcorauth_service; empty defaults tooidc)controlPlane.auth.bearer.issuerURLcontrolPlane.auth.bearer.clientIDcontrolPlane.auth.bearer.authServiceBaseURLcontrolPlane.auth.bearer.scopes
Governance Studio example:
controlPlane: auth: enabled: true bearer: enabled: true mode: auth_service # Optional when CONTROL_PLANE_ADAPTER_AUTH_SERVICE_BASE_URL is supplied, # for example through controlPlane.extraEnv. authServiceBaseURL: http://governance-platform-auth-service:8080Secret keys used by control-plane auth secret:
stateSecret(required whenauth.google.enabled=true)registrationTokenSecretgoogleClientID(when Google enabled)googleClientSecret(when Google enabled)
OpenFleet Integration (Current)
Section titled “OpenFleet Integration (Current)”OpenFleet now uses bearer OIDC device flow for onboarding:
openfleet auth login-> reads/v1/auth/device-config, performs OIDC device flow, stores local session.openfleet agents create --guardian-onboard-> mints registration token via control-plane and passes provisioning data to runtime.- Runtime (OpenClaw + viper) generates DID key material and registers with llm-gateway using the provisioning token.
openfleet agents onboard <name>-> rotates provisioning token for an existing runtime-provisioned workload.
This aligns tool onboarding with the same identity/trust model used by control-plane and gateway.