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

# Single sign-on (SSO)

> Connect your OIDC identity provider so your team signs in with your company login.

SSO lets your team sign in to Encrata with your existing identity provider over OIDC. You add a connection for your email domain, verify you own that domain, then optionally require everyone on it to log in through your IdP. This guide walks through the full setup.

<Info>
  SSO is managed per workspace and only a workspace `admin` can configure it. Connections use **OIDC** - point them at any provider that publishes a standard discovery document (Okta, Entra ID, Google, Auth0, and others).
</Info>

## Before you start

<Steps>
  <Step title="Be a workspace admin">
    Only an `admin` can manage SSO. See [Workspaces and teams](/guides/workspaces) for roles.
  </Step>

  <Step title="Register an OIDC app with your IdP">
    Create an OIDC application in your identity provider and note its **issuer URL**, **client ID**, and **client secret**.
  </Step>
</Steps>

## Set up a connection

<Steps>
  <Step title="Create the connection">
    Send your issuer, client credentials, and the email domain it covers. Only `issuer`, `client_id`, `client_secret`, and `email_domain` are required.

    ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
    curl -X POST https://developer.encrata.com/api/account/sso/connections \
      -H "Authorization: Bearer enc_your_key" \
      -H "Content-Type: application/json" \
      -d '{
        "issuer": "https://acme.okta.com",
        "client_id": "0oa1b2c3d4",
        "client_secret": "your-client-secret",
        "email_domain": "acme.com",
        "display_name": "Okta",
        "enforce_sso": true,
        "auto_provision": true
      }'
    ```

    A `201` returns the connection. Note `domain_verified` is `false` and a `verification_token` is included for the next step. The `client_secret` is never returned.

    ```json theme={"theme":{"light":"github-light","dark":"vesper"}}
    {
      "id": "c1d2e3f4-5a6b-4c7d-8e9f-0a1b2c3d4e5f",
      "workspace_id": "b3f1c2a4-5d6e-4f70-8a1b-9c2d3e4f5a6b",
      "provider": "custom",
      "display_name": "Okta",
      "issuer": "https://acme.okta.com",
      "client_id": "0oa1b2c3d4",
      "scopes": "openid email profile",
      "email_domain": "acme.com",
      "enforce_sso": true,
      "auto_provision": true,
      "default_role": "member",
      "active": true,
      "domain_verified": false,
      "verification_token": "9f8e7d6c5b4a39281706",
      "created_at": "2026-01-15T10:00:00Z",
      "updated_at": "2026-01-15T10:00:00Z",
      "last_used_at": null,
      "connection_count": 0
    }
    ```

    | Field | Type | Required | Description |
    | - | - | - | - |
    | `issuer` | string | Yes | OIDC issuer URL. Must be reachable over HTTPS and publish `/.well-known/openid-configuration`. |
    | `client_id` | string | Yes | OIDC client ID from your IdP. |
    | `client_secret` | string | Yes | OIDC client secret. Stored encrypted and never returned. |
    | `email_domain` | string | Yes | Email domain this connection covers, e.g. `acme.com`. |
    | `display_name` | string | No | Label shown on the login screen. Defaults to `SSO`. |
    | `provider` | string | No | Provider tag. Defaults to `custom`. |
    | `scopes` | string | No | OIDC scopes. Defaults to `openid email profile`. |
    | `enforce_sso` | boolean | No | Require users on this domain to sign in through SSO. Defaults to `false`. |
    | `auto_provision` | boolean | No | Create an account on first SSO login. Defaults to `true`. |
    | `default_role` | string | No | Role given to auto-provisioned users. Defaults to `member`. |
  </Step>

  <Step title="Verify domain ownership">
    A connection cannot log anyone in until you prove you own its domain. Add a DNS `TXT` record, then call verify.

    Create this record with your DNS provider:

    | Host | Value |
    | - | - |
    | `_encrata-sso.acme.com` | `encrata-sso-verify=<verification_token>` |

    Then confirm it:

    ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
    curl -X POST https://developer.encrata.com/api/account/sso/verify-domain \
      -H "Authorization: Bearer enc_your_key" \
      -H "Content-Type: application/json" \
      -d '{ "id": "c1d2e3f4-5a6b-4c7d-8e9f-0a1b2c3d4e5f" }'
    ```

    ```json theme={"theme":{"light":"github-light","dark":"vesper"}}
    { "domain_verified": true }
    ```

    <Note>
      DNS changes can take time to propagate. If the record is not visible yet, the response returns `domain_verified: false` with the exact `record_host` and `record_value` to set. Wait and retry.
    </Note>
  </Step>

  <Step title="Test the connection">
    Check that your issuer's discovery endpoint is reachable before you rely on it. Pass just the issuer.

    ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
    curl -X POST https://developer.encrata.com/api/account/sso/test \
      -H "Authorization: Bearer enc_your_key" \
      -H "Content-Type: application/json" \
      -d '{ "issuer": "https://acme.okta.com" }'
    ```

    ```json theme={"theme":{"light":"github-light","dark":"vesper"}}
    { "success": true }
    ```

    <Warning>
      This endpoint always returns `200`. Read the `success` field - a failure comes back as `{ "success": false, "error": "..." }`.
    </Warning>
  </Step>
</Steps>

## Manage connections

<AccordionGroup>
  <Accordion title="List connections" icon="list">
    Returns every SSO connection in your current workspace. Admin only.

    ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
    curl https://developer.encrata.com/api/account/sso/connections \
      -H "Authorization: Bearer enc_your_key"
    ```
  </Accordion>

  <Accordion title="Update a connection" icon="gear">
    Send the connection `id` and the fields to change. Leave `client_secret` empty to keep the stored one. Admin only.

    ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
    curl -X PUT https://developer.encrata.com/api/account/sso/connections \
      -H "Authorization: Bearer enc_your_key" \
      -H "Content-Type: application/json" \
      -d '{
        "id": "c1d2e3f4-5a6b-4c7d-8e9f-0a1b2c3d4e5f",
        "issuer": "https://acme.okta.com",
        "client_id": "0oa1b2c3d4",
        "email_domain": "acme.com",
        "enforce_sso": true,
        "active": true
      }'
    ```

    ```json theme={"theme":{"light":"github-light","dark":"vesper"}}
    { "status": "updated" }
    ```

    <Note>
      Changing `email_domain` resets `domain_verified` to `false`. You will need to verify the new domain again.
    </Note>
  </Accordion>

  <Accordion title="Delete a connection" icon="trash">
    Pass the connection id as the `id` query parameter. Admin only.

    ```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
    curl -X DELETE "https://developer.encrata.com/api/account/sso/connections?id=c1d2e3f4-5a6b-4c7d-8e9f-0a1b2c3d4e5f" \
      -H "Authorization: Bearer enc_your_key"
    ```

    ```json theme={"theme":{"light":"github-light","dark":"vesper"}}
    { "status": "deleted" }
    ```
  </Accordion>
</AccordionGroup>

## Next steps

<CardGroup cols={2}>
  <Card title="Workspaces and teams" icon="users" href="/guides/workspaces">
    Manage members and roles inside your workspace.
  </Card>

  <Card title="Authentication" icon="key" href="/authentication">
    How API keys and bearer auth work.
  </Card>
</CardGroup>
