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

# Single Sign-On for Self-Hosted Overcut

> Connect a self-hosted Overcut installation (Kubernetes, AWS, or Docker Compose) to your organization's OIDC or SAML identity provider so your team signs in with it.

<Note>
  This page is for customer-managed installations. On Overcut Cloud, see
  [Single Sign-On](/docs/security/single-sign-on).
</Note>

A self-hosted installation can send your team to your organization's identity
provider (Okta, Microsoft Entra ID, Google Workspace, ADFS, or any OIDC or
SAML 2.0 provider). Users choose **Continue with SSO** on the login page,
below **Sign in with email**, and the `overcut` CLI sign-in offers the same
option. Email and password sign-in stays available, so the bootstrap admin
can always get in.

The Keycloak bundled with your installation brokers the login. You set up
providers with the `overcut-admin` command in the server container, not in the
Keycloak admin console.

## Before you start

* Overcut v1.3.0 or later, installed from the matching deployment kit.
* Shell access to run `kubectl exec` (Kubernetes, AWS) or `docker compose exec`
  (Docker Compose) against the installation.
* Admin access to your identity provider.
* The workspace users should join, and the email domain or domains they sign
  in with. Public mailbox domains such as `gmail.com` are refused.
* Keycloak must reach your identity provider over HTTPS. Behind an egress
  proxy or a TLS-intercepting proxy, configure the kit's proxy and CA bundle
  settings first. On Kubernetes and AWS they apply to Keycloak too. On Docker
  Compose, Keycloak has its own proxy and trust store settings in
  `standalone/.env`.

## How it works

1. A user chooses **Continue with SSO** and enters their work email.
2. Overcut looks up the email domain. If a provider is bound to it, the user
   goes to your identity provider.
3. Your provider authenticates the user and returns their email, first name,
   and last name.
4. An existing member is signed in. A user with an open invitation gets an
   account and joins the workspace. Anyone else is admitted only when
   auto-join is on for the provider, otherwise they are asked to request an
   invitation.

Users are matched by email: a person who already has a password account with
the same email keeps it, and both sign-in methods work afterwards. Bind only
domains your identity provider is authoritative for.

## Set up single sign-on

The commands below run the `overcut-admin` command inside the server
container. Use the form for your deployment (on Kubernetes, replace
`overcut` with your namespace if you installed into another one):

<CodeGroup>
  ```bash Kubernetes and AWS theme={"dark"}
  kubectl -n overcut exec -i deploy/server -- node ./overcut-admin.js <command>
  ```

  ```bash Docker Compose theme={"dark"}
  cd standalone
  docker compose exec -T server node ./overcut-admin.js <command>
  ```
</CodeGroup>

