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

# SSO Integration

> How to configure Single Sign-On with Keycloak using OIDC or SAML for enterprise identity providers like Entra ID, Okta, and Google Workspace.

# Configure SSO with Keycloak

CRAFT uses **Keycloak** as its identity provider, supporting Single Sign-On (SSO) via both **OIDC** and **SAML 2.0** protocols. This guide covers configuring SSO for enterprise identity providers including Microsoft Entra ID (Azure AD), Okta, Google Workspace, and PingFederate.

## Prerequisites

<Info>
  Before you begin, ensure you have:

  * Administrative access to the Keycloak admin console
  * Administrative access to your enterprise identity provider (IdP)
  * The Keycloak realm ID for your organization (realm ID = organization ID)
  * Network connectivity between Keycloak and the IdP (HTTPS required)
</Info>

## How SSO Works in CRAFT

Each organization in the platform maps to a **Keycloak realm**. When SSO is configured:

1. Users navigate to the platform login page
2. Keycloak redirects to the enterprise IdP for authentication
3. The IdP authenticates the user and returns claims to Keycloak
4. Keycloak issues a JWT containing `org_id` (from the realm) and group memberships
5. The platform uses the JWT for authorization via OpenFGA

<Note>
  Per-tenant SSO configuration means each organization can connect to a different identity provider. One organization might use Okta while another uses Entra ID.
</Note>

## Configure OIDC SSO

OIDC is the recommended protocol for most identity providers.

<Tabs>
  <Tab title="Microsoft Entra ID">
    <Steps>
      <Step title="Register an application in Entra ID">
        1. Navigate to **Azure Portal** > **Microsoft Entra ID** > **App registrations** > **New registration**
        2. Set the **Redirect URI** to: `https://<keycloak-host>/realms/<org-id>/broker/entra-id/endpoint`
        3. Note the **Application (client) ID** and **Directory (tenant) ID**
        4. Under **Certificates & secrets**, create a new client secret and note the value
      </Step>

      <Step title="Configure group claims">
        1. In the app registration, go to **Token configuration** > **Add groups claim**
        2. Select **Security groups** and set the token type to **ID**
        3. Ensure the groups claim format is set to **Group ID**
      </Step>

      <Step title="Add the IdP in Keycloak">
        1. Log in to Keycloak Admin Console
        2. Select the realm matching your organization ID
        3. Navigate to **Identity Providers** > **Add provider** > **OpenID Connect v1.0**
        4. Configure the following:

        | Field             | Value                                                                 |
        | ----------------- | --------------------------------------------------------------------- |
        | Alias             | `entra-id`                                                            |
        | Authorization URL | `https://login.microsoftonline.com/<tenant-id>/oauth2/v2.0/authorize` |
        | Token URL         | `https://login.microsoftonline.com/<tenant-id>/oauth2/v2.0/token`     |
        | Client ID         | Your Entra ID application client ID                                   |
        | Client Secret     | Your Entra ID client secret                                           |
        | Default Scopes    | `openid email profile`                                                |
      </Step>

      <Step title="Map groups to Keycloak roles">
        In the IdP configuration, add an **Attribute Importer** mapper:

        * **Mapper Type:** Attribute Importer
        * **Claim:** `groups`
        * **User Attribute Name:** `groups`
      </Step>
    </Steps>
  </Tab>

  <Tab title="Okta">
    <Steps>
      <Step title="Create an application in Okta">
        1. Navigate to **Okta Admin** > **Applications** > **Create App Integration**
        2. Select **OIDC - OpenID Connect** and **Web Application**
        3. Set the **Sign-in redirect URI** to: `https://<keycloak-host>/realms/<org-id>/broker/okta/endpoint`
        4. Note the **Client ID** and **Client secret**
      </Step>

      <Step title="Configure Okta groups">
        1. In the application settings, go to **Sign On** > **OpenID Connect ID Token**
        2. Set **Groups claim type** to **Filter**
        3. Set **Groups claim filter** to match the groups you want to sync
      </Step>

      <Step title="Add the IdP in Keycloak">
        1. Select the realm matching your organization ID
        2. Navigate to **Identity Providers** > **Add provider** > **OpenID Connect v1.0**
        3. Configure:

        | Field             | Value                                       |
        | ----------------- | ------------------------------------------- |
        | Alias             | `okta`                                      |
        | Authorization URL | `https://<okta-domain>/oauth2/v1/authorize` |
        | Token URL         | `https://<okta-domain>/oauth2/v1/token`     |
        | Client ID         | Your Okta client ID                         |
        | Client Secret     | Your Okta client secret                     |
        | Default Scopes    | `openid email profile groups`               |
      </Step>
    </Steps>
  </Tab>

  <Tab title="Google Workspace">
    <Steps>
      <Step title="Create OAuth credentials in Google Cloud">
        1. Navigate to **Google Cloud Console** > **APIs & Services** > **Credentials**
        2. Create an **OAuth 2.0 Client ID** of type **Web application**
        3. Add the redirect URI: `https://<keycloak-host>/realms/<org-id>/broker/google/endpoint`
        4. Note the **Client ID** and **Client secret**
      </Step>

      <Step title="Add the IdP in Keycloak">
        1. Select the realm matching your organization ID
        2. Navigate to **Identity Providers** > **Add provider** > **Google**
        3. Enter the Client ID and Client Secret
        4. Set **Default Scopes** to `openid email profile`
      </Step>
    </Steps>
  </Tab>
