On this page
Configure OIDC authentication
By default, Holon uses local control tokens for authentication. For shared team servers or remote deployments, you can switch to OpenID Connect (OIDC). Team members log in through your existing identity provider (IdP), and Holon records which user prompted an agent, enabling multiple team members to share an assistant with clear accountability. To see how OIDC fits into the broader team collaboration workflow, see Share AI assistants with your team.
This guide covers registering an OIDC client, configuring Holon, tuning session timeouts, and verifying logins.
Prerequisites
- A running Holon instance reachable by your users (for example via
--access tunnel,--access tailnet, or a reverse proxy). - An OIDC-compliant identity provider, such as self-hosted Keycloak, self-hosted Casdoor, Okta, Authentik, Google Workspace, self-hosted GitLab CE, or Microsoft Entra ID.
- Administrative access in your IdP to register a new client application.
Security note: Holon requires HTTPS for the OIDC issuer URL and callback endpoint. The callback alone may use HTTP when its host is
localhostor a loopback IP literal (127.0.0.1,[::1]); the issuer must still use HTTPS.
Keep administrative access to the runtime host while changing authentication, so you can correct a failed configuration. OIDC identifies signed-in users; it does not create a sandbox or imply per-user workspace isolation. See Security and execution boundaries.
Step 1: Register Holon in your IdP
Provider-Specific Guides:
- If your team uses Google Workspace, see the dedicated walkthrough: Configure OIDC Single Sign-On with Google Workspace, which covers Internal user type enforcement, admin access controls, and verified test scopes.
- If you want a completely self-hosted setup without external identity dependencies, see Configure OIDC Single Sign-On with Self-Hosted GitLab CE, which covers Docker deployment, Let's Encrypt certificates, confidential client setup, and verified test scopes.
- If you use a dedicated open-source identity platform as your organization-wide SSO hub, see Configure OIDC Single Sign-On with Self-Hosted Keycloak, which covers Docker deployment, realm and confidential client setup, and verified test scopes.
- If you want a lightweight open-source IAM platform to manage organizations and users centrally, see Configure OIDC Single Sign-On with Self-Hosted Casdoor, which covers Docker deployment, declarative init_data.json bootstrapping, organization path issuers, and verified test scopes.
Create a new OpenID Connect application in your identity provider:
- Client ID: Choose an identifier, such as
holon. - Client Authentication: Register a confidential client for the authorization code login flow and generate a Client Secret. This is user sign-in, not the client-credentials grant.
- Redirect URI: Set the callback URL:
If testing locally on porthttps://<your-holon-host>/api/auth/oidc/callback7878, use:http://localhost:7878/api/auth/oidc/callback - Scopes: Ensure the client requests at least
openid,profile, andemail.
Note down the Issuer URL, Client ID, and Client Secret.
Step 2: Store the Client Secret in an environment variable
Keep the secret out of Holon's configuration and source control. Supply it through an environment variable where the daemon runs:
export HOLON_OIDC_CLIENT_SECRET="your-oidc-client-secret"
If you run Holon as a service or container, supply it through that process's secret or environment mechanism. Restrict access to any backing environment file. Exporting it in an unrelated shell does not update an existing service.
Step 3: Configure Holon
Set the authentication mode and provider parameters with holon config set:
# Switch to OIDC authentication mode
holon config set auth.mode "oidc"
# Set the issuer URL (must support OIDC discovery at /.well-known/openid-configuration)
holon config set auth.oidc.issuer_url "https://auth.example.com/realms/team"
# Set your registered Client ID
holon config set auth.oidc.client_id "holon"
# Point to the environment variable containing the secret
holon config set auth.oidc.client_secret_env "HOLON_OIDC_CLIENT_SECRET"
# Set the public callback URL (recommended behind reverse proxies)
holon config set auth.oidc.redirect_uri "https://holon.example.com/api/auth/oidc/callback"
Step 4: Configure session policies
Holon issues HttpOnly session cookies for browsers and session credentials for API clients. Configure how long sessions stay valid:
# Idle session lifetime in seconds (default: 604800, or 7 days)
# Authenticated activity refreshes this timer.
holon config set auth.session.idle_ttl_seconds 43200
# Optional absolute session lifetime in seconds (must be >= idle_ttl_seconds)
# When set, the session expires after this period regardless of activity.
holon config set auth.session.absolute_ttl_seconds 604800
To disable the absolute timeout and allow active users to stay signed in, omit
auth.session.absolute_ttl_seconds or set it to null.
Step 5: Restart the daemon
Restart the daemon to apply authentication changes:
holon daemon restart
If running Holon interactively:
holon serve --access local
Use the same protected network endpoint or reverse proxy as before. If you also change the public hostname, update the registered redirect URI. Direct non-loopback, LAN, and tailnet CLI listeners still require a configured control token at startup; OIDC login does not remove that listener check.
Verify the setup
1. Log in via the Web GUI
- Open
https://<your-holon-host>/loginin your browser. - The login page detects OIDC mode and displays a Continue with organization login link.
- Click the link to redirect to your identity provider.
- Sign in. The IdP redirects back to
/api/auth/oidc/callback, which sets a secureholon_sessioncookie and lands on the dashboard (/).
2. Verify session identity
Inspect the current session using the session API:
curl -b "holon_session=<session-cookie>" https://<your-holon-host>/api/auth/session/me
Or provide the session token as a bearer credential:
curl -H "Authorization: Bearer <session-token>" https://<your-holon-host>/api/auth/session/me
The endpoint returns the authenticated user identity and authentication method:
{
"ok": true,
"user_id": "oidc-550e8400-e29b-41d4-a716-446655440000",
"display_name": "Alice Chen",
"auth_method": "oidc"
}
3. Check message attribution
In OIDC mode, every prompt sent through the control plane records the user's identity in the message origin:
actor_id: The persistent user identifier in Holon (formatted asoidc-<uuid-v4>).actor_display_name: The user's display name at send time (falls back toactor_idif no name claim exists).
When auditing agent transcripts or inspecting messages via GET /api/agents/{agent_id}/messages/{message_id}, check who submitted the prompt.
That attribution does not mean the user individually approved every later
tool call.
4. Verify a shared task with two test users
For team deployments where multiple users interact with the same agent runtime, verify that individual sessions produce attributable tasks and that team members can follow shared work according to your intended policy:
-
Pre-flight scope table: Agree on the testing boundaries before running the verification:
Scope item Setting in test Test users Two provisioned test accounts (e.g. alice@example.comandbob@example.com)Target agent An existing shared agent (e.g. team-assistant)Permitted shared task A bounded, read-only check (e.g. inspecting a status report or build result) Expected sharing boundary Both members can inspect the task result; each prompt records its own actor_idOut of scope File system sandboxing or per-user workspace isolation (not provided by OIDC) -
User A submits the task:
- Alice logs in via browser session A and submits a prompt: "Check the build status of commit 6a21e3c4".
- Alice receives a WorkItem or task ID.
- Inspecting the message record confirms
actor_display_name: "Alice Chen"and Alice'sactor_id.
-
User B follows up on the shared result:
- In an independent browser window (or private session), Bob logs in as
bob@example.com. - Bob navigates to the shared agent, locates Alice's completed task, and submits a follow-up query: "Summarize the verification items from that check".
- The message transcript records Bob's distinct
actor_idand display name while maintaining context continuity on the shared WorkItem.
- In an independent browser window (or private session), Bob logs in as
-
Verify audit trail:
- Inspect the agent transcript via
GET /api/agents/{agent_id}/messages: - Both prompts appear in order, each with its authenticated user attribution (
actor_idandactor_display_name).
- Inspect the agent transcript via
Security & isolation boundary:
- Authentication vs Authorization vs Execution: OIDC verifies who the user is and attributes prompt submissions. It does not provide multi-tenant filesystem virtualization, container boundaries, or per-user workspace isolation.
- Execution environment: Tools invoked by agents execute under the daemon process user on the host. To isolate untrusted workloads, configure separate daemon instances or containerized host environments. See Security and execution boundaries and Agents in a small team.
- Testing requirements: End-to-end multi-user verification requires an authorized non-production test instance and two test IdP credentials. In environments without multi-user test credentials, verify single-user attribution (Step 3) and mark multi-user task tests as pending authorization.
5. Log out
To end a session, click Log out in the Web GUI or issue:
curl -X POST -H "Authorization: Bearer <session-token>" \
https://<your-holon-host>/api/auth/session/logout
Logout invalidates the session record. Browser logout also clears its cookie;
a separate curl request does not clear a cookie in your browser.
6. Verify rejection of unauthorized requests
Make a request without a cookie or bearer credential:
curl -i https://<your-holon-host>/api/auth/session/me
Expect an authentication error rather than a user identity. Repeat with the revoked session credential after logout and confirm that it is rejected. Use a private browser window to check the sign-in flow separately from an already authenticated session.
Troubleshooting
- Redirect URI mismatch: Ensure the callback URI in your IdP matches
auth.oidc.redirect_uribyte for byte, including protocol (https://), port, and trailing path (/api/auth/oidc/callback). - Invalid issuer URL: The issuer URL must match the
issclaim in ID tokens and serve/.well-known/openid-configurationover HTTPS. - Secret not found: Verify that the environment variable named in
auth.oidc.client_secret_envis exported in the daemon process environment. - Invalid TTL configuration: If you configure
auth.session.absolute_ttl_seconds, it must be greater than or equal toauth.session.idle_ttl_seconds. Otherwise, Holon fails configuration validation on startup. - Login works but the wrong identity appears: Inspect
/api/auth/session/mein that same session and check the IdP account used. Do not infer identity from a display name alone. - Logged-out browser immediately signs in again: Check whether the IdP still has an active browser session. Holon session logout does not imply organization-wide IdP logout.
See Also
- HTTP Control Plane reference — API endpoints for session exchange, inspection, and logout
- Configuration reference — Full list of
auth.*options - Connect to a remote Holon runtime — Remote access options and networking
- Use the Web GUI — Working with agents and tasks in the browser
- Security and execution boundaries — Authentication, authorization, and isolation boundaries
- Agents in a small team — Shared team agent workflows and attribution
