Skip to main content
Zyra Zyra
Features Pricing Security FAQ Documentation
Sign In Sign up for free

Documentation › User Guides › Organizations › Stage 4 › SSO and SAML

SSO and SAML

Chapter 3 · about 20 minutes to read

Password logins work for small teams. The moment you cross a few dozen users — or an auditor asks "how do you offboard?" — you want SSO. Zyra supports SAML 2.0 and OIDC out of the box, plus SCIM 2.0 for auto-provisioning.

Time: about 20 minutes (plus IdP-side configuration). Prerequisites: Org Admin in Zyra. Admin access to your IdP (Okta, Entra ID, Google Workspace, OneLogin, etc.).

What's implemented today

Confirmed in backend/app/routers/auth/sso_saml.py, sso_oidc.py, and scim_users.py:

  • SAML 2.0 — IdP-initiated and SP-initiated login, SP metadata endpoint, attribute mapping, auto-provisioning, email-domain matching.
  • OIDC — discovery document, PKCE flow, nonce verification, code exchange, ID-token validation.
  • SCIM 2.0 — full user CRUD (GET / POST / PUT / PATCH / DELETE /scim/v2/Users) using Bearer tokens.

[VERIFY: confirm Okta + Entra ID as production-tested; Google Workspace and OneLogin as community-reported]

Step 1 — Pick your protocol

Use SAML when your IdP is Okta or Entra ID and your security team prefers SAML, or when compliance mandates SAML assertions. Use OIDC when you already use Google Workspace or any OAuth2/OIDC IdP, or when you want simpler XML-free config. Both flows land in the same place: a Zyra JWT for the browser. IdP tokens stay server-side.

Step 2 (SAML) — Exchange metadata

Download Zyra's SP metadata from GET /api/v1/sso/saml/metadata, upload to your IdP, then copy back the IdP entity ID, SSO URL, and X.509 signing certificate.

curl -X POST https://app.getzyra.io/api/v1/sso/saml/config \
  -H "Authorization: Bearer $ZYRA_API_KEY" \
  -d '{
    "idp_entity_id": "https://idp.example.com/saml",
    "idp_sso_url": "https://idp.example.com/sso",
    "idp_certificate": "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----",
    "attribute_mapping": {"email":"...","role":"..."},
    "default_role": "org_member",
    "auto_provision_users": true,
    "email_domains": ["acme.com"]
  }'

email_domains wires the auto-detect on the Zyra login page (POST /api/v1/sso/check-email).

Step 2 (OIDC) — Point to the discovery URL

OIDC is configured via POST /api/v1/sso/config with protocol=oidc and the IdP's issuer URL. Zyra fetches /.well-known/openid-configuration, performs the PKCE flow, and verifies the ID token's signature, audience, issuer, and nonce. [VERIFY: full OIDC config-create payload — see backend/app/routers/auth/sso_config.py for the canonical schema]

Step 3 — Map attributes to Zyra roles

The attribute_mapping.role claim from your IdP normalises to one of super_admin, org_admin, or org_member. Unknown values fall through to default_role. See Stage 3, Chapter 5 for the full permission matrix.

Step 4 — Fallback to password auth

Password login stays enabled for Org Admins even after SSO is active. This is the "break-glass" path if your IdP is down. Members on SSO-restricted domains are forced through the IdP — they cannot fall back unless an admin temporarily disables SSO.

Step 5 (Optional) — SCIM provisioning

SCIM auto-syncs users from your IdP into Zyra: hire someone, they land in Zyra; remove them, they're deactivated.

  1. Generate a SCIM token. POST /api/v1/scim/tokens (Org Admin). Copy the token once.
  2. Configure your IdP's SCIM connector. Base URL https://app.getzyra.io/api/v1/scim/v2. Bearer token from step 1. Content-Type application/scim+json.
  3. Push users. Your IdP starts calling POST /scim/v2/Users for new hires and DELETE /scim/v2/Users/{id} (soft-delete) for offboards.

Rate limits: 100/min for reads, 50/min for writes.

What just happened

You picked SAML or OIDC, exchanged metadata, mapped attributes to roles, and optionally turned on SCIM. New hires sign in with their corporate account; leavers are deactivated automatically.

Troubleshooting

  • SAML callback returns 400 Invalid SAMLResponse. Your IdP cert doesn't match the one you uploaded. Re-download and update via PUT /sso/saml/config.
  • OIDC fails with IdP did not return id_token. Your IdP's response_type is misconfigured.
  • SCIM returns 401. The Bearer token doesn't match any active row, or it's been revoked. Generate a new one.

← Previous: Receive webhooks from Zyra

Next: Read and export the audit log →

Last reviewed: 2026-05-21

© 2026 Zyra. All rights reserved. | Privacy Policy | Terms of Service | Careers