</Tabs>

## Configure SAML 2.0 SSO

For identity providers that prefer SAML, Keycloak supports SAML 2.0 as well.

<Steps>
  <Step title="Export the Keycloak SAML descriptor">
    Download the SAML metadata from your Keycloak realm:

    ```
    https://<keycloak-host>/realms/<org-id>/protocol/saml/descriptor
    ```

    Upload this XML to your IdP as the service provider metadata.
  </Step>

  <Step title="Configure the IdP">
    In your SAML IdP, configure the following:

    | Field          | Value                                                             |
    | -------------- | ----------------------------------------------------------------- |
    | Entity ID      | `https://<keycloak-host>/realms/<org-id>`                         |
    | ACS URL        | `https://<keycloak-host>/realms/<org-id>/broker/<alias>/endpoint` |
    | Name ID format | `urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress`          |
  </Step>

  <Step title="Add the SAML IdP in Keycloak">
    1. Navigate to **Identity Providers** > **Add provider** > **SAML v2.0**
    2. Import the IdP's SAML metadata XML or manually configure:
       * **Single Sign-On Service URL**
       * **Single Logout Service URL** (optional)
       * **Signing certificate**
    3. Set **NameID Policy Format** to `email`
  </Step>
</Steps>

## Just-In-Time User Provisioning

Keycloak supports **JIT provisioning** by default. When a user authenticates via SSO for the first time:

1. Keycloak creates a local user account in the realm
2. User attributes (email, name) are synced from the IdP
3. Group memberships are mapped from IdP claims to Keycloak groups
4. OpenFGA relationships are established based on group-to-role mappings

<Tip>
  JIT provisioning eliminates the need to pre-create user accounts. Users are provisioned automatically on their first SSO login.
</Tip>

## Enforce SSO (Disable Password Login)

To require SSO for all users in an organization:

1. In the Keycloak admin console, select the organization's realm
2. Navigate to **Authentication** > **Flows**
3. Edit the **Browser** flow to remove or disable the **Username Password Form**
4. Ensure the **Identity Provider Redirector** is enabled and set to your SSO provider

<Warning>
  Keycloak client credentials for service accounts remain available even when password login is disabled. This ensures CI/CD pipelines and machine-to-machine integrations continue to function.
</Warning>

## Session Management

Configure session behavior for your organization:

| Setting          | Location                  | Description                                             |
| ---------------- | ------------------------- | ------------------------------------------------------- |
| SSO Session Idle | Realm Settings > Sessions | Idle timeout before re-authentication (default: 30 min) |
| SSO Session Max  | Realm Settings > Sessions | Maximum session duration (default: 10 hours)            |
| Remember Me      | Realm Settings > Login    | Allow users to extend their session                     |

## Group-to-Role Mapping

Map IdP groups to OpenFGA roles for authorization:

| IdP Group         | Keycloak Group | OpenFGA Role |
| ----------------- | -------------- | ------------ |
| `Platform-Admins` | `admins`       | `admin`      |
| `Developers`      | `developers`   | `developer`  |
| `Data-Analysts`   | `members`      | `member`     |
| `Viewers`         | `viewers`      | `viewer`     |

The mapping pipeline flows: **IdP groups** -> **Keycloak groups** -> **OpenFGA relations**. See [RBAC Configuration](/guides/rbac-configuration) for setting up the OpenFGA side.

## Troubleshooting

<AccordionGroup>
  <Accordion title="Redirect loop after SSO login">
    Verify the redirect URI in your IdP matches the Keycloak broker endpoint exactly, including the protocol (HTTPS) and realm ID. Check for trailing slashes.
  </Accordion>

  <Accordion title="Groups not appearing in JWT">
    Ensure group claims are configured in the IdP and a group mapper is set up in the Keycloak identity provider configuration. Verify the claim name matches between the IdP and the Keycloak mapper.
  </Accordion>

  <Accordion title="User created but no permissions">
    Groups must be mapped from the IdP through Keycloak to OpenFGA. If the group-to-role mapping pipeline is not configured, users will authenticate but have no permissions. See the Group-to-Role Mapping section above.
  </Accordion>
</AccordionGroup>

## Next Steps

<CardGroup cols={2}>
  <Card title="RBAC Configuration" icon="user-shield" href="/guides/rbac-configuration">
    Configure OpenFGA roles and permissions to complete the authorization setup.
  </Card>

  <Card title="Authentication Deep Dive" icon="lock" href="/security/authentication">
    Learn about OIDC flows, token management, and machine-to-machine authentication.
  </Card>

  <Card title="SCIM Provisioning" icon="users" href="/security/compliance/soc2">
    Automate user provisioning with SCIM 2.0 for SOC 2 compliance.
  </Card>

  <Card title="Multi-Tenancy" icon="building" href="/platform/multi-tenancy">
    Understand how SSO integrates with the multi-tenant architecture.
  </Card>
</CardGroup>
