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

# SAML SSO in EK — How It Works

> Understand how EK integrates with your Identity Provider for SAML 2.0 SSO before you begin configuration.

<Note>
  This guide is written for IT and identity administrators managing an on-premise EK instance. Any reference to "your IdP," "your IdP administrator," or "your email domain" refers to your organization's own infrastructure — not anything managed by Odin AI.
</Note>

EK supports **SAML 2.0 SSO** for on-premise deployments, allowing your users to sign in through your organization's existing **Identity Provider (IdP)**. The setup happens entirely through the **Super Admin Dashboard → SSO Metadata** tab — no code changes required.

EK works with any **standards-compliant SAML 2.0 IdP** — Okta, Azure AD / Entra ID, Ping, ADFS, OneLogin, Auth0, Keycloak, Google Workspace, and others. Once you upload IdP metadata for an email domain, EK will automatically route SSO for any user whose email belongs to that domain.

## Understanding Your Two EK Hostnames

An on-premise EK deployment has two hostnames with distinct roles:

* `<your-backend-host>` — handles all SAML traffic: SP metadata, SSO initiation, and the ACS endpoint. **This is the only host your IdP needs to know about.** *(Example: `ek-api.corp.acme.com`)*
* `<your-frontend-host>` — the web UI your users open in their browser. EK redirects users here after a successful sign-in, configured via the `FRONTEND_ROOT_URL` environment variable. **This host never appears in your IdP configuration.** *(Example: `ek.corp.acme.com`)*

## How SAML SSO Works in EK

Setting up SAML SSO requires a mutual exchange of trust between two systems. Each side needs to know who the other is before any authentication can happen:

<CardGroup cols={2}>
  <Card title="Service Provider (SP) — EK" icon="server">
    Your on-premise EK instance. EK publishes SP metadata so your IdP knows where to send SAML responses, which NameID format to use, and which signing certificate to trust on AuthnRequests.
  </Card>

  <Card title="Identity Provider (IdP) — Your Org" icon="shield-halved">
    Your organization's Okta, Entra ID, Ping, ADFS, etc. Your IdP publishes its own metadata XML describing its issuer, SSO endpoint, and signing certificate — EK needs this to validate the assertions your IdP returns.
  </Card>
</CardGroup>

To enable SSO for an email domain (for example `acme.com`), a Super Admin needs to complete both sides of this exchange:

<Steps>
  <Step title="Share SP Metadata with Your IdP">
    Give your IdP administrator the SP metadata published by your EK instance so they can register EK as a SAML application in your IdP.
  </Step>

  <Step title="Upload IdP Metadata to EK">
    Once the IdP application is created, upload the resulting IdP metadata XML to EK through **Super Admin → SSO Metadata**, keyed to the email domain users will sign in with.
  </Step>
</Steps>

Once both sides are in place, any user with an email ending in `@<domain>` can sign in to EK via SAML SSO through your corporate IdP.

## How the User Reaches the SSO Flow

The EK sign-in screen always shows a "Sign in with SSO" option. What happens when a user clicks it depends on two frontend environment variables baked into your EK web UI build:

| Variable                    | Purpose                                                                             |
| --------------------------- | ----------------------------------------------------------------------------------- |
| `VITE_ALLOW_ONLY_SSO_LOGIN` | Determines which SSO mode the login screen uses.                                    |
| `VITE_SSO_ENTERPRISE_ID`    | Used only in single-click mode to specify the email domain to authenticate against. |

