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

# Okta

> Connect Okta to ClosedLoop AI for OIDC SSO, SCIM provisioning, Universal Logout, and role entitlements.

Connect Okta to ClosedLoop AI to centralize enterprise sign-in, automate user and group provisioning, govern workspace access, and revoke active access during security events.

<Tip>Use one Okta integration for one ClosedLoop AI region. Do not mix US and EU URLs in the same Okta app instance.</Tip>

## What Okta Manages

| Capability            | Description                                                                                   |
| --------------------- | --------------------------------------------------------------------------------------------- |
| OIDC SSO              | Users sign in to ClosedLoop AI through Okta OpenID Connect.                                   |
| SCIM 2.0 provisioning | Okta manages user and group lifecycle in a ClosedLoop AI workspace.                           |
| Universal Logout      | Okta can revoke a user's active ClosedLoop AI and MCP access through Global Token Revocation. |
| Role entitlements     | Okta can discover ClosedLoop AI roles for governance and access review workflows.             |

## Prerequisites

* An Okta admin account with permission to configure applications and provisioning.
* A ClosedLoop AI workspace admin account.
* Your ClosedLoop AI workspace region: US or EU.
* Your ClosedLoop AI workspace ID. ClosedLoop AI provides this value during Okta setup.

## Region URLs

Use the row that matches your ClosedLoop AI workspace region.

| Region | App URL                        | API URL                        |
| ------ | ------------------------------ | ------------------------------ |
| US     | `https://app.closedloop.sh`    | `https://api.closedloop.sh`    |
| EU     | `https://eu.app.closedloop.sh` | `https://eu.api.closedloop.sh` |

## Setup Guide

<AccordionGroup>
  <Accordion icon="key-round" title="Step 1: Add the ClosedLoop AI app in Okta">
    1. In Okta Admin, go to **Applications**.
    2. Add the **ClosedLoop AI** integration.
    3. When Okta asks for tenant settings, enter your ClosedLoop AI workspace ID.

    Use this tenant setting:

    | Label                      | Name      | Value                             |
    | -------------------------- | --------- | --------------------------------- |
    | ClosedLoop AI workspace ID | `team_id` | Your ClosedLoop AI workspace UUID |

    Okta references this value as `app.team_id` when it builds dynamic URLs.
  </Accordion>

  <Accordion icon="log-in" title="Step 2: Configure OIDC SSO">
    Use the values for your region.

    | Okta field              | US value                                                              | EU value                                                                 |
    | ----------------------- | --------------------------------------------------------------------- | ------------------------------------------------------------------------ |
    | Redirect URI            | `https://api.closedloop.sh/api/okta/oidc/callback`                    | `https://eu.api.closedloop.sh/api/okta/oidc/callback`                    |
    | Initiate login URI      | `https://api.closedloop.sh/api/okta/oidc/login?team_id={app.team_id}` | `https://eu.api.closedloop.sh/api/okta/oidc/login?team_id={app.team_id}` |
    | Post-logout URI         | `https://app.closedloop.sh/auth`                                      | `https://eu.app.closedloop.sh/auth`                                      |
    | Configuration guide URL | `https://closedloop.sh/docs/integrations/okta`                        | `https://closedloop.sh/docs/integrations/okta`                           |

    After Okta creates the OIDC client, copy the Okta **Issuer**, **Client ID**, and **Client secret**.
  </Accordion>

  <Accordion icon="shield-check" title="Step 3: Save OIDC settings in ClosedLoop AI">
    1. Sign in to ClosedLoop AI as a workspace admin.
    2. Go to **Integrations** > **Okta**.
    3. Enter your Okta domain.
    4. Paste the Okta **Client ID** and **Client secret**.
    5. Keep **Enable Okta sign-in** on.
    6. Turn on **Just-in-time provisioning** only if users should be created when they first sign in through Okta.
    7. Click **Save Okta setup**.

    ClosedLoop AI generates the Okta issuer from your domain and shows the region-specific setup URLs for the workspace.
  </Accordion>

  <Accordion icon="refresh-cw" title="Step 4: Configure Universal Logout">
    Universal Logout is separate from the post-logout URI. Use the Global Token Revocation endpoint below.

    | Okta field                       | US value                                              | EU value                                                 |
    | -------------------------------- | ----------------------------------------------------- | -------------------------------------------------------- |
    | Global token revocation endpoint | `https://api.closedloop.sh/api/okta/universal-logout` | `https://eu.api.closedloop.sh/api/okta/universal-logout` |
    | Authentication method            | `SIGNED_JWT`                                          | `SIGNED_JWT`                                             |
    | Subject format                   | `Email`                                               | `Email`                                                  |
    | Partial support                  | Off                                                   | Off                                                      |

    When Okta sends a valid Global Token Revocation request, ClosedLoop AI revokes the user's ClosedLoop AI API tokens and MCP tokens.
  </Accordion>

  <Accordion icon="users" title="Step 5: Configure SCIM provisioning">
    Use OAuth 2.0 for SCIM authentication. Okta obtains a bearer token from ClosedLoop AI and uses it for SCIM calls.

    | Okta field         | US value                                                  | EU value                                                     |
    | ------------------ | --------------------------------------------------------- | ------------------------------------------------------------ |
    | Base URL           | `'https://api.closedloop.sh/api/scim/v2/' + app.team_id`  | `'https://eu.api.closedloop.sh/api/scim/v2/' + app.team_id`  |
    | Authorize endpoint | `https://api.closedloop.sh/api/okta/scim/oauth/authorize` | `https://eu.api.closedloop.sh/api/okta/scim/oauth/authorize` |
    | Token endpoint     | `https://api.closedloop.sh/api/okta/scim/oauth/token`     | `https://eu.api.closedloop.sh/api/okta/scim/oauth/token`     |
    | Scopes             | `scim.read, scim.write, entitlements.read`                | `scim.read, scim.write, entitlements.read`                   |

    SCIM Base URL fields use Okta Expression Language string concatenation. Enter the quote characters exactly as shown.

    Supported user operations:

    | Operation              | Setting |
    | ---------------------- | ------- |
    | Create                 | On      |
    | Read                   | On      |
    | Update                 | On      |
    | Change password        | Off     |
    | Deactivate             | On      |
    | Support PATCH for User | On      |

    Supported group operations:

    | Operation           | Setting |
    | ------------------- | ------- |
    | Create              | On      |
    | Read                | On      |
    | Update (Uses PATCH) | On      |
    | Delete              | On      |

    ClosedLoop AI provisions Okta-created users as **Member** by default and keeps profile, group, and access status in sync from Okta.
  </Accordion>

  <Accordion icon="layers" title="Step 6: Configure entitlements">
    Enable Entitlement Management if your Okta plan includes it.

    Resource type mapping:

    | Field         | Value                           |
    | ------------- | ------------------------------- |
    | Resource Type | `Role`                          |
    | Endpoint      | `/Roles`                        |
    | Properties    | `id, displayName, description`  |
    | Description   | `ClosedLoop AI workspace roles` |

    Entitlements schema mapping:

    | Okta Attribute | ClosedLoop AI Attribute |
    | -------------- | ----------------------- |
    | `id`           | `id`                    |
    | `displayName`  | `displayName`           |
    | `description`  | `description`           |

    ClosedLoop AI exposes role entitlements to Okta for access governance workflows.
  </Accordion>