<Steps>
  <Step title="Turn on single sign-on" icon="toggle-on">
    **Kubernetes and AWS**: set `global.sso.enabled: true` in your values
    file (on AWS, `helm-values/overcut-values.local.yaml`) and run
    `helm upgrade`. On AWS, pass both `helm-values/overcut-values.rendered.yaml`
    and `helm-values/overcut-values.local.yaml` to the upgrade.

    **Docker Compose**: set `SSO_ENABLED=true` in `standalone/.env` and run
    `docker compose up -d`.

    The login page then shows **Continue with SSO**.
  </Step>

  <Step title="Pick an alias" icon="pen-to-square">
    Choose a short alias for the provider, using lowercase letters, digits,
    and hyphens, starting with a letter or digit (for example `acme-okta`). It appears in the URLs below as
    `<alias>`, and `<domain>` is your installation's hostname.
  </Step>

  <Step title="Create the application in your identity provider" icon="key">
    **OIDC**

    Create a web application with:

    | Setting | Value |
    | - | - |
    | Sign-in redirect URI | `https://<domain>/idp/realms/overcut/broker/<alias>/endpoint` |
    | Grant type | Authorization Code |
    | Client type | Confidential, with a client secret |
    | Scopes | `openid`, `profile`, `email` |

    Note the **issuer URL**, **client ID**, and **client secret**.

    **SAML 2.0**

    Create a SAML application with:

    | Setting | Value |
    | - | - |
    | Single sign-on URL (ACS URL) | `https://<domain>/idp/realms/overcut/broker/<alias>/endpoint` |
    | Audience URI (SP entity ID) | `https://<domain>/idp/realms/overcut` |
    | Name ID format | `EmailAddress` |
    | Assertion signing | Signed (required) |

    Add the attribute statements `email`, `firstName`, and `lastName`. Note
    the **identity provider metadata URL**. If your provider asks for
    Overcut's SP metadata, it is served at
    `https://<domain>/idp/realms/overcut/broker/<alias>/endpoint/descriptor`
    once the provider exists.

    Assign the users or groups who should be able to sign in.
  </Step>

  <Step title="Write the provider spec" icon="brackets-curly">
    Save the provider details as JSON. For OIDC:

    ```json acme-okta.json theme={"dark"}
    {
      "oidc": {
        "issuer": "https://acme.okta.com",
        "clientId": "0oa1b2c3d4",
        "clientSecret": "<client secret>"
      }
    }
    ```

    For SAML, `{"saml": {"metadataUrl": "https://..."}}`, or
    `{"saml": {"metadataXml": "<EntityDescriptor ...>"}}` when the metadata
    has no URL. If your provider sends attributes under other names (for
    example the long claim URIs of ADFS or Entra ID), add
    `"attributes": {"email": "...", "firstName": "...", "lastName": "..."}`
    at the top level, next to `oidc` or `saml`. If the OIDC discovery document
    is not at `<issuer>/.well-known/openid-configuration`, add
    `"discoveryUrl"` inside `oidc`. Unknown keys are rejected.

    The spec is read from standard input (`--spec=-`) or from a file
    (`--spec=<path>`), so the client secret never appears on a command line. Delete the file when you are done.
  </Step>

  <Step title="Create the provider" icon="link">
    Find the workspace ID, then create the provider and bind it to the
    workspace and its email domains:

    ```bash theme={"dark"}
    kubectl -n overcut exec -i deploy/server -- node ./overcut-admin.js workspaces list

    kubectl -n overcut exec -i deploy/server -- node ./overcut-admin.js sso create \
      --workspace=<workspace id> --alias=acme-okta --name="Acme" \
      --domains=acme.com,acme.io --spec=- < acme-okta.json
    ```

    This creates the provider in the bundled Keycloak with Overcut's settings
    and binds it in invitation-only mode (add `--auto-join` to start with
    auto-join on).
  </Step>

  <Step title="Check the setup" icon="circle-check">
    ```bash theme={"dark"}
    kubectl -n overcut exec -i deploy/server -- node ./overcut-admin.js sso doctor --alias=acme-okta
    ```

    Each check prints `[ok]`, `[FAIL]`, or `[??]` (could not verify). Fix
    every `[FAIL]` and look into any `[??]` before going on. Then invite one
    person from your organization and have them sign in through
    **Continue with SSO**.
  </Step>

  <Step title="Roll out to the team" icon="users">
    Invite the rest of the team, or turn on auto-join so anyone on the bound
    domains can sign in without an invitation:

    ```bash theme={"dark"}
    kubectl -n overcut exec -i deploy/server -- node ./overcut-admin.js sso update --alias=acme-okta --auto-join=true
    ```

    Workspace admins can also switch auto-join and the provider on or off
    under **Security → Single sign-on**.
  </Step>
</Steps>

## Operate

| Task | Command (after `node ./overcut-admin.js`) |
| - | - |
| List providers | `sso list` |
| Rotate an OIDC client secret or replace SAML metadata | `sso update --alias=<alias> --spec=- < new-spec.json` |
| Change the bound domains (replaces the list) | `sso update --alias=<alias> --domains=acme.com,acme.io` |
| Rename | `sso update --alias=<alias> --name="New name"` |
| Turn a provider off or on | `sso update --alias=<alias> --enabled=false` |
| Remove a provider | `sso delete --alias=<alias>` |
| Remove the binding but keep the provider in Keycloak | `sso delete --alias=<alias> --keep-idp` |
| Check everything | `sso doctor` |