<AccordionGroup>
  <Accordion title="Mode A — Single-click SSO (VITE_ALLOW_ONLY_SSO_LOGIN=true)">
    The login screen shows only an SSO button — no email or password fields. This is the typical setup for an on-premise deployment serving a single email domain.

    When the user clicks the button, the frontend reads `VITE_SSO_ENTERPRISE_ID` and immediately redirects to:

    ```
    https://<your-backend-host>/sso/login?enterprise_id=<VITE_SSO_ENTERPRISE_ID>&target_url=https://<your-frontend-host>/okta/authenticate
    ```

    For this to work:

    * `VITE_SSO_ENTERPRISE_ID` must be set on the frontend.
    * Its value must match a domain that has IdP metadata uploaded in the **SSO Metadata** tab.
    * When uploading metadata, the **SSO Team Email Domain** must match `VITE_SSO_ENTERPRISE_ID` exactly (case-insensitive; values are normalized to lowercase on save).

    If `VITE_SSO_ENTERPRISE_ID` is unset, the user sees *"Could not determine domain for SSO login"* and cannot proceed. If it's set but no metadata exists for that domain, the redirect goes through but SSO fails at the backend.
  </Accordion>

  <Accordion title="Mode B — Email-modal SSO (VITE_ALLOW_ONLY_SSO_LOGIN=false, default)">
    The login screen shows email/password and SSO controls together. Clicking the SSO button opens an *"Enter your email"* modal. After the user submits their email, the frontend extracts the domain and checks with the backend whether SSO is configured for it via `POST https://<your-backend-host>/sso/verify_enterprise_id`.

    * If **yes**, the frontend redirects to:
      ```
      https://<your-backend-host>/sso/login?enterprise_id=<email-domain>&target_url=https://<your-frontend-host>/okta/authenticate
      ```
    * If **no**, the user sees *"Your organization is not configured for SSO login. Please contact your administrator."*

    `VITE_SSO_ENTERPRISE_ID` is not used in this mode. Multiple domains can coexist — each one needs its own IdP metadata uploaded in the SSO Metadata tab.
  </Accordion>
</AccordionGroup>

<Info>
  Both modes use the same backend `/sso/login` endpoint with the same `enterprise_id` parameter. The only difference is whether that value is hard-coded by a frontend environment variable (Mode A) or derived from the user's email at sign-in (Mode B).
</Info>

## What the Backend Does with `enterprise_id`

When the backend receives `GET /sso/login?enterprise_id=acme.com`, it looks up the IdP metadata uploaded for `acme.com` and builds a SAML SP configuration on the fly:

| Parameter               | Value                                                                                                                                             |
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Entity ID**           | `CUSTOM_ENTITY_ID_FOR_GENERIC_SSO` if set at deployment time; otherwise defaults to `https://<your-backend-host>/user/generic/sso/saml/acs/admin` |
| **ACS endpoint**        | `https://<your-backend-host>/user/generic/sso/saml/acs/admin` (HTTP-POST binding)                                                                 |
| **NameID format**       | `emailAddress`                                                                                                                                    |
| **Remote IdP metadata** | A signed URL pointing to the uploaded XML in storage                                                                                              |

If no metadata is on file for the supplied `enterprise_id`, the backend cannot build a SAML SP configuration and the SSO attempt fails.

## Browser-Level Redirect Chain

Once `enterprise_id` resolves to uploaded metadata, authentication proceeds as a sequence of browser redirects:

<Steps>
  <Step title="User starts on the frontend">
    The user opens EK at `https://<your-frontend-host>` and clicks the SSO button.
  </Step>

  <Step title="Frontend → Backend">
    The frontend redirects the browser to the backend SSO entry point:

    ```
    GET https://<your-backend-host>/sso/login?enterprise_id=acme.com&target_url=https://<your-frontend-host>/okta/authenticate
    ```
  </Step>

  <Step title="Backend → IdP">
    The backend builds a SAML AuthnRequest from the uploaded IdP metadata for `acme.com` and redirects the browser to your IdP's SSO endpoint.
  </Step>

  <Step title="IdP authenticates the user">
    Your IdP handles authentication — password, MFA, certificate, or whatever your organization has configured.
  </Step>

  <Step title="IdP → Backend">
    The IdP POSTs the SAML response to the EK backend ACS endpoint:

    ```
    POST https://<your-backend-host>/user/generic/sso/saml/acs/admin
    ```

    The backend validates the assertion against the IdP's signing certificate from the uploaded metadata, then signs the user into their existing EK account or provisions a new one.
  </Step>

  <Step title="Backend → Frontend">
    The backend redirects the user's browser back to EK at `<your-frontend-host>`. The exact URL is determined by the `FRONTEND_ROOT_URL` environment variable on the backend — if this is misconfigured, the user will appear to complete SSO successfully but land on the wrong page.
  </Step>
</Steps>

<Note>
  The IdP only ever interacts with `<your-backend-host>`. The frontend host appears at the very start of the flow (where the user begins) and the very end (where they land after sign-in) — it never appears in any IdP-facing URL.
</Note>

Ready to configure SSO? See the [SSO Metadata Setup Guide](/super-admin/sso/saml-sso-metadata-setup-guide) for step-by-step instructions.