</AccordionGroup>

## SCIM Attribute Mapping

ClosedLoop AI reads the following SCIM user attributes:

| Okta attribute                  | ClosedLoop AI usage            |
| ------------------------------- | ------------------------------ |
| `userName`                      | Primary email address          |
| `emails[primary eq true].value` | Primary email address fallback |
| `name.givenName`                | First name                     |
| `name.familyName`               | Last name                      |
| `displayName`                   | Full name fallback             |
| `active`                        | Workspace access status        |
| `externalId`                    | Okta-side stable identifier    |

ClosedLoop AI does not use Okta passwords. Leave password management disabled in provisioning.

ClosedLoop AI also reads SCIM group `displayName`, `externalId`, and `members` for group lifecycle management.

## Testing

After configuration, test in this order:

1. Assign a test user to the ClosedLoop AI app in Okta.
2. Run provisioning so Okta creates the user in ClosedLoop AI.
3. Sign in to ClosedLoop AI with the test user's email address.
4. Confirm the user is redirected to Okta and returns to ClosedLoop AI after authentication.
5. Deactivate the user in Okta and confirm ClosedLoop AI access is removed.
6. Run a Universal Logout test from Okta and confirm the user must sign in again.

## Troubleshooting

| Symptom                                                       | Fix                                                                                                                       |
| ------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
| Okta reports an invalid SCIM base URL                         | Confirm the base URL uses string concatenation with `app.team_id` and that the tenant setting name is `team_id`.          |
| Users can authenticate in Okta but cannot enter ClosedLoop AI | Confirm the user is assigned to the Okta app and is provisioned or Just-in-time provisioning is enabled in ClosedLoop AI. |
| The OIDC callback fails                                       | Confirm the Redirect URI exactly matches the region-specific callback URL.                                                |
| Universal Logout returns 401                                  | Confirm Okta is using `SIGNED_JWT` and the Global Token Revocation endpoint for the same region as the workspace.         |
| A user is deactivated but still has the app open              | Confirm Okta sent the SCIM deactivation or Universal Logout event for the same ClosedLoop AI region.                      |

<CardGroup cols={2}>
  <Card title="Open ClosedLoop AI US" icon="log-in" href="https://app.closedloop.sh/integrations/okta">
    Configure Okta in the US workspace integrations page
  </Card>

  <Card title="Open ClosedLoop AI EU" icon="log-in" href="https://eu.app.closedloop.sh/integrations/okta">
    Configure Okta in the EU workspace integrations page
  </Card>
</CardGroup>
