No auth by default. When running locally or without --auth-mode, everything works exactly as before - no login, no restrictions.
How It Works
- Authentication identifies the user (proxy headers or OIDC login)
- Reads are filtered by namespace - Radar discovers which namespaces the user can access via
SubjectAccessReviewand only returns resources from those namespaces. Cluster-scoped resources (Nodes, ClusterRoles whenrbac.viewRBACis on, StorageClasses, etc.) are served from the ServiceAccount-populated informer cache without per-user RBAC re-checks, so anyone reaching Radar’s API sees them regardless of their own K8s permissions on those kinds. - Writes use K8s impersonation - Radar makes the K8s API call as the authenticated user, so K8s RBAC decides whether it’s allowed
- UI adapts - capability checks run per-user, so buttons (exec, restart, scale, Helm) only appear if the user has permission
kubectl, Terraform, GitOps, etc.).
Auth Modes
| Mode | Flag | When to Use |
|---|---|---|
none | --auth-mode=none | Local use, single-user, no restrictions needed (default) |
proxy | --auth-mode=proxy | You already have an auth proxy (oauth2-proxy, Pomerium, Cloudflare Access, etc.) in front of your ingress |
oidc | --auth-mode=oidc | You want Radar to handle login directly - no separate auth proxy needed |
Proxy Mode
Use this when you already have (or plan to deploy) an auth proxy like oauth2-proxy, Pomerium, Authelia, or similar. The proxy authenticates users and forwards their identity to Radar via HTTP headers. Flow:Security: Your ingress must stripX-Forwarded-UserandX-Forwarded-Groupsheaders from external requests to prevent spoofing. The auth proxy should be the only path to Radar. Radar logs a warning at startup as a reminder.
OIDC Mode
Use this when you want Radar to handle login directly - no separate auth proxy needed. Radar redirects to your identity provider (Google, Okta, Dex, Keycloak, etc.), validates the token, and creates a session cookie. Flow:openid profile email groups at the authorization endpoint. The groups scope is required by Dex, Keycloak, and most IdPs to actually include the groups claim in the ID token. If your IdP rejects unknown scopes (Google in particular doesn’t define groups), override via auth.oidc.scopes / --auth-oidc-scopes to drop it or substitute the provider-specific equivalent.
Logout behavior:
When a user clicks logout, Radar clears the local session cookie and - if the identity provider supports it - redirects the browser to the provider’s logout endpoint (RP-Initiated Logout) to terminate the SSO session as well. This prevents the common issue where the user appears to log out but is silently re-authenticated on the next visit.
Radar discovers the provider’s end_session_endpoint automatically from the OIDC discovery document at startup. If the provider supports it (Okta, Keycloak, Azure AD), Radar redirects the browser there to terminate the SSO session. If the provider doesn’t advertise end_session_endpoint (e.g., Google), Radar uses prompt=login on the next authorization request to force the IdP to show a login screen instead of silently re-authenticating. Check the startup logs for confirmation:
--auth-oidc-post-logout-redirect-url (or auth.oidc.postLogoutRedirectURL in Helm). This URL must be registered with your identity provider as a valid post-logout redirect URI.
Back-Channel Logout (IdP-initiated session revocation):
When an admin disables a user at the IdP level (e.g., disables an Okta account), Radar has no way to know - the existing session cookie remains valid until it expires. Back-Channel Logout (spec) solves this: the IdP POSTs a signed logout_token to Radar’s /auth/backchannel-logout endpoint, and Radar immediately revokes the matching session.
To enable, set --auth-oidc-backchannel-logout (or auth.oidc.backchannelLogout: true in Helm), then register https://radar.example.com/auth/backchannel-logout as the Back-Channel Logout URI in your IdP.
- Single-replica only. Revocations are stored in memory and not shared across pods. If Radar runs multiple replicas behind a load balancer, a revocation hitting one pod won’t affect sessions on other pods.
- Lost on restart. If Radar restarts, all pending revocations are lost. The session will expire naturally at cookie TTL (4h default).
sidrequired for targeted revocation. If the IdP’s logout_token contains onlysub(nosid), Radar cannot target the specific session - it logs a warning and the session expires at cookie TTL. Most major IdPs (Okta, Keycloak, Auth0, Azure AD) includesid.- Google does not support back-channel logout. For Google, session exposure is bounded by cookie TTL only.
existingSecret for the client secret but pass clientID as a plain value (it’s not sensitive).
TLS configuration for self-signed certificates:
If your OIDC provider uses a self-signed or internal CA certificate (e.g., on-prem Keycloak), use one of:
caCert in Kubernetes, mount the CA certificate into the pod via a ConfigMap or Secret volume.
Radar Cloud mode
If you seeRADAR_CLOUD_MODE or cloud.* values in the chart, they control a specialized deployment mode used by Radar Cloud - a hosted SaaS that lets a single Cloud frontend manage many in-cluster Radar instances over an outbound tunnel. You don’t need to use it to run Radar standalone; leave cloud.enabled: false (the default).
Under cloud-mode (RADAR_CLOUD_MODE=true, set automatically by the chart when cloud.enabled=true), Radar:
- Forces
--auth-mode=proxywith pinnedX-Forwarded-User/X-Forwarded-Groupsheaders - the Cloud tunnel is the trust boundary. - Ships three default ClusterRoleBindings mapping Cloud’s
cloud:owner/cloud:member/cloud:viewergroups to the standard K8sadmin/edit/viewClusterRoles. Configurable viacloud.defaultRbac.*invalues.yaml. - Hardens the listener (no
/debug/pprof/*, narrower exempt paths).
rbac.helm=true). Helm’s pre-flight existence check needs cluster-scoped reads/writes that the K8s built-in admin/edit/view ClusterRoles don’t grant. The chart emits two add-on ClusterRoles, split by trust tier:
radar-helm- CRDs, StorageClasses, RuntimeClasses, PriorityClasses, PodDisruptionBudgets, Namespaces. Bound tocloud:ownerANDcloud:member.radar-helm-admin- RBAC objects (Roles/Bindings, Cluster variants), validating/mutating webhooks, ApiServices. Bound tocloud:ownerONLY. Granting these to a tier weaker than owner would let a member self-promote to cluster-admin in oneClusterRoleBindingwrite, collapsing the owner/member distinction.
cloud:member attempting to install a chart that bundles its own RBAC will get a typed rbac_preflight 403 with an actionable “ask an owner” message. Day-to-day app charts and operator-CRD installs still work for members.
Customer-facing documentation for Radar Cloud lives on radarhq.io. The authoritative reference for the Cloud-mode chart values is the comment block in deploy/helm/radar/values.yaml under cloud:.
Setting Up User Permissions
Radar delegates authorization entirely to K8s RBAC via impersonation. It doesn’t have its own role system - permissions are managed with standard K8s tooling (kubectl, Terraform, Helm, GitOps, etc.). If your cluster already has RBAC bindings (most production clusters do), they work automatically. Radar impersonates the authenticated user, and K8s evaluates their existing bindings. You only need to create new bindings if users don’t already have the access they need.How It Works with Cloud Providers
Cloud-managed clusters typically map their IAM to K8s RBAC automatically:- GKE: Google Groups for RBAC maps Google Workspace groups to K8s groups. IAM roles (
roles/container.viewer, etc.) grant K8s access. The username is the user’s Google email. - EKS: The
aws-authConfigMap maps IAM roles/users to K8s users and groups. The username is typically the IAM role ARN or a mapped alias. - AKS: Azure AD integration maps Azure AD groups directly to K8s groups. The username is the Azure AD user principal name.
Understanding the Chain
User (a string like alice@company.com) and Group (a string like sre-team). These strings just need to match what the identity provider returns.
Using Built-in K8s Roles
K8s ships with built-in ClusterRoles that work well with Radar. You don’t need to create custom roles unless you want fine-grained control:| Built-in Role | What Users Can Do in Radar |
|---|---|
view | See resources, topology, events, logs. No restart, scale, or Helm writes. |
edit | Everything in view + restart, scale, edit resources. Does NOT include exec or port-forward (those require pods/exec and pods/portforward subresources - use the custom radar-operator role below). |
admin | Everything in edit + manage RBAC within namespaces. Same exec/port-forward caveat as edit. |
cluster-admin | Full access to everything across all namespaces, including exec and port-forward. |
Step 1: Create a ClusterRole with the permissions you want
Step 2: Bind it to your users or groups
By group (recommended - matches group from your identity provider):Step 3: Verify
After deploying with auth enabled, you can verify impersonation works:What Users See
When auth is enabled:- A username appears in the Radar header with a logout option
- The namespace selector only shows namespaces the user can access
- Topology, resources, events, dashboard are filtered to accessible namespaces
- Cluster-scoped resources (Nodes, PersistentVolumes, StorageClasses) are currently visible to all authenticated users regardless of namespace permissions - per-resource SAR checks for these are planned for a future release
- Helm releases are visible to all authenticated users (reads use the ServiceAccount, not impersonation, because the K8s
viewrole doesn’t includelist secretswhich Helm requires). Write operations (install, upgrade, rollback, uninstall) are impersonated and require the user to have appropriate RBAC. - Write buttons (restart, scale, exec, Helm install, etc.) only appear if the user has permission
- Write operations return 403 from K8s if RBAC denies them (shown as an error toast)
- The /api/auth/me endpoint returns the current user info and whether auth is enabled
ServiceAccount RBAC
When auth is enabled, Radar’s ServiceAccount needs two additional permissions (added automatically by the Helm chart):Session Cookies
Radar uses stateless HMAC-SHA256 signed cookies for sessions. The cookie contains the username and groups - no server-side session storage.- Cookie TTL: 4 hours by default (sliding), configurable with
--auth-cookie-ttlorauth.cookieTTLin Helm values. Sessions auto-extend while you’re active; idle sessions expire after the configured TTL. Active users won’t notice - Radar’s frontend polling keeps the session alive automatically. - Proxy mode: When the cookie expires, the middleware transparently re-creates the session from proxy headers on the next request, so the shorter default TTL has no UX impact.
- Session secret: Set
auth.secretorRADAR_AUTH_SECRETenv var. If empty, a random key is generated at startup (sessions won’t survive pod restarts) - For production: Use
auth.existingSecretto reference a K8s Secret, so sessions survive restarts
Configuration Reference
| Parameter | CLI Flag | Helm Value | Default |
|---|---|---|---|
| Auth mode | --auth-mode | auth.mode | none |
| Session secret | --auth-secret | auth.secret | auto-generated |
| Cookie TTL | --auth-cookie-ttl | auth.cookieTTL | 4h (sliding) |
| User header (proxy) | --auth-user-header | auth.proxy.userHeader | X-Forwarded-User |
| Groups header (proxy) | --auth-groups-header | auth.proxy.groupsHeader | X-Forwarded-Groups |
| OIDC issuer | --auth-oidc-issuer | auth.oidc.issuerURL | - |
| OIDC client ID | --auth-oidc-client-id | auth.oidc.clientID | - |
| OIDC client secret | --auth-oidc-client-secret | auth.oidc.clientSecret | - |
| OIDC client secret (K8s Secret) | - | auth.oidc.existingSecret | - |
| OIDC client secret key | - | auth.oidc.clientSecretKey | client-secret |
| OIDC redirect URL | --auth-oidc-redirect-url | auth.oidc.redirectURL | - |
| OIDC groups claim | --auth-oidc-groups-claim | auth.oidc.groupsClaim | groups |
| OIDC scopes | --auth-oidc-scopes | auth.oidc.scopes | openid,profile,email,groups |
| OIDC post-logout redirect | --auth-oidc-post-logout-redirect-url | auth.oidc.postLogoutRedirectURL | - |
| OIDC username prefix | --auth-oidc-username-prefix | auth.oidc.usernamePrefix | - |
| OIDC groups prefix | --auth-oidc-groups-prefix | auth.oidc.groupsPrefix | - |
| OIDC CA certificate | --auth-oidc-ca-cert | auth.oidc.caCert | - |
| OIDC skip TLS verify | --auth-oidc-insecure-skip-verify | auth.oidc.insecureSkipVerify | false |
| OIDC backchannel logout | --auth-oidc-backchannel-logout | auth.oidc.backchannelLogout | false |
Troubleshooting
User is logged back in immediately after logout (OIDC)
This happens when the identity provider’s SSO session is not terminated during logout. Check:- Check the startup logs. Look for
[oidc] RP-Initiated Logout enabledor theprompt=loginfallback message. Both approaches should prevent silent re-authentication. - Is
post_logout_redirect_uriregistered? If you set--auth-oidc-post-logout-redirect-url, it must be registered as a valid post-logout redirect URI with your identity provider. If not registered, the IdP may show an error instead of redirecting. - Browser extensions or aggressive caching? Some browser extensions may interfere with the redirect to the IdP’s logout endpoint.
Users get 401 on every request
- Proxy mode: Check that the auth proxy is setting
X-Forwarded-User. Inspect with: - OIDC mode: Verify the issuer URL, client ID, and redirect URL are correct. Check Radar logs for OIDC errors.
Users authenticate but see empty dashboard / no resources
The user will see a “No Namespace Access” message if they have no K8s RBAC bindings. Radar usesSubjectAccessReview to discover which namespaces each user can access - with no bindings, the result is zero namespaces.
Verify the user’s access:
All users see empty data even with correct RBAC
Radar’s ServiceAccount may be missing thesubjectaccessreviews permission needed to check user access. When this fails, Radar denies all namespace access (fail-closed). Verify:
no, the Helm chart’s RBAC was not applied. Re-install with rbac.create: true (the default) or add the rule manually.
Write operations return 403
The user’s K8s RBAC doesn’t include the required verb. Check with:Impersonation errors in Radar logs
Radar’s ServiceAccount is missing impersonation permissions. Verify:rbac.create: false in Helm, make sure your custom ClusterRole includes the impersonation rules.