SSO and RBAC - bishoku/vmcp GitHub Wiki
SSO and roles
The UI can sign users in through any OpenID Connect provider (authorization-code flow with PKCE and nonce).
Enable it
Set on the control plane:
| Variable | Meaning |
|---|---|
VMCP_OIDC_ISSUER |
Issuer URL (must serve /.well-known/openid-configuration); enables SSO |
VMCP_OIDC_CLIENT_ID, VMCP_OIDC_CLIENT_SECRET |
Client registered at the provider |
VMCP_OIDC_REDIRECT_URL |
Public URL of /auth/callback, e.g. https://vmcp.example.com/auth/callback |
VMCP_OIDC_GROUPS_CLAIM |
ID-token claim with groups (default groups) |
VMCP_OIDC_ADMIN_GROUPS, VMCP_OIDC_EDITOR_GROUPS, VMCP_OIDC_VIEWER_GROUPS |
Comma-separated group names per role |
Register VMCP_OIDC_REDIRECT_URL as an allowed redirect URI at the provider and make sure the UI's host proxies /auth
to the control plane (the bundled nginx config does).
Try it with Keycloak
The repository ships a ready-to-run Keycloak realm (development only):
docker compose -f deploy/docker-compose.yml -f deploy/docker-compose.sso.yml up -d --build
Open http://localhost:3000 and choose Sign in with SSO. Users (password = username): alice → admin, bob → editor,
carol → viewer, dave → no group (refused). Keycloak's own console is at http://localhost:8180 (admin/admin).
The realm (deploy/keycloak/vmcp-realm.json) defines the vmcp client (confidential, PKCE S256, redirect
http://localhost:3000/auth/callback), the groups vmcp-admins|editors|viewers and a group membership mapper that puts
groups (without the leading slash) into the ID token. Tokens carry issuer http://localhost:8180/realms/vmcp while the
control plane reaches Keycloak as http://keycloak:8080 (VMCP_OIDC_DISCOVERY_URL).
For another provider, check that it puts the groups in the ID token and that the redirect URI and post-logout redirect URI (the UI's origin) are registered.
Signing out
Sign out clears the vMCP session and, when the provider advertises end_session_endpoint, sends the browser there so the
provider session ends too (otherwise the next click on SSO would sign you straight back in). Register the UI origin as an
allowed post-logout redirect URI.
Roles
| Role | Can |
|---|---|
| viewer | Read everything (GET) |
| editor | Change configuration, but not manage admin tokens |
| admin | Everything |
The highest matching role wins; users in none of the groups are refused. Admin API tokens map read to viewer and admin
to admin.
Good to know
- Signed cookies are valid for 8 hours and reference shared PostgreSQL session records. Logout revokes the session across control-plane replicas; operators can revoke all sessions for a subject. Database errors deny authentication. Role changes apply at the next sign-in; see security operations.
- Cookie-authenticated writes must send the header
X-VMCP-CSRF: 1(the UI does). Bearer-token calls do not need it. - Tokens keep working with SSO enabled; use them for automation.