> ## Documentation Index
> Fetch the complete documentation index at: https://bifrost-backport-outbound-fetchers.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# SSO using OIDC

> Configure any standard OpenID Connect provider as your identity provider for Bifrost Enterprise.

This guide applies to any identity provider that implements the OpenID Connect (OIDC) standard - including PingIdentity, ForgeRock, OneLogin, JumpCloud, CyberArk Identity, and others not covered by a dedicated Bifrost guide.

## Prerequisites

* An OIDC-capable identity provider with admin access
* Bifrost Enterprise deployed and accessible
* Your Bifrost callback URL: `https://<your-bifrost-domain>/login`
* The ability to create a **confidential** (client secret) OAuth 2.0 application in your IdP
* Bifrost [roles](../rbac) created for the roles you plan to map

***

## Step 1: Create an OIDC application in your IdP

<Steps>
  <Step title="Register a new application">
    In your identity provider's admin console, create a new application. Look for options like **Create App Integration**, **Add Application**, **New Application**, or **Register Client**.

    Choose a type that matches the **Authorization Code** flow with a server-side callback - typically **Web Application** or **Regular Web Application** with a **Confidential** client. Avoid **SPA** or **Native** types.
  </Step>

  <Step title="Configure redirect URIs">
    Set the following URIs in your IdP:

    | Field | Value |
    | - | - |
    | **Redirect / Callback URI** | `https://<your-bifrost-domain>/login` |
    | **Discovery callback URI** | `https://<your-bifrost-domain>/workspace/scim/oauth-discover-callback` |
    | **Logout / Sign-out URI** | `https://<your-bifrost-domain>` (optional) |

    Save the application.
  </Step>
</Steps>

***

## Step 2: Configure token claims

<Steps>
  <Step title="Ensure the required scopes are requested">
    Your application must request the following OAuth scopes:

    * `openid` - required for OIDC
    * `profile` - provides `name`, `given_name`, `family_name`
    * `email` - provides the user's email address
    * `offline_access` - provides a refresh token for session maintenance (if supported)
  </Step>

  <Step title="Include group or role claims">
    For role and team mapping to work, your IdP must include group memberships or role values in the ID token.

    | Provider type | How to add group/role claims |
    | - | - |
    | **Okta / Auth0** | Add a groups claim in the app settings or via an Action |
    | **Keycloak / Zitadel** | Enable project/realm role claims in token settings |
    | **LDAP-backed IdPs** | Map LDAP group attributes to OIDC claims |
    | **Generic OIDC** | Use your provider's claim mapping or transformation rules |

    Any claim present in the ID token is available for mapping in Bifrost.
  </Step>
</Steps>

***

## Step 3: Copy your credentials

<Steps>
  <Step title="Note the Issuer URL, Client ID, and Client Secret">
    From your application settings, copy:

    | Value | Where to find |
    | - | - |
    | **Issuer URL** | Also called OIDC Issuer or Authorization Server URL. Must match the `iss` claim in the JWT. |
    | **Client ID** | Application ID or Client ID |
    | **Client Secret** | Application secret (confidential clients only) |

    The issuer URL typically looks like `https://auth.company.com` or `https://auth.company.com/realms/my-realm`. Bifrost uses it to discover endpoints via `<issuer>/.well-known/openid-configuration`.
  </Step>
</Steps>

***

## Step 4: Assign users

<Steps>
  <Step title="Grant users access to the application">
    In your IdP, assign the users or groups that should be able to log in to Bifrost:

    * **Explicit assignment** - add users directly to the application
    * **Group-based access** - assign a group; all members get access
    * **Policy-based** - configure an access policy

    Only users explicitly granted access can authenticate via Bifrost.
  </Step>
</Steps>

***

## Step 5: Configure Bifrost

