Obexal Docs

Docs/Federation/SAML SP (inbound SSO)

Enterprise SSO into Obexal (Obexal as SP)

Let your users sign in to Obexal through your corporate SAML IdP (Entra ID, ADFS, Okta, Keycloak), with hardened assertion validation, automatic account linking and JIT provisioning.

If your company already runs an identity provider (Microsoft Entra ID, ADFS, Okta, Keycloak, or any SAML 2.0 IdP), your users can sign in to Obexal with it. Obexal acts as the SAML Service Provider: it sends the user to your IdP, validates the returned assertion, then opens an ordinary Obexal session. One SAML connection exists per organization. For the opposite direction (Obexal issuing assertions to your apps), see Obexal as IdP.

What Obexal exposes to your IdP

{tenant} is your organization slug. The examples use accounts.obexal.com; your custom sign-in domain replaces it if you have one.

EndpointRole
GET /saml/{tenant}/metadataSP metadata (XML). The entityID of the SP is this URL
GET /saml/{tenant}/login?redirect_uri=Starts SP-initiated SSO (redirects to your IdP)
POST /saml/{tenant}/acsAssertion Consumer Service (called by your IdP)

In your corporate IdP, create the application with this entityID and this ACS URL (most products import the metadata URL directly).

Configure the connection

Configuration requires the tenant:manage permission (console session or an obx_ admin API token). You paste the metadata XML of your IdP and enable the connection; the XML is parsed and rejected with a 400 if invalid:

curl -sS -X PUT https://accounts.obexal.com/v1/admin/saml \
  -H "Authorization: Bearer $OBEXAL_API_TOKEN" -H 'Content-Type: application/json' \
  -d "{\"metadataXml\": $(jq -Rs . < idp-metadata.xml), \"enabled\": true}"
# 200 -> {"status":"ok"}

GET /v1/admin/saml returns the current state (configured, enabled, metadataXml). In the admin console, the same setting lives in the inbound SAML SSO panel: download the federation metadata XML from your IdP (in Entra ID: the enterprise application's "Federation Metadata XML"; in Keycloak: the realm SAML descriptor) and paste it there.

The sign-in flow

  1. The browser opens /saml/{tenant}/login?redirect_uri=.... The redirect_uri (where the user lands after sign-in) is validated against the allowed origins.
  2. Obexal builds an AuthnRequest (HTTP-Redirect binding, not signed) and redirects to your IdP's SSO URL. The flow state is stored server side, hashed, single use, with a 10 minute TTL, and tied to the RelayState.
  3. The user authenticates at your IdP, which POSTs the signed response to the ACS.
  4. Obexal validates the assertion, resolves the account, then either sets the session cookie and redirects to redirect_uri, or redirects to the MFA screen. On failure the user is redirected with error=social_failed (invalid assertion) or error=social_state (expired or replayed flow state); no session is ever set on failure.

Hardened assertion validation

No session exists until the assertion passes every check:

  • Signature: verified against the certificate published in your IdP's metadata. Assertions must be signed.
  • Conditions: audience restriction, NotBefore and NotOnOrAfter windows.
  • Anti-replay: the InResponseTo of the response must match the ID of the AuthnRequest that Obexal actually emitted for this browser; that ID is kept server side and consumed once. Unsolicited (IdP-initiated) responses are therefore not accepted.

Identity extraction is deliberately minimal: the NameID becomes the stable federated subject, and the email is read from the first attribute whose name contains email or mail (including the standard claims/emailaddress URI). If no email attribute exists but the NameID itself is an email address, it is used. Emails are lowercased.

Account resolution and JIT provisioning

The federated identity is scoped to your organization: the same NameID at two tenants stays two distinct identities. Resolution, in order:

  1. The identity is already linked to a user: direct sign-in.
  2. First time for this identity, and a local account with the asserted email exists: the identity is linked automatically and the email is marked verified (your corporate IdP vouches for it).
  3. No account exists: a user is provisioned just in time, with the email already verified.

A first-time sign-in requires an email in the assertion; without one the flow fails. Every path writes to the audit log.

MFA applies after federation

SAML is a primary factor, exactly like a password: if the resolved account has an active MFA factor, no session is opened at the ACS. The browser is redirected to the MFA screen with a one-time challenge token; see the MFA checkpoint. Conditional access rules also apply.

Honest limits

  • One SAML connection per organization; you cannot federate several corporate IdPs into one tenant.
  • Assertions must be signed and not encrypted; encrypted assertions are not supported.
  • Your IdP must expose an HTTP-Redirect SSO binding; the AuthnRequest itself is not signed.
  • IdP-initiated sign-in into Obexal is not accepted (a consequence of strict InResponseTo validation).
  • Only the subject and the email are consumed from the assertion; other attributes (name, groups) are not mapped. Use SCIM provisioning to synchronize profiles.
  • No SAML Single Logout.