# 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`). The feature 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"
```

Edit `id`, `displayName`, `issuer`, `clientId`, and `adminClaim` directly in values. `clientSecret` is the one sensitive field; inject it from the `OIDC_PROVIDER_CLIENT_SECRET` environment variable 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>

## Enable OIDC wallet verification [#enable-oidc-wallet-verification]

OIDC wallet verification (`OIDC_MFA`) requires two more fields on a provider entry: `applicationId` (the FusionAuth application id, plain config) and `apiKey` (sensitive). Source `OIDC_PROVIDER_MFA_API_KEY` from a Kubernetes Secret, the same way as `clientSecret`. Never place it in a values literal or a ConfigMap.

```yaml
global:
  dalpApp:
    config:
      auth:
        oidcProviders:
          - id: "fusionauth"
            issuer: "https://auth.example.com"
            applicationId: "the-fusionauth-application-id"
            apiKey: "${OIDC_PROVIDER_MFA_API_KEY:-}"
```

OIDC wallet verification is independent of sign-in. A provider with `issuer`, `apiKey`, and `applicationId` set is OIDC-MFA-capable even when `clientId` and `clientSecret` are empty, and enabling OIDC wallet verification does not disable local login. You can roll OIDC wallet verification out to a deployment that uses local sign-in or to one that uses OIDC sign-in without changing the login method.

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

`requireIssuerValidation` defaults to `true`, keeping 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]

Enabling a provider disables local login. A misconfigured provider can lock every user out, and there is no in-band fallback. Recovery requires 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 platform must invalidate the cached session for the new authorization to take effect. Without invalidation, stale authorization persists. 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, and the `apiKey` when OIDC wallet verification is enabled, 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.
* `OIDC_PROVIDER_MFA_API_KEY` sourced from a Secret when OIDC wallet verification is enabled, and OIDC wallet verification exercised end-to-end in staging.
* `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).
