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

# Set up SSO for the dashboard

> Wire an OIDC identity provider (Keycloak, Okta, Auth0, generic OIDC) into the ForceAI dashboard login, then map users to roles and access groups.

ForceAI's dashboard supports single sign-on through any OIDC provider. This guide uses Keycloak as the example, but the same fields work for Okta, Auth0, or any generic OIDC issuer. When it is done, users click "Login with SSO" and authenticate with your identity provider instead of a password, and their role and capabilities come from your directory

The login flow is a standard authorization-code exchange: the browser goes to `{proxy_base_url}/sso/key/generate`, bounces to your provider, and your provider redirects back to `{proxy_base_url}/sso/callback`, which the dashboard's nginx routes to the backend

<Info>
  You need admin access to configure this. Sign in with the local admin (username `admin` and your `LITELLM_MASTER_KEY`) so you have the full sidebar, since an SSO user with a limited role cannot reach these pages
</Info>

## Prerequisites

* An OIDC provider and its discovery document (the `.well-known/openid-configuration`), which gives you the authorization, token, and userinfo endpoints
* The URL your users open the dashboard at, for example `http://localhost:3000`. This is your `proxy_base_url`
* Permission to create a client in your provider

## Step 1: Create a client in your provider

In Keycloak, open your realm and go to **Clients -> Create client**:

<Steps>
  <Step title="Client basics">
    Client type **OpenID Connect**, and a Client ID you will paste into the dashboard, for example `forceai-ui`
  </Step>

  <Step title="Enable the browser login flow">
    Turn **Client authentication** on (this makes it confidential and gives it a secret) and enable the **Standard flow** (authorization code). A bearer-only or service-account-only client cannot complete the browser login
  </Step>

  <Step title="Register the callback">
    Set **Valid redirect URIs** to `{proxy_base_url}/sso/callback`, for example `http://localhost:3000/sso/callback`, and **Web origins** to `{proxy_base_url}`, for example `http://localhost:3000`
  </Step>

  <Step title="Copy the secret">
    Save, then open the **Credentials** tab and copy the client secret. The Client ID and this secret are the only two values that are not in your discovery document
  </Step>
</Steps>

<Warning>
  The redirect URI you register here must match `{proxy_base_url}/sso/callback` character for character, including scheme and no trailing slash. A mismatch is the single most common failure (see [Troubleshooting](#troubleshooting))
</Warning>

## Step 2: Configure SSO in the dashboard

Go to **Admin Settings -> SSO Settings -> Configure SSO**, pick the generic OIDC provider, and fill the fields. Everything except the Client ID and secret comes straight from your discovery document

| Field                  | Value                                  | From                               |
| ---------------------- | -------------------------------------- | ---------------------------------- |
| SSO Provider           | Generic OIDC                           | -                                  |
| Generic Client ID      | `forceai-ui`                           | step 1                             |
| Generic Client Secret  | the client secret                      | step 1 Credentials tab             |
| Authorization Endpoint | `.../protocol/openid-connect/auth`     | discovery `authorization_endpoint` |
| Token Endpoint         | `.../protocol/openid-connect/token`    | discovery `token_endpoint`         |
| Userinfo Endpoint      | `.../protocol/openid-connect/userinfo` | discovery `userinfo_endpoint`      |
| Proxy Admin Email      | the email of your first admin          | your directory                     |
| Proxy Base URL         | `http://localhost:3000`                | how users reach the dashboard      |

Save. The Proxy Base URL must be the same origin you registered the callback against in step 1

## Step 3: Test the login

<Steps>
  <Step title="Keep the config tab open">
    Do not close the tab where you just saved, so you can fix the config if the login fails
  </Step>

  <Step title="Log in from a new tab">
    Open a new tab, go to the dashboard, and click **Login with SSO**. You should bounce to your provider, sign in, and land back in the dashboard
  </Step>
</Steps>

## Map users to roles

The role decides the sidebar and admin powers. With nothing configured, every SSO user falls through to the default role (a restricted internal viewer), which is why a fresh SSO user sees a stripped-down sidebar. The role is decided at each login in this order:

1. If the user's email equals the **Proxy Admin Email** in the config, they become `proxy_admin`
2. Else if **Role Mappings** are on and a value in the group claim matches, they get the mapped role
3. Else they get the default role

### By email (one admin)

Set **Proxy Admin Email** to that user's email in the SSO config. Simplest for a single admin. It only elevates that one address

### By group (scalable)

Map a directory group or role to a ForceAI role so membership drives access:

<Steps>
  <Step title="Expose the groups in the token">
    Realm roles already arrive as `realm_access.roles`. To use groups instead, add a **Group Membership** mapper on the client's dedicated scope with claim name `groups` and "Full group path" off
  </Step>

  <Step title="Turn on Role Mappings">
    In the SSO config, enable **Use Role Mappings**, set **Group Claim** to `realm_access.roles` (or `groups`), and map for example `forceai-admin` to Proxy Admin and `forceai-user` to Internal User
  </Step>

  <Step title="Assign users in your provider">
    Add users to those groups or roles. On their next login the role is applied
  </Step>
</Steps>

<Info>
  ForceAI sets the role on the user record at login. A user who already logged in with the default role is upgraded on the next login once the email or mapping matches. If it does not flip, set the role once on the Internal Users page and SSO keeps it in sync afterward
</Info>

## Map users to access groups

Role controls the sidebar; access groups control which skills, models, agents, and MCP servers a user may actually call. The **Access Group Mappings** section sits right below Role Mappings and uses the same group claim. Map a directory group to an access group id, for example `pinesmith-traders` to `ag-traders`, and members of that group inherit that access group. One group can both set a role and unlock a capability set

## Troubleshooting

**"Invalid parameter: redirect\_uri" on the provider's page.** The callback ForceAI sent is not registered on the client. ForceAI sends `{proxy_base_url}/sso/callback`. Add that exact URL to the client's Valid redirect URIs, and confirm the Client ID in the config matches the client you edited

**The login works but the sidebar is limited.** The user got the default role because no email or group mapping matched. Set the Proxy Admin Email or configure Role Mappings, then log out and back in

**The token exchange fails after the provider login.** The backend calls the token and userinfo endpoints server to server, so the backend container must have outbound network access to your provider's host. If the provider is on a private network, make sure the backend can reach it

**The callback is `http://localhost` but the issuer is HTTPS.** That is fine. The browser handles the local callback while the backend talks to the HTTPS provider directly
