# Deploy OIDC in production

Source: https://docs.settlemint.com/docs/developers/sso-oidc/deploy-production
Roll out OIDC sign-in through the DALP Helm chart, inject the client secret safely, keep issuer validation fail-safe, and recover from a lockout.



OIDC sign-in is configured in the DALP Helm chart under `global.dalpApp.config.auth.oidcProviders` (the shared app config rendered into `config.yml`). It is **disabled by default** — an empty list keeps local email/password and passkey sign-in active. This page covers enabling a provider safely for a real deployment. Read [Configure an OIDC provider](/docs/developers/sso-oidc/configure-provider) for the field meanings first.

## Enable a provider in Helm values [#enable-a-provider-in-helm-values]

The chart ships the provider list empty with a commented example:

```yaml
global:
  dalpApp:
    config:
      auth:
        # Disabled by default. An empty list keeps local login active.
        oidcProviders: []
        # oidcProviders:
        #   - id: "fusionauth"
        #     displayName: "FusionAuth"
        #     issuer: "https://auth.example.com"
        #     clientId: "dalp"
        #     clientSecret: "${OIDC_PROVIDER_CLIENT_SECRET:-}"
        #     adminClaim: "dalp-admin"
```

The plain fields — `id`, `displayName`, `issuer`, `clientId`, `adminClaim` — are edited directly in values. `clientSecret` is the one sensitive field and is injected from the `OIDC_PROVIDER_CLIENT_SECRET` environment variable, which must be sourced from a Kubernetes Secret. Add more list entries for multiple providers.

<Callout type="warning" title="A complete entry disables local login deployment-wide">
  As soon as one entry has `id`, `issuer`, `clientId`, and `clientSecret` set,
  external OIDC becomes the only login method. Stage and verify the rollout in a
  non-production environment first.
</Callout>

## Inject the client secret from a Secret [#inject-the-client-secret-from-a-secret]

Source `OIDC_PROVIDER_CLIENT_SECRET` from a Kubernetes Secret (or your external-secrets / Conjur integration), never from a values literal or a plain ConfigMap.

<Callout type="warning" title="Do not let the client secret land in a ConfigMap">
  If the secret is interpolated into the rendered `config.yml` and that file is
  stored in a ConfigMap, it is unencrypted in etcd and readable by anything with
  `get` on configmaps in the namespace. Keep `OIDC_PROVIDER_CLIENT_SECRET`
  flowing from a Secret into the pod environment, and confirm your deployment
  does not bake the resolved value into a committed or ConfigMap-stored config.
</Callout>

## Keep issuer validation fail-safe [#keep-issuer-validation-fail-safe]

`requireIssuerValidation` defaults to `true` (RFC 9207 issuer checking on). Keep that default. Disable it **only per provider** for an IdP that provably lacks RFC 9207 support — FusionAuth is the common case.

Prefer a per-deployment environment variable over a committed `false`, so a new deployment fails safe (validation on) rather than fail-open:

```yaml
requireIssuerValidation: ${OIDC_PROVIDER_REQUIRE_ISSUER_VALIDATION:-}
```

With the variable unset the field resolves to its `true` default; an operator running FusionAuth sets `OIDC_PROVIDER_REQUIRE_ISSUER_VALIDATION=false` explicitly. Disabling RFC 9207 still leaves the ID token's `iss` claim validated against discovery.

## Privilege comes from the admin claim [#privilege-comes-from-the-admin-claim]

The `adminClaim` value grants platform admin to any profile carrying it. Treat the IdP as trusted configuration: anyone who can mint that claim at the provider can grant themselves platform admin on DALP.

* Scope who can assign the admin role or group at the IdP.
* Keep `adminClaim` empty unless the deployment deliberately mints the claim (deny-by-default).
* Roles re-derive on every login, so revoking the claim at the IdP demotes the user on their next sign-in.

## Recover from a lockout [#recover-from-a-lockout]

Because enabling a provider disables local login, a misconfigured provider can lock every user out — there is no in-band fallback. Recovery is a redeploy with the provider list emptied:

```yaml
global:
  dalpApp:
    config:
      auth:
        oidcProviders: []
```

Redeploying with an empty list restores local email/password and passkey sign-in. Validate provider changes in a staging environment so production never depends on an unverified IdP.

## Session cache and role changes [#session-cache-and-role-changes]

A user's role is part of their session cache key. When a claim change at the IdP changes a user's role, the cached session must be invalidated for the new authorization to take effect — otherwise stale authorization can persist. Account for cache invalidation when you rely on claim-driven promotion or demotion.

## OpenShift parity [#openshift-parity]

Chart changes must stay deployable to on-prem OpenShift clusters. When you add or change OIDC values, mirror them in `values-openshift.yaml`, the canonical OpenShift override example, in the same change. Source the client secret through the cluster's secret mechanism (for example Conjur-injected secrets) rather than chart literals.

## Rollout checklist [#rollout-checklist]

* Provider verified end-to-end in staging (sign-in completes, admin role resolves).
* `OIDC_PROVIDER_CLIENT_SECRET` sourced from a Secret, not a ConfigMap or values literal.
* `requireIssuerValidation` left at `true` except for providers proven to lack RFC 9207.
* `adminClaim` set only when the IdP deliberately mints it; admin role assignment scoped at the IdP.
* `values-openshift.yaml` updated to match (if deploying to OpenShift).
* Lockout recovery path (empty `oidcProviders` redeploy) understood and reachable.

If sign-in fails after rollout, see [Troubleshooting](/docs/developers/sso-oidc/troubleshooting).
