OIDC Setup
Configure OpenID Connect (OIDC) authentication so AgentVisor™ validates JWT tokens and establishes real user identities.
How OIDC Works with AgentVisor
OIDC is the standard protocol for verifying identity. When configured:
- Clients include a JWT bearer token in the
Authorizationheader - AgentVisor validates the token's signature, expiration, and claims
- The token's claims become the principal for policy evaluation
- Your existing policies evaluate against the real identity
Configuration
Enable OIDC in your configuration file or via environment variables:
Config File
# agentvisor.yaml
api:
auth:
enabled: true
oidc_issuer: "https://accounts.google.com"
oidc_audience: "your-client-id.apps.googleusercontent.com"
Environment Variables
export AGENTVISOR_API_AUTH_ENABLED=true
export AGENTVISOR_API_AUTH_OIDC_ISSUER=https://accounts.google.com
export AGENTVISOR_API_AUTH_OIDC_AUDIENCE=your-client-id.apps.googleusercontent.com
Configuration Reference
| Variable | Config Key | Required | Description |
|---|---|---|---|
AGENTVISOR_API_AUTH_ENABLED | api.auth.enabled | Yes | Set to true to enable authentication |
AGENTVISOR_API_AUTH_OIDC_ISSUER | api.auth.oidc_issuer | Yes | OIDC issuer URL |
AGENTVISOR_API_AUTH_OIDC_JWKS_URL | api.auth.oidc_jwks_url | No | Override JWKS URL (see below) |
AGENTVISOR_API_AUTH_OIDC_AUDIENCE | api.auth.oidc_audience | No | Expected aud claim in JWT |
Provider Examples
Google
api:
auth:
enabled: true
oidc_issuer: "https://accounts.google.com"
oidc_audience: "your-client-id.apps.googleusercontent.com"
Keycloak
api:
auth:
enabled: true
oidc_issuer: "https://keycloak.example.com/realms/agentvisor"
oidc_audience: "agentvisor-api"
Keycloak (Kubernetes Internal)
When running in Kubernetes, the external OIDC issuer URL may not be reachable from inside the cluster (e.g., self-signed certs). Use oidc_jwks_url to point to an internal endpoint:
api:
auth:
enabled: true
oidc_issuer: "https://keycloak.example.com/realms/agentvisor"
oidc_jwks_url: "https://keycloak-service.keycloak.svc.cluster.local:8443/realms/agentvisor/protocol/openid-connect/certs"
oidc_audience: "agentvisor-api"
The oidc_jwks_url overrides the JWKS endpoint discovered from the issuer's .well-known/openid-configuration. The issuer URL is still used for iss claim validation.
The JWKS URL must be https. A plaintext http:// endpoint lets anyone on the network path
substitute the signing keys and mint tokens for any principal. If your in-cluster provider
genuinely cannot serve TLS, you can opt in with oidc_allow_insecure: true
(AGENTVISOR_API_AUTH_OIDC_ALLOW_INSECURE=true) — a loud warning is logged and this should
never be used in production.
Auth0
api:
auth:
enabled: true
oidc_issuer: "https://your-tenant.auth0.com/"
oidc_audience: "https://api.your-app.com"
How Claims Map to the Principal
All JWT claims become top-level fields in the principal map used for policy evaluation — each claim is directly accessible as principal.<claim>:
| JWT Claim | Principal Field | Description |
|---|---|---|
sub | principal.sub | Subject identifier — used in policy rules |
mroles | principal.mroles | Array of role MRNs for role-based policies (see MPE PORC) |
mgroups | principal.mgroups | Array of group MRNs for group-based policies |
| (all others) | principal.<claim> | All JWT claims are passed through as top-level fields (e.g., principal.iss, principal.aud, principal.email) |
Credential delegation: The original JWT is also preserved internally for credential delegation scenarios (e.g., principal_passthrough). This is not a policy-visible field — it is used by credential resolvers to forward the caller's token to upstream services.
Role and Group Mapping
MPE evaluates roles and groups from specific claims in the principal. Your OIDC provider must be configured to include these claims in the JWT:
| Claim | Type | Purpose |
|---|---|---|
mroles | Array of MRN strings | Role-based access control (e.g., ["mrn:agentvisor:role:admin"]) |
mgroups | Array of MRN strings | Group-based policy selection |
Configure your identity provider to map user roles/groups to these claim names. For example, in Keycloak, use a "Token Mapper" to emit mroles as a JSON array claim.
Then reference them in your policies:
package authz
import rego.v1
default allow := false
allow if {
"mrn:agentvisor:role:admin" in input.principal.mroles
}
See the MPE PORC documentation for the full list of principal fields MPE supports.
OIDC Discovery
On startup, AgentVisor performs automatic OIDC discovery:
- Fetches
{issuer}/.well-known/openid-configuration - Discovers the JWKS (JSON Web Key Set) endpoint
- Fetches signing keys for JWT validation
If discovery fails, the host runtime will not start — this is fail-fast by design.
Testing Locally
You can test OIDC configuration without a full identity provider deployment:
Use Test Mode Alongside OIDC
Enable test mode to allow X-Test-Principal header injection while OIDC is configured. X-Test-Principal is only parsed when authentication is enabled, so both env vars are required:
AGENTVISOR_API_AUTH_ENABLED=true AGENTVISOR_API_AUTH_TEST_MODE=true agentvisor serve ./my-agent
X-Test-Principal cannot exercise the mroles-based policies described
below in Role and Group Mapping — the test
authenticator strips any mroles claim from the header before it reaches
policy evaluation, so a test principal can never forge a role. Use
mgroups instead (not stripped) if you need to grant a role while testing,
or test against a real OIDC token.
Verify Token Validation
Send a request with a real JWT to confirm OIDC is working:
TOKEN="eyJhbG..." # Your JWT token
curl -H "Authorization: Bearer $TOKEN" \
-X POST http://localhost:8090/threads
Debug Authentication Failures
Enable debug logging to see detailed authentication information:
AGENTVISOR_LOG_LEVEL=debug agentvisor serve ./my-agent
The logs will show:
- Token claims (
iss,aud,sub,exp,iat) - Expected vs. actual values for mismatches
- JWKS key lookup details
Troubleshooting
"Invalid token" Errors
- Expired token: Check the
expclaim — tokens have a limited lifetime - Wrong issuer: Ensure
oidc_issuermatches theissclaim exactly (including trailing slashes) - Wrong audience: If
oidc_audienceis configured, the token'saudclaim must match
Discovery Failures
- Network issues: Ensure the issuer URL is reachable from the AgentVisor host
- Self-signed certs / unreachable issuer from inside the cluster: Use
oidc_jwks_urlto point to an internal https endpoint that serves the same keys — see Keycloak (Kubernetes Internal) above. The JWKS URL must still behttps(oroidc_allow_insecure: true, dev only — see the warning above); a plaintexthttp://endpoint is rejected at startup either way - Startup failure: Discovery is fail-fast — check logs for the specific error
Missing Principal Fields
- Ensure your identity provider includes the expected claims (
sub,email, roles) in the JWT - Some providers require explicit scope requests to include certain claims
See Also
- Authentication Tutorial — Development identity options
- Policy Configuration — Writing policies that use principal claims
- Multi-Tenancy — User isolation with owner-based access
- Production Deployment — Full hardening checklist
- Configuration Reference — All configuration options