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

# Introduction

> Configure SAML 2.0 single sign-on (SSO) for your Auth application.

SAML SSO lets your users authenticate through their organization's Identity Provider (IdP), such as Okta, Google Workspace, or JumpCloud. Prelude Auth acts as the SAML Service Provider (SP): it consumes signed assertions from the IdP, provisions or links the matching user, and issues a session.

## Prerequisites

Before you start, make sure you have:

* A Prelude account with access to Prelude Auth
* An **Application ID** (`appID`) — see [Applications](/session/documentation/applications)
* Your **Management API key** for backend calls
* A verified [custom domain](/session/documentation/domain-names) — SAML Service Provider URLs are anchored to your domain
* Admin access to the Identity Provider you want to connect

## Supported providers

| Provider         | Identifier  |
| ---------------- | ----------- |
| Okta             | `okta`      |
| Google Workspace | `google`    |
| JumpCloud        | `jumpcloud` |

## How the flow works

Prelude Auth supports both flows defined by SAML 2.0:

* **SP-initiated** — your app calls a SAML initiate endpoint, the SDK redirects the user to the IdP, and the IdP posts a signed `SAMLResponse` back to the connection's Assertion Consumer Service (ACS) URL. The flow is bound with [PKCE](https://datatracker.ietf.org/doc/html/rfc7636) so the resulting `challenge_token` can only be finalized by the browser that started the flow.
* **IdP-initiated** — the user clicks the application tile in the IdP dashboard and the IdP posts directly to the ACS URL. No `RelayState` is involved.

Both flows converge on the ACS endpoint and redirect back to your app with a `challenge_token` you finalize the same way as [social login](/session/documentation/frontend-sdks/web/social-login).

## Service Provider endpoints

When you create a connection, Prelude Auth derives a unique set of SP endpoints from your domain, the provider identifier, and the generated connection ID:

| Endpoint                     | Pattern                                                                     |
| ---------------------------- | --------------------------------------------------------------------------- |
| Entity ID (Audience URI)     | `https://${YOUR_DOMAIN}/v1/session/login/saml/${PROVIDER}/${CONNECTION_ID}` |
| ACS URL (Single sign-on URL) | `…/${CONNECTION_ID}/acs`                                                    |
| Metadata URL                 | `…/${CONNECTION_ID}/metadata`                                               |

These values are returned in the `sp` block of the connection response and are **immutable** — they are what you register on the IdP side.

<Note>
  Because the SP endpoints embed the connection ID, you create the connection in
  Prelude **first**, then copy the generated `sp` values into your IdP
  application. The provider guides below walk through the exact ordering.
</Note>

## Connection behavior

Every connection carries a `behavior` block that controls provisioning and login enforcement:

| Field                       | Type      | Description                                                                                                                                                                                                                                                                        |
| --------------------------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `jit_provisioning`          | boolean   | When `true`, just-in-time provisions a new user on first SSO login.                                                                                                                                                                                                                |
| `allow_email_account_merge` | boolean   | When `true`, links the SAML identifier to an existing user that owns the same verified email.                                                                                                                                                                                      |
| `email_domain_allowlist`    | string\[] | Email domains this connection covers. This is the only domain→connection binding, and is required for email-resolved login and for `enforce_login`.                                                                                                                                |
| `enforce_login`             | boolean   | When `true`, emails in the allowlist must sign in through SAML — OTP and OAuth are refused for them. See [Enforce SSO login](/session/documentation/integration-guide/saml/enforce).                                                                                               |
| `default_redirect_uri`      | string    | Redirect URI used for IdP-initiated logins and when an SP-initiated flow omits `redirect_uri`.                                                                                                                                                                                     |
| `sync_profile_on_login`     | boolean   | When `true`, refreshes `given_name`, `family_name`, and the assertion's groups (stored under `samlgroups`) from the IdP on every SSO login instead of only at first provisioning. The IdP becomes the source of truth for these fields and may overwrite values changed elsewhere. |

## Attribute mapping

The `mapping` block maps assertion attributes to user profile fields (`email`, `first_name`, `last_name`, `groups`, plus arbitrary `custom` claims). Sensible per-provider defaults are applied when you omit it — Google Workspace, for example, defaults to the snake\_case attribute names it recommends.

The mapped `groups` attribute is persisted to the user's profile under `samlgroups` only when [`sync_profile_on_login`](#connection-behavior) is enabled.

## Provider guides

<CardGroup cols={2}>
  <Card title="Okta" icon="lock" href="/session/documentation/integration-guide/saml/okta">
    Configure an Okta SAML application.
  </Card>

  <Card title="Google Workspace" icon="google" href="/session/documentation/integration-guide/saml/google">
    Configure a Google Workspace custom SAML app.
  </Card>

  <Card title="JumpCloud" icon="key" href="/session/documentation/integration-guide/saml/jumpcloud">
    Configure a JumpCloud custom SAML application.
  </Card>
</CardGroup>

## What's next?

<CardGroup cols={2}>
  <Card title="Enforce SSO login" icon="shield-halved" href="/session/documentation/integration-guide/saml/enforce">
    Require allowlisted email domains to authenticate through SAML.
  </Card>

  <Card title="Web integration" icon="js" href="/session/documentation/frontend-sdks/web/saml">
    Start a SAML login from the JavaScript SDK.
  </Card>
</CardGroup>
