Skip to main content
Available on the Corporate plan. This functionality is part of woku’s enterprise capabilities. Talk to our sales team.
woku supports enterprise SSO (SAML 2.0 + OpenID Connect) so that a company’s users can log in with the identity provider (IdP) they already use internally: Azure AD / Microsoft Entra, Okta, OneLogin, Google Workspace, ADFS, etc. The technical broker is Stytch B2B: Stytch hosts the SAML/OIDC connections and hands us a verifiable token when the IdP authentication finishes successfully.
Reference case. RE/MAX Chile uses SSO with woku, integrating its Active Directory from Microsoft Azure AD (Entra ID).

Model

  • One woku company ↔ one Stytch Organization. Every company that enables SSO is linked to an organization in Stytch.
  • One Stytch organization ↔ one or more SAML/OIDC connections. The connections are configured in the Stytch dashboard (IdP XML metadata, attribute mapping, certificates, etc.).
  • Domain allowlist. Every company that enables SSO declares which email domains may use SSO against that organization. This prevents cross-tenant impersonation attacks.
  • Identity scoped by organization + Stytch member. Once a woku user logs in via SSO, we link them to the tuple (stytchOrganizationId, stytchMemberId). Subsequent logins resolve by that tuple, not by email, which closes the impersonation window even if the email changes or is reused.
  • Per-company opt-in. By default SSO is off and users log in with email + password + (optional) MFA TOTP.

Enabling SSO in your company

Prerequisites:
  1. Have a Stytch organization created (the first time we create it for you).
  2. Have at least one SAML or OIDC connection configured in that organization against your IdP.
Then, from woku:
  1. Go to Company → Security → SSO.
  2. Check Enabled and enter what Stytch gives you:
    • Stytch Organization ID (format organization-prod-...).
    • Stytch Connection ID (format saml-connection-prod-... or oidc-connection-prod-...).
  3. Add at least one allowed email domain (for example acme.com). Only users whose email ends in one of those domains will be able to complete SSO against this company.
  4. Save.
The backend refuses to enable SSO without an Organization ID, Connection ID, and at least one allowed domain (400 BadRequest). This prevents leaving the company with SSO enabled but with no destination or control over who can log in.

Why the domain list

Without this list, a malicious (or misconfigured) IdP could assert an email from another company (someone@other-company.com) and gain access to the wrong tenant. With the list, the backend rejects with 403 any SSO assertion whose email domain is not among the company’s authorized ones.

What the login flow looks like (SP-initiated)

As seen by the user:
  1. The user opens the admin login page and types their email. They click Continue.
  2. The admin queries the discovery service to resolve which method to show:
    • If the email domain belongs to a company with SSO enabled, the Continue with SSO button appears.
    • Otherwise, the Password field appears.
  3. If it was SSO: the browser is redirected to Stytch, Stytch to the IdP, the IdP back to Stytch, and Stytch to our callback. After exchanging the token, it redirects to the admin with the woku tokens in the URL fragment and the session is started.
As seen by the backend:
  1. Discovery resolves whether the email domain belongs to a company with SSO active. The response indicates the mode (sso or password) and has a stable shape regardless of whether the user exists in woku, so as not to leak enumeration data.
  2. When the user clicks Continue with SSO, the backend validates that the company has SSO enabled and responds with a 302 redirect to Stytch’s public URL.
  3. Stytch redirects to the IdP where the user authenticates.
  4. The IdP redirects back to Stytch, which validates the assertion and redirects to the woku callback.
  5. woku exchanges the token (stytch.sso.authenticate), resolves the company by organization_id, verifies that the asserted email domain is in ssoEmailDomains, looks up the user first by (stytchOrganizationId, stytchMemberId) and, if it is the first time, does JIT provisioning + records the identity. Finally it ensures the UserCompany membership, issues a pair of woku tokens (access + refresh) and redirects to the admin with the tokens in the URL fragment.
  6. The admin’s callback page reads the fragment, persists the token in the authentication store, opens the real time channel and clears the fragment from history before redirecting the user to the dashboard.
V1 supports only the SP-initiated flow (the user starts in woku). IdP-initiated arrives in a later iteration.

Just-In-Time provisioning

When a user logs in via SSO for the first time:
  1. Resolution by scoped identity. First we look for a woku user that already has the identity (stytchOrganizationId, stytchMemberId) recorded. If it exists, we use it.
  2. Email fallback. If there was no recorded identity, we look up by normalized email. If the user exists we link them to the new identity for subsequent logins.
  3. JIT. If the email does not exist either, we create it automatically with a username derived from the email and a random password (that the user never uses). We mark the account as confirmed.
  4. Membership. In all cases we ensure the user has UserCompany membership in the corresponding company. The default role is member. If you need SSO users to log in with the admin role, contact support (the role mapping UI is on the backlog).
Every SSO login is recorded in the audit log as auth.sso.login with actorEmail, companyId, stytchOrganizationId, stytchMemberId, newlyLinked (true when the identity was just recorded) and IP.

Guarantees

  • The Stytch secret never touches the client. Only the STYTCH_PUBLIC_TOKEN (public by design) is included in the start URL; the STYTCH_SECRET lives only in the backend.
  • Server-side validation. The woku session is issued only after Stytch confirms the authentication. The Stytch token is single-use.
  • Per-company isolation. The callback rejects with 403 if the Stytch organization is not linked to any woku company.
  • Cross-tenant anti-impersonation. The callback rejects with 403 if the email domain asserted by the IdP is not in ssoEmailDomains, and the woku identity is resolved by the tuple (stytchOrganizationId, stytchMemberId) before by email.
  • No enumeration. The discovery response does not depend on whether the user exists in woku; only on the email domain. It is rate-limited to discourage sweeps.
  • Auditable. Every step is recorded.

Known limitations (V1)

  • The detailed SAML/OIDC configuration (XML metadata, attribute mapping, certificates) is done in the Stytch dashboard, not in the woku panel. Only the IDs and the domains live in woku.
  • SP-initiated only. IdP-initiated requires an additional endpoint; it arrives in the next iteration.
  • No automatic role mapping: all SSO users log in as member by default. Upgrades to admin/owner are done manually from Company → Members.
  • The SSO add-on is opt-in and monetizable: the commercial model (add-on price) is documented separately. In the meantime the flag ssoEnabled is turned on manually.

Loss of access

If the IdP’s SAML/OIDC connection breaks, if the user’s email domain changes, or if you need to add/remove an allowed domain without access to the panel, contact support (team@woku.app) to temporarily disable SSO or reassign the membership manually.