<Steps>
  <Step title="Open User Provisioning and choose Generic OIDC">
    In your Bifrost dashboard, go to **Governance** → **User Provisioning**.

    Select **Generic OIDC Provider** and click **Next**.

    <Frame caption="Select Generic OIDC Provider from the list of identity providers.">
      <img src="https://mintcdn.com/bifrost-backport-outbound-fetchers/L0PPc5gg3uLKNILE/media/user-provisioning/generic-oidc/bifrost-provider-selection.png?fit=max&auto=format&n=L0PPc5gg3uLKNILE&q=85&s=3c7d2541fe2f819d6822587a28b1196d" alt="Bifrost Choose Provider screen with Generic OIDC Provider selected" width="2912" height="1664" data-path="media/user-provisioning/generic-oidc/bifrost-provider-selection.png" />
    </Frame>
  </Step>

  <Step title="If your IdP is on a private network, add a trusted network">
    Skip this step if your IdP is reachable on the public internet.

    A self-hosted IdP on `10.x`, `172.16-31.x`, or `192.168.x` is blocked by that guard until you explicitly trust its range, and discovery fails with an error like:

    ```
    Invalid issuer URL: access to IP 10.20.4.11 is not allowed
    Invalid issuer URL: host idp.internal.company.com resolves to a disallowed address 10.20.4.11
    ```

    On the **Provider Configuration** screen, click **Trusted Networks** → **Add network**, then enter:

    | Field | Value |
    | - | - |
    | **IP or CIDR** | The range your IdP resolves to - e.g. `10.20.0.0/16`. A bare IP such as `192.168.1.50` is treated as a single host (`/32`, or `/128` for IPv6). |
    | **Description** | Optional label, e.g. `On-prem Keycloak` |

    Add the range **before** clicking **Discover endpoints** - the allowlist is read at discovery time.

    <Frame caption="The Trusted Networks control on the Provider Configuration screen, shown for self-hostable providers.">
      <img src="https://mintcdn.com/bifrost-backport-outbound-fetchers/L0PPc5gg3uLKNILE/media/user-provisioning/generic-oidc/bifrost-trusted-networks.png?fit=max&auto=format&n=L0PPc5gg3uLKNILE&q=85&s=edfe52eff35e4f5b77193653d212024c" alt="Bifrost Generic OIDC Provider Configuration screen with a Trusted Networks button above the Issuer URL field" width="2908" height="1604" data-path="media/user-provisioning/generic-oidc/bifrost-trusted-networks.png" />
    </Frame>

    To remove a range later, reopen the same **Trusted Networks** sheet and delete the row.

    You can also declare the allowlist in `config.json` instead of the dashboard:

    ```json theme={null}
    {
      "scim_config": {
        "enabled": true,
        "provider": "generic",
        "trusted_networks": [{ "cidr": "10.20.0.0/16", "description": "On-prem Keycloak" }],
        "config": { "...": "provider fields" }
      }
    }
    ```

    Or, on Helm:

    ```yaml theme={null}
    bifrost:
      scim:
        enabled: true
        provider: "generic"
        trustedNetworks:
          - cidr: "10.20.0.0/16"
            description: "On-prem Keycloak"
    ```

    Declaring the key makes the file own the whole list: it replaces whatever is stored, and an explicit `[]` clears ranges added from the dashboard. Omit the key entirely to leave dashboard-managed ranges alone.
  </Step>

  <Step title="Fill in the provider configuration">
    Enter the credentials you copied in Step 3:

    | Field | Value |
    | - | - |
    | **Issuer URL** | Your IdP's OIDC issuer URL (no trailing slash) |
    | **Client ID** | Application Client ID |
    | **Client Secret** | Application Client Secret |
    | **Audience** | Optional - the expected `aud` claim. Defaults to Client ID. |

    Click **Discover endpoints** to auto-fill the authorize, token, and userinfo endpoints from your issuer's discovery document. Then click **Verify & Next**.

    <Frame caption="Provider Configuration - enter your OIDC issuer URL and client credentials, then Discover endpoints to validate.">
      <img src="https://mintcdn.com/bifrost-backport-outbound-fetchers/X75Bpt9SVa6WwN5p/media/user-provisioning/generic-oidc/bifrost-provider-config.png?fit=max&auto=format&n=X75Bpt9SVa6WwN5p&q=85&s=b38b935d7fa39545cbd9c4b647007913" alt="Bifrost Provider Configuration form showing Issuer URL, discovered endpoints, Client ID, Client Secret, and optional Audience fields" width="2912" height="1664" data-path="media/user-provisioning/generic-oidc/bifrost-provider-config.png" />
    </Frame>
  </Step>

  <Step title="Discover claims">
    On the Attribute Mapping screen, click **Discover Claims** to fetch live claims from your IdP.

    Bifrost opens a sign-in popup - no session is created. Once you authenticate, it returns the exact claims your IdP is sending in the JWT. Use this to confirm which attributes - groups, roles, department, or custom claims - are present before building your mappings.

    <Frame caption="Discover Claims - shows all claims the IdP is returning in the JWT so you can reference exact names when building mappings.">
      <img src="https://mintcdn.com/bifrost-backport-outbound-fetchers/X75Bpt9SVa6WwN5p/media/user-provisioning/generic-oidc/bifrost-discover-claims.png?fit=max&auto=format&n=X75Bpt9SVa6WwN5p&q=85&s=4477577c2a1197d605216a906fef8186" alt="Bifrost Discover Claims screen listing all claims returned by the generic OIDC provider" width="2912" height="1664" data-path="media/user-provisioning/generic-oidc/bifrost-discover-claims.png" />
    </Frame>

    <Note>
      If **Discover Claims** fails, confirm your IdP is configured to allow the `openid`, `profile`, and `email` scopes and that the discovery callback URI is registered.
    </Note>
  </Step>

  <Step title="Set up attribute mappings">
    Use the sections below the claim list to map IdP claim values to Bifrost roles, teams, and business units.

    **Attribute-to-Role Mappings**

    Map a claim value to a Bifrost role. All matching rules are evaluated. If several rules match, Bifrost picks one using your chosen resolution strategy:

    * **The role with the most permissions** (default)
    * **The first matching role, by list order** (drag rows to set priority)

    If no rule matches, login is denied.

    **Attribute-to-Team Mappings**

    Map a claim value to a Bifrost team. All matching rules apply.

    * Use a specific value (e.g. `engineering`) to map that exact claim value to a named team
    * Use `*` to sync the claim value directly as the team name
    * Use `${*}` to extract part of the string - e.g. `/${*}` matches `/Engineering` and creates team **Engineering**

    **Attribute-to-Business Unit Mappings**

    Same wildcard support as team mappings. When a rule matches, the resolved business unit is assigned to the user, and all matching rules apply, so a user can belong to several business units at once.

    <Frame caption="Attribute Mapping - configure role, team, and business unit rules based on the claims your IdP sends.">
      <img src="https://mintcdn.com/bifrost-backport-outbound-fetchers/X75Bpt9SVa6WwN5p/media/user-provisioning/generic-oidc/bifrost-attribute-setup.png?fit=max&auto=format&n=X75Bpt9SVa6WwN5p&q=85&s=ec0f7fa1386f7474dbed6da4e9115842" alt="Bifrost Attribute Mapping screen showing role and team mapping rules configured for the generic OIDC provider" width="2912" height="1664" data-path="media/user-provisioning/generic-oidc/bifrost-attribute-setup.png" />
    </Frame>

    <Note>
      Setting a value to `*` maps the claim value directly as the entity name. Value comparisons are case-insensitive.
    </Note>

    Click **Next** when done.
  </Step>

  <Step title="Review and enable">
    Review your full configuration - connection details, attribute mappings, and SCIM status - then click **Save & Enable**.

    <Frame caption="Review & Enable - confirm your connection and mappings before activating the provider.">
      <img src="https://mintcdn.com/bifrost-backport-outbound-fetchers/L0PPc5gg3uLKNILE/media/user-provisioning/generic-oidc/bifrost-review-enable.png?fit=max&auto=format&n=L0PPc5gg3uLKNILE&q=85&s=35f6fefd79d98a75e2d69cacdadd8b93" alt="Bifrost Review and Enable screen showing Generic OIDC Provider connection details and configured attribute mappings" width="2912" height="1664" data-path="media/user-provisioning/generic-oidc/bifrost-review-enable.png" />
    </Frame>

    <Warning>
      Restart your Bifrost server after enabling for the changes to take effect.
    </Warning>
  </Step>
