Skip to main content
By default a SAML connection is one of several ways a user can sign in — they could still use OTP or a social provider with the same email. Enabling enforce login makes SAML the only way in for the domains the connection covers.

How it works

Enforcement is keyed off the connection’s email_domain_allowlist. When enforce_login is true, any login attempt whose email domain resolves to that connection is redirected into SAML, and the other methods step aside:
  • OTP create — submitting an email identifier whose domain is enforced is refused with the saml_login_required error (HTTP 403). The SDK is expected to restart the flow via the SAML initiate endpoint.
  • OAuth callback — when the IdP-supplied email’s domain is enforced, the OAuth flow is abandoned (no account is created or linked) and the user is redirected into a fresh SAML AuthnRequest. The PKCE challenge and dispatch from the OAuth state are carried over.
Enforcement is a gate layered on top of the existing flows, never a new way for them to fail. A domain that can’t be resolved to exactly one enforcing connection — because it isn’t allowlisted, or it’s ambiguous — is simply not enforced, and the normal login methods proceed.
enforce_login is inert without a non-empty email_domain_allowlist. The allowlist is the only domain→connection binding; with no domains, there is nothing to enforce.

Enable enforcement

Set enforce_login to true on the connection’s behavior block. You can do this at creation or with a PUT:
curl -X PUT https://api.prelude.dev/v2/session/apps/${APP_ID}/config/login/saml/okta/${CONNECTION_ID} \
  -H "Authorization: Bearer ${MANAGEMENT_API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{
    "behavior": {
      "jit_provisioning": true,
      "allow_email_account_merge": true,
      "email_domain_allowlist": ["acme.com"],
      "enforce_login": true,
      "default_redirect_uri": "https://app.acme.com/callback"
    }
  }'
After this, a user with an @acme.com email can no longer obtain a session via OTP or OAuth — only through this Okta connection.

The saml_login_required error

When a client tries to start an OTP login for an enforced email, POST /v1/session/otp returns 403 with:
{
  "code": "saml_login_required",
  "type": "forbidden",
  "message": "This email domain must sign in with SSO. Please use SAML to continue."
}
This is the signal for your app to restart authentication through SAML. The Web SDK surfaces it as a typed SAMLLoginRequiredError so you can transparently fall back to loginWithSAMLByEmail — see Enforce SSO login (Web SDK).

Notes and edge cases

  • Ambiguous or unmatched domains are not enforced. Connection creation rejects overlapping allowlists, so a domain resolves to at most one connection; an unresolvable domain falls through to the normal login flows.
  • IdP-initiated logins are unaffected. Enforcement only intercepts the OTP and OAuth entry points — a user clicking the IdP tile always lands on the ACS endpoint.
  • Existing sessions are not revoked. Enforcement governs new logins; it does not invalidate sessions a user already holds.

What’s next?

Enforce login (Web SDK)

Handle saml_login_required and fall back to SAML in the browser.

SAML login (Web SDK)

Start a standard SAML login from the JavaScript SDK.