---
title: Enabling OIDC in a Kubernetes installation
sidebar_label: OIDC in a Kubernetes installation
---

This guide explains how to configure OpenID Connect (OIDC) authentication for Deephaven running in Kubernetes. OIDC enables single sign-on (SSO) by delegating authentication to your organization's identity provider (IdP), such as Okta, Keycloak, Auth0, or Azure AD.

OIDC is provider-agnostic and coexists with SAML: an install may enable `saml`, `oidc`, both, or neither. When both are enabled, the Web login screen shows a button for each.

For OIDC configuration options and background not specific to Kubernetes, see [OIDC authentication](../configuration/oidc-auth.md).

> [!NOTE]
> OIDC login is available in the Deephaven **Web** interface only; there is no OIDC login panel for the Classic (Java/Swing) console.

## Prerequisites

- A Deephaven Kubernetes installation, which is always fronted by the Envoy proxy.
- An OIDC application registered at your IdP. Its **Sign-in redirect URI** must be set to `https://<envoyFrontProxyUrl>:<envoy.exposedPort>/dh-oidc/cb` (this is the URL the Helm chart generates).
- The OIDC client secret, provided one of two ways:
  - set `oidc.clientSecret` with the value and the chart creates the Kubernetes secret for you; **or**
  - pre-create a Kubernetes secret containing the value under the `clientSecret` key and set `oidc.clientSecretName` to its name.
    Providing `oidc.clientSecret` puts the value in your values file and the rendered release manifest; for production, prefer a pre-created secret (or an external secrets manager).
- Nothing extra for TLS. The OIDC module's embedded Jetty reuses the install's auto-generated keystore, which is correct in Kubernetes. See [TLS for the OIDC module](#tls-for-the-oidc-module).

## Configuration overview

Setting the `oidc` Helm values causes the chart to:

- enable the `OidcAuthModule` in the authentication server and template its `authentication.oidcauth.*` properties;
- mount the client-secret secret into the auth-server pod under `/auth-server-oidc/`;
- add the Envoy routes for `/dh-oidc/`, `/dh-oidc/cb`, and `/static/` so the browser can reach the login and callback endpoints;
- add the OIDC keys to the Web front-end's `authentication.client.configuration.list` (combined with SAML's keys if SAML is also enabled).

## OIDC Helm values

| Value                   | Default                | Description                                                                                                                                       |
| ----------------------- | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `oidc.providerName`     | `OIDC`                 | Optional. Provider name to display in the UI (e.g., "Okta").                                                                                      |
| `oidc.clientSecret`     | N/A                    | The OIDC client secret value; the chart creates the secret. Use this **or** `clientSecretName`.                                                   |
| `oidc.clientSecretName` | N/A                    | Name of a pre-created secret holding the client secret under the `clientSecret` key.                                                              |
| `oidc.issuer`           | N/A                    | IdP issuer URL (discovery is read from `<issuer>/.well-known/openid-configuration`).                                                              |
| `oidc.clientId`         | N/A                    | OAuth client ID registered at the IdP.                                                                                                            |
| `oidc.scopes`           | `openid profile email` | Optional. Space-separated scopes; must include `openid`.                                                                                          |
| `oidc.usernameClaim`    | `preferred_username`   | Optional. id_token claim mapped to the Deephaven user (falls back to `sub`).                                                                      |
| `oidc.groupsClaim`      | —                      | Optional. Names the field holding the user's groups, commonly `groups`. Required by the `claim` and `userinfo` sources; has no effect on its own. |