</Steps>

***

## How background sync works

Bifrost refreshes active OIDC sessions every **15 minutes**. If a session cannot be refreshed, Bifrost checks with your IdP whether the user is still active; if the IdP reports the user as inactive, Bifrost decommissions that user locally.

For providers that support it, see [SCIM with Generic OIDC](./scim) to enable real-time user and group provisioning.

***

## Troubleshooting

**User is not redirected to the IdP** - verify the provider is enabled in Bifrost and the server was restarted after saving. Confirm the Issuer URL has no trailing slash and is reachable from your Bifrost server.

**Discover endpoints or Discover Claims fails with "access to IP ... is not allowed" or "resolves to a disallowed address"** - your IdP is on a private network. Add its IP or CIDR range under **Trusted Networks** on the Provider Configuration screen (see Step 5), then retry. If the error names `localhost` or `metadata.google.internal`, those hosts can never be trusted - use the IdP's real private address or internal DNS name.

**Discover endpoints fails with "URL scheme must be https"** - the guard on discovery requires TLS even for internal issuers. Terminate HTTPS in front of your IdP with a certificate your Bifrost host trusts.

**JWKS validation fails** - Bifrost fetches `<issuer>/.well-known/openid-configuration` to discover the JWKS endpoint. Ensure this URL is reachable from your Bifrost host.

**Audience mismatch** - set the **Audience** field in Bifrost to match the `aud` claim in the JWT. Leave blank to default to the Client ID.

**Claims are present in Discover Claims but role mapping is not working** - confirm the claim name matches exactly what the IdP sends (case-sensitive, including namespacing). Dotted paths (e.g. `realm_access.roles`) are supported.

**Login fails after successful IdP authentication** - check that the redirect URI in your IdP exactly matches `https://<your-bifrost-domain>/login`. Trailing slashes and path differences are not allowed.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.