Skip to main content
Back to blog

How SAML SSO Secures Tenant-Isolated Dashboard Access at Orbit

A deep dive into the SAML 2.0 flow Devotel Orbit runs per organization — signed assertions, audience and replay checks, IdP-group role mapping, and the org-binding gate that keeps one tenant's sign-in from touching another.

Orbit Editorial Team

Dashboard access on a CPaaS is not one login into one app — it is one login per organization, over traffic that bills to that organization alone. A sign-in flow that works for organization A but can mint a session for organization B is a cross-tenant breach with a billing consequence. Devotel Orbit runs SAML 2.0 per organization for exactly this reason, and the flow carries five distinct gates between your identity provider and a session. This deep dive walks those gates in the order an assertion meets them.

Gate 1: per-organization endpoints, keyed by org slug

Each organization gets its own SAML endpoints under its organization slug, set up under Settings → Single sign-on: a metadata document your IdP imports, a login endpoint that redirects to your IdP, a callback (ACS) endpoint your IdP posts the signed response to, and a logout endpoint. The metadata is the public half of the contract — it publishes that organization's ACS URL in HTTP-POST binding, its logout URL, and the email NameIDFormat — so your IdP admin can import it directly. Because one metadata document exists per organization, an IdP misconfiguration in one tenant never aliases into another: the acme org's callback URL is a different endpoint from the globex org's, and each expects assertions carrying that org's own entity ID.

Gate 2: signature verification against the org's own certificate

The callback accepts a response only when the signature on it verifies against the certificate the organization's admin uploaded — WantAssertionsSigned="true" is baked into the metadata the IdP imports. A response with no signature, or a signature computed against any other key, is rejected before anything in it is read. Gate passes and failures are recorded in the audit log with neutral reason codes, so a certificate mismatch shows up as a configuration problem for your admin rather than as a hint for an attacker.

Gate 3: conditions — validity window and audience restriction

A signature proves the IdP signed something; the <Conditions> block proves this assertion is for this service provider, right now. Orbit requires NotBefore and NotOnOrAfter timestamps (with a small clock-skew tolerance) and an <AudienceRestriction> entry that exactly matches the organization's entity ID. Without the audience check, an assertion your IdP minted for some other application — a Salesforce tenant, an internal tool — could be replayed at Orbit's callback and would otherwise pass gate 2. With the check, replay across applications fails closed.

Gate 4: replay protection

Even an assertion that passes signature and conditions is refused if its identifier has already been presented on that organization. A fresh assertion ID is required per response within the assertion's validity window, so a captured POST body replayed later — or replayed onto a different organization's callback — resolves to a denial, not a session.

Gate 5: org binding — the tenant-isolation gate

This is the gate that separates a working SSO setup from a cross-tenant one. A signed assertion proves the IdP vouches for an email — but your IdP can assert any email it chooses, including the personal email of an owner on a different Orbit organization. Orbit therefore checks, after signature and conditions pass, whether a user row already exists for that email and which organization it belongs to:

  • Bound to this organization — proceed.
  • Bound to a different organization — reject with SAML_USER_NOT_IN_ORG. No hint is returned about where the user actually lives; the audit log records just the org-binding failure for the legitimate admin to find.
  • No user row at all — first-time sign-in proceeds only when the email holds a pending invitation on this organization, or the org admin has enabled org-wide enforcement. Without one of those guardrails, the invite-less assertion is rejected. JIT (just-in-time) provisioning is bounded by the invite list, not by IdP assertion alone.

That rule is the difference between per-organization SSO and a shared-login page with an org switcher: an IdP admin for organization A cannot mint an Orbit session for organization B's owner, even though both orgs route through the same SAML implementation.

Role-map provisioning: IdP groups to Orbit roles

When the organization also provisions through SCIM, the SAML callback reads the assertion's group attributes — memberOf, groups, roles, whichever the IdP emits first — and applies the group's role mapping you configured on the SCIM side. A user whose IdP groups claim both support-viewers (mapped to viewer) and eng-admins (mapped to admin) resolves to admin; a user with no mapped group claim lands on the configured default role. The priority order across the five Orbit roles (owner, admin, developer, billing, viewer) decides on collisions, and it matches the SCIM precedence exactly. SAML-only tenants — where no SCIM mapping exists — simply keep the role the user already holds, so a plain SSO rollout never demotes existing members on the first sign-in.

The redirect back and the audit trail

The final hop is a redirect to the dashboard, and RelayState is honored only when it resolves to a same-origin URL — a startsWith check would accept https://app.attacker.example/x as a prefix match, so the comparison is origin-for-origin, and anything cross-origin falls back to the dashboard root. Every gate above, pass or fail, writes an audit event on the organization. An access review is a filter on those events, not a forensic dig through IdP logs.

If you already run an IdP, the walkthrough is on the authentication docs page: import the metadata, upload your IdP certificate, test the connection, and enable. The role-mapping half is configured on the SCIM provisioning guide.

Frequently asked questions

Why does the audience check matter if the signature already verifies?

A signature proves your IdP minted the assertion, not that it was minted for Orbit. IdPs mint assertions for every connected application, and a signed assertion for another app — your CRM, an internal tool — would pass signature verification. The <AudienceRestriction> requirement binds the response to Orbit's entity ID, so a cross-app replay is rejected.

Can someone map an IdP group to the owner role?

Only if the organization's admin explicitly mapped that group on the SCIM side. SAML reads the SCIM role mapping as-is and applies it; it does not invent a mapping. Keep owner unmapped in the SCIM configuration if IdP-group-controlled ownership is not acceptable for your org.

What happens when a user is in two mapped groups?

The higher-priority role in the fixed precedence order wins — owner beats admin beats developer beats billing beats viewer. The precedence is the same one SCIM applies on directory-side updates, so the two flows agree on collision resolution instead of guessing differently.

If no SCIM mapping exists, does SAML still apply a default role?

No. SAML-only organizations keep each user's existing role. The mapped role applies only when a SCIM configuration gives one — otherwise the sign-in leaves the role unsettled rather than demoting members on first login.

How SAML SSO Secures Tenant-Isolated Dashboard Access at Orbit — Orbit by Devotel