--- title: "User Provisioning (SCIM)" description: "Authenticate users, sync teams, and provision roles and business units from your identity provider using SCIM-backed OAuth 2.0 / OIDC flows." icon: "users-gear" --- ## Overview Bifrost Enterprise uses **SCIM-backed identity provisioning** to connect your organization's identity provider to Bifrost. A single configuration gives you: - **Single sign-on (SSO)** via OAuth 2.0 / OIDC with JWKS-based JWT validation - **Automatic role assignment** using custom claims, app roles, or group-to-role mappings - **Team synchronization** from IdP groups into Bifrost teams - **Business unit mapping** from IdP attributes to Bifrost business units - **Bulk user provisioning** with filter-preview before import - **Silent token refresh** using server-stored refresh tokens Once configured, users sign in to Bifrost with their corporate credentials and inherit the right [role and permissions](./rbac) immediately — no manual account creation. User Provisioning overview in Bifrost dashboard --- ## Supported Identity Providers Pick your IdP to follow a step-by-step setup guide. All providers share the same Bifrost configuration surface — the only difference is how the OAuth client and role/group claims are created on the provider side. OIDC with Org or Custom Authorization Servers, plus group-to-role mapping and API tokens for bulk user sync. Entra ID (Azure AD) with app roles, group claims, and v1.0 / v2.0 token support. Cloud or self-hosted Zitadel with project-scoped role claims and service-account-based provisioning. Google Workspace domains with OAuth login plus optional Directory API sync via a service account. --- ## How it works SCIM authentication and provisioning flow 1. **Login** — Bifrost redirects unauthenticated users to the provider's authorization endpoint (Authorization Code flow). 2. **Token exchange** — on callback, Bifrost exchanges the code for an access token and refresh token, stores them in an `HttpOnly` cookie / server session, and validates the JWT against the provider's JWKS. 3. **Identity extraction** — configurable JWT claims (`userIdField`, `rolesField`, `teamIdsField`) are mapped to a Bifrost user, role, and teams. Provider-specific app roles or custom attributes override claim lookup. 4. **Attribute mapping** — optional `attributeRoleMappings`, `attributeTeamMappings`, and `attributeBusinessUnitMappings` translate arbitrary claim values (e.g., a department string or Okta group name) into Bifrost roles, teams, or business units. 5. **Bulk import** — admins can preview users matching a filter and bulk-import them via the dashboard, which calls the provider's user directory API. 6. **Silent refresh** — when the access token expires, Bifrost uses the stored refresh token to mint a new one without requiring re-login. --- ## Capabilities | Capability | Description | | --- | --- | | **OAuth 2.0 / OIDC SSO** | Authorization Code + PKCE with configurable scopes (`openid profile email offline_access`). | | **JWKS validation** | JWTs are validated against the provider's published JWKS keys; configuration is cached and auto-refreshed. | | **Role mapping** | Map from a claim value (string or array) to Admin / Developer / Viewer or a custom role. Highest-privilege wins when multiple match. | | **Team mapping** | Map multiple claim values to Bifrost teams in a single pass (a user can belong to many teams). | | **Business unit mapping** | Same as team mapping but scoped to business units. | | **Provisioning preview** | Preview up to 50 users matching filters (groups, roles, departments) before importing. | | **Bulk import** | Import matched users into Bifrost with role + team + BU assignments applied. | | **Team sync** | Sync IdP groups as Bifrost teams with a single action. | | **Business unit sync** | Sync IdP organizational units as Bifrost business units. | | **Deprovisioning** | Re-running import reconciles removed users and updates role / team assignments. | | **API key pass-through** | Requests using Bifrost API keys (`bfst-*`) bypass SCIM middleware so inference traffic is not affected. | --- ## Configuration reference All providers share the same outer config shape in `config.json`: ```json { "scim_config": { "enabled": true, "provider": "okta | entra | zitadel | keycloak | google", "config": { "...": "provider-specific fields — see each IdP guide" } } } ``` Shared fields across providers: | Field | Required | Description | | --- | --- | --- | | `clientId` | Yes | OAuth client ID from the identity provider. | | `clientSecret` | Usually | Client secret. Required for confidential clients and (where applicable) token revocation. | | `audience` | Optional | JWT audience to validate against. Defaults vary per provider. | | `attributeRoleMappings` | Optional | Ordered list of `{ attribute, value, role }` rules evaluated top-to-bottom. | | `attributeTeamMappings` | Optional | List of `{ attribute, value, team }` rules (all matches apply). | | `attributeBusinessUnitMappings` | Optional | List of `{ attribute, value, businessUnit }` rules (all matches apply). | Provider-specific fields (domain, tenant ID, server URL, service-account credentials) are documented in each IdP's setup guide. Changing `scim_config` at runtime through the UI is applied after saving. For file-based configuration, restart the Bifrost server to pick up changes. --- ## Configuring from the dashboard 1. Navigate to **Governance → User Provisioning** in the Bifrost dashboard. 2. Select your identity provider from the **SCIM Provider** dropdown. 3. Fill in the provider-specific fields. Required fields are marked and validated on **Verify**. Selecting a SCIM provider in the Bifrost dashboard 4. Click **Verify** to test credentials end-to-end. Bifrost will reach the provider's JWKS / directory endpoint and report any failures. 5. Configure **Attribute → Role / Team / Business Unit** mappings as needed. 6. Toggle **Enabled** and click **Save Configuration**. After enabling a new provider, the next dashboard load redirects to your IdP for login. Test in an incognito window first to avoid being locked out of your current session. --- ## Attribute mappings Attribute mappings let you translate claim values into Bifrost roles, teams, or business units without forcing your IdP admins to restructure claim names. Preview of users matching an import filter Each mapping is an ordered rule: ```json { "attribute": "department", "value": "Engineering", "role": "developer" } ``` Rules are evaluated top-to-bottom: - **Role mappings** — first match wins. Set a fallback with `"attribute": "*"` at the end. - **Team mappings** and **business unit mappings** — all matching rules apply, so a user with `department=Platform` and `group=sre` can be placed on multiple teams. Claim values can be strings, arrays, or nested objects — Bifrost resolves dotted paths (e.g., `realm_access.roles`). --- ## Bulk user provisioning Once SCIM is enabled, import users in bulk from your IdP: 1. Go to **Governance → User Provisioning → Import Users**. 2. Select a filter — groups, roles, departments, or a custom query depending on provider support. 3. Click **Preview** to see up to 50 matching users. 4. Click **Import** to create them in Bifrost with role / team / BU assignments applied. Preview of users matching an import filter Re-running an import reconciles existing users — role and team changes in the IdP are reflected on the next import. --- ## Troubleshooting | Symptom | Likely cause | | --- | --- | | Access denied: no application role or group mapping is assigned to this user. | Make sure you have assigned user to the Bifrost IdP application and they have a valid group/attribute mapping to role in Bifrost | | Redirect loop on login | Make sure you have restarted pods/Bifrost instance after changing SCIM configuration, or check for a redirect URI mismatch. Exact string match required — check trailing slashes and `http` vs `https`. | | `invalid audience` | `audience` field does not match the access token's `aud` claim. Use the same value your IdP issues. | | Empty roles / teams | Claim mapping is off. Verify the JWT at [jwt.io](https://jwt.io) and check `rolesField` / `teamIdsField`. | | Token refresh failing | `offline_access` scope missing or refresh token revoked. Re-enable the scope and re-authenticate. | | First user gets Admin | By design — if no matching role mapping applies, the first user is promoted to Admin so they can finish configuration. Subsequent users default to Viewer. | Provider-specific troubleshooting lives in each IdP's guide. --- ## Related - [Role-Based Access Control](./rbac) — permissions model and custom roles - [Advanced Governance](./advanced-governance) — budgets, limits, and compliance - [Audit Logs](./audit-logs) — track authentication events and role changes