> ## Documentation Index
> Fetch the complete documentation index at: https://docs.getbifrost.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# SSO using OIDC

> Configure Keycloak as your identity provider for Bifrost Enterprise using OpenID Connect.

## Prerequisites

* A running Keycloak server (self-hosted or cloud) with admin access to a realm
* Bifrost Enterprise deployed and accessible
* Your Bifrost callback URL: `https://<your-bifrost-domain>/login`

***

## Step 1: Create an OIDC Client

<Steps>
  <Step title="Open the Clients list">
    In the Keycloak Admin Console, select your realm from the top-left dropdown.

    Go to **Clients** in the left nav and click **Create client**.

    <Frame caption="The Clients list — click Create client to start.">
      <img src="https://mintcdn.com/bifrost/t2xGvkL5ieUlU35Z/media/user-provisioning/keycloak/keycloak-create-client.png?fit=max&auto=format&n=t2xGvkL5ieUlU35Z&q=85&s=3cc912951088baccfd6cee5bf91fb38e" alt="Keycloak Admin Console Clients list with Create client button highlighted" width="3024" height="1660" data-path="media/user-provisioning/keycloak/keycloak-create-client.png" />
    </Frame>
  </Step>

  <Step title="Fill in General settings">
    Set the following fields:

    * **Client type**: OpenID Connect
    * **Client ID**: `bifrost-oidc` (or any identifier you prefer)
    * **Name**: `Bifrost`

    Click **Next**.

    <Frame caption="General settings — set Client type to OpenID Connect and provide a Client ID.">
      <img src="https://mintcdn.com/bifrost/t2xGvkL5ieUlU35Z/media/user-provisioning/keycloak/keycloak-client-creation.png?fit=max&auto=format&n=t2xGvkL5ieUlU35Z&q=85&s=3352416f4fd1b94fc32267f3848407f9" alt="Keycloak Create client General settings form with Client type OpenID Connect, Client ID bifrost-oidc, and Name Bifrost" width="3024" height="1660" data-path="media/user-provisioning/keycloak/keycloak-client-creation.png" />
    </Frame>
  </Step>

  <Step title="Configure Capability config">
    On the **Capability config** step, enable:

    * **Client authentication** — makes this a confidential client and generates a client secret
    * **Standard flow** — enables Authorization Code login
    * **Service accounts roles** — required for Bifrost to call the Keycloak Admin REST API for background user sync

    Leave all other toggles at their defaults. Click **Next**.
  </Step>

  <Step title="Configure Login settings">
    Set your redirect URIs:

    * **Root URL**: `https://<your-bifrost-domain>`
    * **Valid redirect URIs**: `https://<your-bifrost-domain>/login`

    Optionally, to use Discover Claims during setup, also add:

    ```
    https://<your-bifrost-domain>/workspace/scim/oauth-discover-callback
    ```

    Click **Save**.

    <Frame caption="Login settings — add your Bifrost login URL and optionally the Discover Claims callback URI.">
      <img src="https://mintcdn.com/bifrost/t2xGvkL5ieUlU35Z/media/user-provisioning/keycloak/keycloak-login-settings.png?fit=max&auto=format&n=t2xGvkL5ieUlU35Z&q=85&s=0be8ee68688e97e26561ca784f8cd3eb" alt="Keycloak Login settings form with Root URL, Valid redirect URIs showing the Bifrost login and oauth-discover-callback URLs" width="3024" height="1660" data-path="media/user-provisioning/keycloak/keycloak-login-settings.png" />
    </Frame>
  </Step>

  <Step title="Grant Admin REST API permissions to the service account">
    The client is now saved. Open it and go to the **Service accounts roles** tab.

    Click **Assign role**, filter by `realm-management`, and assign:

    | Role           | Required                                         |
    | -------------- | ------------------------------------------------ |
    | `view-users`   | Required — lets Bifrost list and import users    |
    | `view-realm`   | Recommended — enables group and role listing     |
    | `query-groups` | Optional — needed for group-based import filters |

    These permissions power the **Sync Users from Keycloak** import flow in [Optional Next Steps](#optional-next-steps).
  </Step>
</Steps>

***

## Step 2: Copy Your Client Secret

<Steps>
  <Step title="Open the Credentials tab">
    Open the **bifrost-oidc** client and go to the **Credentials** tab.

    Copy the **Client Secret** — you will need it in [Step 5](#step-5-configure-bifrost).

    <Frame caption="Credentials tab — copy the Client Secret.">
      <img src="https://mintcdn.com/bifrost/t2xGvkL5ieUlU35Z/media/user-provisioning/keycloak/keycloak-client-config.png?fit=max&auto=format&n=t2xGvkL5ieUlU35Z&q=85&s=2d2da4cfcf36de8f00827f4b97fa87ab" alt="Keycloak Credentials tab showing Client Authenticator set to Client Id and Secret with the Client Secret field" width="3024" height="1660" data-path="media/user-provisioning/keycloak/keycloak-client-config.png" />
    </Frame>
  </Step>
</Steps>

***

## Step 3: Configure Claim Mappers

Keycloak does not include realm roles or full group paths in tokens by default. Add two mappers to the client's dedicated scope.

<Steps>
  <Step title="Open the dedicated scope">
    In the **bifrost-oidc** client, go to the **Client scopes** tab.

    Click on the **bifrost-oidc-dedicated** scope.

    <Frame caption="Client scopes tab — open the dedicated scope to add mappers.">
      <img src="https://mintcdn.com/bifrost/t2xGvkL5ieUlU35Z/media/user-provisioning/keycloak/keycloak-client-scopes.png?fit=max&auto=format&n=t2xGvkL5ieUlU35Z&q=85&s=1ecbab2a0acbe810181a80a7d8ede808" alt="Keycloak Client scopes tab with bifrost-oidc-dedicated scope highlighted" width="3024" height="1660" data-path="media/user-provisioning/keycloak/keycloak-client-scopes.png" />
    </Frame>
  </Step>

  <Step title="Add the Group Membership mapper">
    Click **Add mapper** → **By configuration**.

    <Frame caption="Configure a new mapper — select Group Membership from the list.">
      <img src="https://mintcdn.com/bifrost/t2xGvkL5ieUlU35Z/media/user-provisioning/keycloak/keycloak-configure-new-mapper.png?fit=max&auto=format&n=t2xGvkL5ieUlU35Z&q=85&s=b01318dc936a4b5a854f55eef65aa5b0" alt="Keycloak Configure a new mapper dialog showing mapper type list with Group Membership visible" width="3024" height="1660" data-path="media/user-provisioning/keycloak/keycloak-configure-new-mapper.png" />
    </Frame>

    Select **Group Membership** and configure it:

    | Field                   | Value    |
    | ----------------------- | -------- |
    | **Name**                | `Groups` |
    | **Token Claim Name**    | `groups` |
    | **Full group path**     | **On**   |
    | **Add to ID token**     | **On**   |
    | **Add to access token** | **On**   |
    | **Add to userinfo**     | **On**   |

    Click **Save**.

    <Frame caption="Group Membership mapper — Full group path must be On so Bifrost receives paths like /Engineering instead of just Engineering.">
      <img src="https://mintcdn.com/bifrost/t2xGvkL5ieUlU35Z/media/user-provisioning/keycloak/keycloak-groups-mapping.png?fit=max&auto=format&n=t2xGvkL5ieUlU35Z&q=85&s=1feaa7827ac5bd8a187016fb3bb9f8c7" alt="Group Membership mapper form with Name Groups, Token Claim Name groups, Full group path On, and all Add to token toggles On" width="3024" height="1660" data-path="media/user-provisioning/keycloak/keycloak-groups-mapping.png" />
    </Frame>

    <Note>
      Keep **Full group path** enabled. Keycloak sends groups as paths (e.g. `/Engineering`, `/Platform`). Bifrost's `/${*}` wildcard in team mappings extracts the name after the slash automatically — see [Step 5](#step-5-configure-bifrost).
    </Note>
  </Step>

  <Step title="Add the User Realm Role mapper">
    Click **Add mapper** → **By configuration** again.

    Select **User Realm Role** from the list.

    <Frame caption="Select User Realm Role from the mapper list to expose realm roles in the JWT.">
      <img src="https://mintcdn.com/bifrost/t2xGvkL5ieUlU35Z/media/user-provisioning/keycloak/keycloak-realm-role-mapping.png?fit=max&auto=format&n=t2xGvkL5ieUlU35Z&q=85&s=a38d194337b202bc721220a5f057f19a" alt="Keycloak Configure a new mapper dialog with User Realm Role option highlighted" width="3024" height="1660" data-path="media/user-provisioning/keycloak/keycloak-realm-role-mapping.png" />
    </Frame>

    Configure it:

    | Field                   | Value                |
    | ----------------------- | -------------------- |
    | **Name**                | `realm_roles`        |
    | **Token Claim Name**    | `realm_access.roles` |
    | **Claim JSON Type**     | String               |
    | **Multivalued**         | **On**               |
    | **Add to ID token**     | **On**               |
    | **Add to access token** | **On**               |

    Click **Save**.

    <Frame caption="User Realm Role mapper — Token Claim Name realm_access.roles matches the dotted path Bifrost uses for role lookup.">
      <img src="https://mintcdn.com/bifrost/t2xGvkL5ieUlU35Z/media/user-provisioning/keycloak/keycloak-realm-role-config.png?fit=max&auto=format&n=t2xGvkL5ieUlU35Z&q=85&s=7bb78955ecdc2494f8ef61015f76bd05" alt="User Realm Role mapper form with Name realm_roles, Token Claim Name realm_access.roles, Multivalued On, and Add to ID and access token enabled" width="3024" height="1660" data-path="media/user-provisioning/keycloak/keycloak-realm-role-config.png" />
    </Frame>
  </Step>
</Steps>

***

## Step 4: Assign Users

In Keycloak, users need to be assigned to the realm roles and groups you plan to map in Bifrost.

* Go to **Users** → select a user → **Role mapping** tab → assign the relevant realm roles (e.g. `realm-admin`, `bifrost-viewer`)
* Go to **Users** → select a user → **Groups** tab → join the relevant groups (e.g. `/Engineering`, `/Platform`)

***

## Step 5: Configure Bifrost

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

    Select **Keycloak** as the identity provider and click **Next**.

    <Frame caption="Select Keycloak from the list of identity providers.">
      <img src="https://mintcdn.com/bifrost/t2xGvkL5ieUlU35Z/media/user-provisioning/keycloak/bifrost-user-provisioning.png?fit=max&auto=format&n=t2xGvkL5ieUlU35Z&q=85&s=bfc3b2be1f9fa7f67367caa8eaa566c9" alt="Bifrost Choose Provider screen with Keycloak card selected" width="3024" height="1666" data-path="media/user-provisioning/keycloak/bifrost-user-provisioning.png" />
    </Frame>
  </Step>

  <Step title="Fill in the provider configuration">
    Enter the details from the previous steps:

    * **Server URL**: your Keycloak base URL — no `/realms/...` suffix (e.g. `https://keycloak.company.com`)
    * **Realm**: your realm name (e.g. `Bifrost`)
    * **Client ID**: the client ID you set in Step 1 (e.g. `bifrost-oidc`)
    * **Client Secret**: copied from [Step 2](#step-2-copy-your-client-secret)
    * **Audience**: optional — leave blank to default to the Client ID
    * **Team IDs Field (Optional)**: leave as `groups` to match the mapper you created in Step 3

    Click **Verify & Next** to confirm the connection.

    <Frame caption="Provider Configuration — enter your Keycloak Server URL, Realm, Client ID, and Client Secret.">
      <img src="https://mintcdn.com/bifrost/t2xGvkL5ieUlU35Z/media/user-provisioning/keycloak/bifrost-keycloak-provider-config.png?fit=max&auto=format&n=t2xGvkL5ieUlU35Z&q=85&s=3ec6fb14ed634fcc2adef5f2a1b557d3" alt="Bifrost Provider Configuration form for Keycloak with Server URL, Realm, Client ID, Client Secret, and Team IDs Field filled in" width="3024" height="1666" data-path="media/user-provisioning/keycloak/bifrost-keycloak-provider-config.png" />
    </Frame>
  </Step>

  <Step title="Discover claims">
    On the Attribute Mapping screen, click **Discover Claims**.

    Bifrost opens a sign-in popup with your Keycloak realm — no session is created.

    Once you authenticate, it returns the exact claims your Keycloak tenant is sending in the JWT. Confirm that `groups` and `realm_access.roles` appear before building your mappings.

    <Frame caption="Discover Claims shows the live JWT from Keycloak — confirm groups (full paths) and realm_access.roles are present.">
      <img src="https://mintcdn.com/bifrost/t2xGvkL5ieUlU35Z/media/user-provisioning/keycloak/bifrost-keycloak-discover-claims.png?fit=max&auto=format&n=t2xGvkL5ieUlU35Z&q=85&s=043c54ed4af32ab1a34ab55bcdfea879" alt="Bifrost Discover Claims screen showing claims including email, groups with /Engineering and /Platform paths, and realm_access with roles array" width="3024" height="1668" data-path="media/user-provisioning/keycloak/bifrost-keycloak-discover-claims.png" />
    </Frame>
  </Step>

  <Step title="Set up attribute mappings">
    Use the sections below the claim list to map Keycloak 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 multiple rules match, the role with the highest permissions is assigned
    * If no rule matches, the user is not assigned a role and login is denied

    Example: map `realm_access.roles` → `realm-admin` → **Admin**, and `realm_access.roles` → `bifrost-viewer` → **Viewer**.

    **Attribute-to-Team Mappings**

    Map a claim value to a Bifrost team. All matching rules apply. Three value formats work:

    * **Exact value** — e.g. `/Engineering` maps that specific group to a fixed team name
    * **`*`** — syncs the claim value directly as the team name
    * **`/${*}`** — extracts the group name from Keycloak's full group path — e.g. `/${*}` matches `/Engineering` and creates team **Engineering**, and matches `/Platform` and creates team **Platform**

    **Attribute-to-Business Unit Mappings**

    Same wildcard support as team mappings. Three value formats work:

    * **Exact value** — maps a specific claim value to a fixed business unit name
    * **`*`** — syncs the claim value directly as the business unit name
    * **`/${*}`** — extracts the group name from Keycloak's full group path, same as team mappings (e.g. `/${*}` on `/Engineering` → business unit **Engineering**)
    * When a rule matches, the resolved business unit is assigned to all of that user's teams
    * Manually assigned teams are left unchanged

    <Frame caption="Attribute Mapping — role rules use realm_access.roles, team rules use groups with /${*} to extract the team name from Keycloak's full group path.">
      <img src="https://mintcdn.com/bifrost/t2xGvkL5ieUlU35Z/media/user-provisioning/keycloak/bifrost-keycloak-attribute-mapping.png?fit=max&auto=format&n=t2xGvkL5ieUlU35Z&q=85&s=dd12ae45a4227bf6d5dc478aaa59f9bc" alt="Bifrost Attribute Mapping screen showing realm_access.roles mapped to Admin and Viewer roles, and groups mapped with /${*} wildcard to extract team names" width="3024" height="1670" data-path="media/user-provisioning/keycloak/bifrost-keycloak-attribute-mapping.png" />
    </Frame>

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

  <Step title="Review and enable">
    Review your configuration on the final screen and click **Enable**.

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

***

## Optional Next Steps

**Import users from Keycloak** — once SSO is configured, you can bulk-import users from Keycloak into Bifrost without waiting for each user to log in. Go to **Governance** → **Users** → **Sync Users from Keycloak** and filter by group or realm role to preview and import matching users.

<Frame caption="Sync Users from Keycloak — filter by group membership or realm role to select which users to import into Bifrost.">
  <img src="https://mintcdn.com/bifrost/t2xGvkL5ieUlU35Z/media/user-provisioning/keycloak/bifrost-sync-users.png?fit=max&auto=format&n=t2xGvkL5ieUlU35Z&q=85&s=aacca22d46c5268273255649f7de4bae" alt="Sync Users from IdP dialog showing Filter by Groups with Engineering, Operations, and Platform checkboxes, and Filter by Roles section" width="3024" height="1670" data-path="media/user-provisioning/keycloak/bifrost-sync-users.png" />
</Frame>

Imported users appear in **Governance** → **Users** with their role and team assignments applied immediately.

<Frame caption="Users page after syncing — users are marked Managed by Keycloak and receive their roles and teams from the attribute mappings.">
  <img src="https://mintcdn.com/bifrost/t2xGvkL5ieUlU35Z/media/user-provisioning/keycloak/bifrost-users-page.png?fit=max&auto=format&n=t2xGvkL5ieUlU35Z&q=85&s=a5bb2d129da0c57eb6081c30495434a1" alt="Bifrost Users page showing a user with Admin role and Engineering and Platform teams, marked Managed by Keycloak" width="3024" height="1670" data-path="media/user-provisioning/keycloak/bifrost-users-page.png" />
</Frame>

***

## Troubleshooting

**`serverUrl must not include /realms/{realm}`** — the Server URL field takes the base Keycloak URL only. Set the realm separately in the Realm field. Example: `https://keycloak.company.com` + Realm `Bifrost` — not `https://keycloak.company.com/realms/Bifrost`.

**Users are redirected back to login** — confirm the client's **Valid redirect URIs** exactly match your Bifrost login URL (trailing slash matters). Verify the client is **Enabled** in Keycloak.

**Roles not appearing in the token** — check that the **User Realm Role** mapper adds to both ID and access tokens. Use **Evaluate** on the client scope in Keycloak to preview the token a specific user would receive.

**Groups not appearing in the token** — verify the **Group Membership** mapper has **Full group path** enabled and is added to ID token, access token, and userinfo.

**`jwks keys not found`** — confirm the Server URL is reachable from Bifrost. The JWKS endpoint is `{serverUrl}/realms/{realm}/protocol/openid-connect/certs`.