`sso delete` removes the binding first, then the provider in Keycloak. If the
second part fails, run `sso delete --alias=<alias> --idp-only` to finish.
To switch a provider between OIDC and SAML, delete it and create it again;
`sso update` cannot change the protocol.

Upgrades keep your providers. Each upgrade brings the Keycloak realm up to
date and leaves users, passwords, and identity providers alone.

## Troubleshooting

<AccordionGroup>
  <Accordion title="sso doctor reports a failed check">
    * **SSO\_LOGIN\_ENABLED is true on the server**: single sign-on is not
      turned on. Repeat the first setup step.
    * **Realm has the "first broker login auto-link" flow** or **Client
      "overcut-web" maps the identity\_provider claim** (on Kubernetes and
      AWS, also **Client "overcut-cli" maps the identity\_provider claim**):
      the realm is from an older release and was not brought up to date.
      Upgrade to the current kit and check the realm update ran:
      `kubectl -n overcut logs job/keycloak-config-cli` or
      `docker compose logs keycloak-sync`.
    * **exists in Keycloak** or **uses the "first broker login auto-link"
      flow**: the provider was created or changed by hand. Re-apply it with
      `sso update --alias=<alias> --spec=- < spec.json`.
  </Accordion>

  <Accordion title="sso create fails with 403 from Keycloak, or says the realm has no auto-link flow">
    The Keycloak realm has not been brought up to date, so Overcut is not yet
    allowed to manage identity providers, or the realm lacks the
    "first broker login auto-link" flow. Upgrade to the current kit and check
    that the realm update succeeded: `kubectl -n overcut logs
            job/keycloak-config-cli` or `docker compose logs keycloak-sync`.
  </Accordion>

  <Accordion title="sso create fails while importing the metadata">
    Keycloak fetches the OIDC discovery document or SAML metadata itself. A
    timeout or TLS error means Keycloak cannot reach your identity provider:
    check the kit's proxy settings and, behind a TLS-intercepting proxy, that
    the proxy's CA is in the kit's CA bundle.
  </Accordion>

  <Accordion title="No single sign-on is configured for this email domain">
    No enabled provider is bound to the domain of the email the user entered,
    or single sign-on is turned off for the installation. Check for a typo,
    sign in with email instead, bind the domain with
    `sso update --alias=<alias> --domains=...`, or turn the provider on.
  </Accordion>

  <Accordion title="User has not been invited to the workspace yet">
    The user sees "Your organization uses single sign-on, but
    `<email>` has not been invited to the `<provider name>` workspace yet.
    Ask a workspace admin to invite you." The provider is in invitation-only
    mode and the user has no open invitation. Invite them, or turn on
    auto-join.
  </Accordion>

  <Accordion title="Single sign-on is not enabled for this identity provider">
    The provider was turned off, or single sign-on was turned off for the
    installation, while the user was signing in. Turn it back on with
    `sso update --alias=<alias> --enabled=true` or under
    **Security → Single sign-on**.
  </Accordion>

  <Accordion title="Your identity provider shows an error">
    The application on your provider's side does not match: check the redirect
    or ACS URL, that the user is assigned to the application, and for SAML
    that the certificate has not expired and assertions are signed. For SAML
    also check that the Overcut server's and the identity provider's clocks
    are in sync. For OIDC, if your provider asks how the client
    authenticates, choose the client secret sent in the request body
    (`client_secret_post`).
  </Accordion>
</AccordionGroup>

## Limitations

* **No single logout.** Signing out of Overcut does not sign you out of your
  identity provider.
* **One workspace per domain.** A given email domain can be bound to a single
  workspace.
* **Providers are managed with `overcut-admin`.** There is no screen for
  adding a provider; workspace admins can only switch auto-join and the
  provider on or off.

## Related

* [Single Sign-On](/docs/security/single-sign-on): the same feature on Overcut
  Cloud, including how membership modes work.
* [Privacy and Security](/docs/privacy-and-security): how Overcut protects
  workspace data and secrets.