Group synchronization is configured under `oidc.groups` (all optional; omit the block entirely to leave the module's defaults in place):

| Value                               | Default | Description                                                                                                      |
| ----------------------------------- | ------- | ---------------------------------------------------------------------------------------------------------------- |
| `oidc.groups.source`                | —       | Which group source to use: `claim`, `userinfo`, `google`, or one supplied on the classpath. Unset means off.     |
| `oidc.groups.cacheTtlSeconds`       | `300`   | How long a user's fetched group list is reused.                                                                  |
| `oidc.groups.ignoreIdpGroups`       | —       | List of IdP groups never added to Deephaven.                                                                     |
| `oidc.groups.ignoreDeephavenGroups` | —       | List of Deephaven groups never removed, such as `iris-acleditors`.                                               |
| `oidc.groups.mapGroups`             | —       | Map of IdP group to one or more Deephaven groups. Names containing spaces are escaped for you.                   |
| `oidc.groups.google.transitive`     | `false` | Also count membership inherited through nested groups, by checking each mapped group individually.               |
| `oidc.groups.google.customer`       | —       | Cloud Identity customer (`customers/C0xxxxxxx`), required by `transitive` when groups are named by display name. |

See [Group synchronization](../configuration/oidc-auth.md#group-synchronization) for what each source does and how the identifiers are matched.

To enable OIDC, set the following values when installing the Helm release:

```yaml
oidc:
  # Provider name displayed in the UI:
  providerName: "Okta"

  # The chart creates a secret from this value (or omit it and set clientSecretName to a pre-created secret):
  clientSecret: "<okta-client-secret>"

  # Parameters from the IdP (Okta Integrator Free Plan: use the "default" custom authorization server):
  issuer: "https://dev-XXXXXXXX.okta.com/oauth2/default"
  clientId: "0oaXXXXXXXXXXXXXXXXX"

  # Optional:
  scopes: "openid profile email"
  usernameClaim: "preferred_username"

  # Group synchronization (both are needed):
  #groupsClaim: "groups"
  #groups:
  #  source: "claim"
```

The chart registers the redirect URI `https://<envoyFrontProxyUrl>:<envoy.exposedPort>/dh-oidc/cb`; add exactly that URL as a Sign-in redirect URI in the IdP application.

### Google Workspace

Google emits no groups claim, so group synchronization requires the `google` source. It reads the user's groups from the Cloud Identity Groups API using the access token their own login produced — no service account and no Google administrator. Enable the API in the Cloud project that owns the OAuth client first:

```bash
gcloud services enable cloudidentity.googleapis.com --project <PROJECT_ID>
```

```yaml
oidc:
  providerName: "Google"
  issuer: "https://accounts.google.com"
  clientId: "<client-id>.apps.googleusercontent.com"
  clientSecret: "<google-client-secret>"

  # Cloud Identity is keyed by email address, which is also the Deephaven user name that gets auto-created.
  usernameClaim: "email"
  scopes: "openid profile email https://www.googleapis.com/auth/cloud-identity.groups.readonly"

  groups:
    source: "google"
    ignoreIdpGroups:
      - "All Illumon"
    mapGroups:
      QATeam: "iris-superusers,iris-acleditors,iris-schemamanagers"
```

Each user sees a consent prompt for the added scope at their next login. If a mapped group is reached through nesting rather than direct membership, also set `oidc.groups.google.transitive: true` and `oidc.groups.google.customer`.

> [!NOTE]
> On upgrade, `iris-environment.prop` is not reloaded into etcd by default. If you add or change OIDC values on an existing install, set `loadIrisEnvironmentPropOnUpgrade=true` (or re-import the properties) for the changes to take effect.

## TLS for the OIDC module

You do not need to configure this. The OIDC module's embedded Jetty uses the install's auto-generated keystore, which is correct in Kubernetes: the browser's TLS connection ends at Envoy, and although Envoy then reaches the Jetty over TLS as well, it does not verify the Jetty's certificate.

Enabling cert-manager does not change this: it provisions the auth server's service-to-service keystore, not the OIDC Jetty's.

## High availability

OIDC login works with the chart's default of multiple authentication-server replicas (`replicas.authserver`, default `2`) and requires **no session affinity** on the auth-server Service — the login flow is stateless across replicas. You do not need to scale the auth server down to one pod or add sticky-session routing for OIDC to work. The interactive login window is governed by `authentication.federatedauth.cookie.ttlmillis` (default 5 minutes) rather than a session timeout.

## Related documentation

- [OIDC authentication](../configuration/oidc-auth.md)
- [SAML in a Kubernetes installation](./kubernetes-saml-integration.md)
- [Kubernetes configuration settings](./kubernetes-configuration-settings.md)
- [Kubernetes install guide](./kubernetes-install-guide.md)
