Skip to main content

Feature deep-dive · SaaSForge Core

SAML SSO in Next.js (Supabase + enterprise IdPs)

SAML SSO in Next.js (Supabase + enterprise IdPs)

SAML is the protocol that closes enterprise deals and the protocol that makes engineers groan. Most teams who try to implement it from scratch get stuck on XML signing, metadata exchange, and the surprisingly large surface of edge cases between IdP-initiated and SP-initiated flows. The pragmatic path in 2026 is to use a managed SAML layer (BoxyHQ Jackson, WorkOS, Stytch, or Supabase Auth's SSO product) and focus on the workspace-side wiring.

What today's SaaSForge Core ships, and what it does not

SaaSForge Core ships SAML-ready hooks: invocation points in the auth flow, an attribute-mapping configuration shape, and workspace-member provisioning logic that knows how to read a SAML assertion's email and group claims and turn them into the right `workspace_members` row. The UI exposes SSO configuration on the workspace settings page so an Admin can paste in their IdP metadata.

What SaaSForge Core does not ship today is the full IdP plumbing, parsing SAML XML, validating signatures, handling AuthnRequest generation, and the ACS endpoint that consumes the assertion. That layer is what the planned SaaSForge SAML SSO Kit module addresses. The honest read for buyers today: Core gives you the workspace-side scaffolding so adding a managed SAML provider (BoxyHQ Jackson, WorkOS, or Supabase Auth SSO) is straightforward; the dedicated module makes it turnkey.

The SAML 2.0 flow in plain terms

In SP-initiated SSO, the user clicks 'Sign in with SSO' on your app, your app generates an AuthnRequest (an XML blob saying 'authenticate this user'), and redirects the browser to the customer's IdP. The IdP authenticates the user (their own login page, possibly with MFA), then posts a signed SAML assertion to your ACS endpoint (`/api/auth/saml/callback`). Your app validates the signature, reads the assertion's attributes (email, name, groups), and creates or updates a session.

In IdP-initiated SSO, the user starts at their IdP's app launcher (Okta dashboard, Azure portal) and clicks your app's tile. The IdP posts an unsolicited assertion to your ACS endpoint. This flow is convenient for users but harder to secure, your ACS has to be careful about replay attacks and unexpected RelayState. Most teams support SP-initiated as the primary flow and treat IdP-initiated as opt-in per customer.

Attribute mapping and just-in-time provisioning

The SAML assertion carries a NameID (usually the user's email) and a set of attributes the IdP chose to release. Common attributes: `email`, `firstName`, `lastName`, `groups` or `memberOf`. Your app maps these to internal fields: email becomes the auth.users row, groups can map to roles in the workspace.

Just-in-time (JIT) provisioning means a user who has never signed in before is created on the first successful SAML assertion. SaaSForge Core's hook accepts a mapping function that decides which workspace the new user joins and which role they get based on group claims. The alternative, manual provisioning, requires admins to invite every user before SSO works, which defeats most of the operational appeal.

Attribute mapping config shape (SaaSForge Core hook)
export const samlMapping = {
  workspaceId: "{{workspace_id_from_subdomain}}",
  email: (assertion) => assertion.attributes.email,
  role: (assertion) => {
    const groups = assertion.attributes.groups ?? [];
    if (groups.includes("admins")) return "admin";
    if (groups.includes("members")) return "member";
    return "viewer";
  },
};

Why teams use BoxyHQ Jackson, WorkOS, or Supabase SSO

Implementing SAML from XML primitives is a tarpit: signature canonicalization, certificate rotation, metadata exchange formats, and twenty years of IdP-specific quirks. BoxyHQ Jackson is an open-source SAML-as-a-service you can self-host; WorkOS and Stytch are managed services with per-connection pricing; Supabase Auth has its own SSO product on paid plans. All three give you a normalized API ('here's a signed assertion, decoded into attributes') so your app code never touches raw SAML XML.

The honest trade-off: managed services cost per connection ($125-$250/month/connection on some vendors) but reclaim the engineering month you would otherwise spend on XML signing edge cases. Self-hosted Jackson is free but adds operational surface. SaaSForge Core's hooks are written to plug into any of these, the workspace-side logic does not change.

Frequently asked

Can I ship SAML SSO with just SaaSForge Core today?
You can ship the workspace-side scaffolding and pair it with a managed SAML provider (Supabase Auth SSO on a paid Supabase plan, BoxyHQ Jackson self-hosted, or WorkOS/Stytch). The full turnkey integration, your own ACS endpoint, AuthnRequest generation, metadata UI, is the SaaSForge SAML SSO Kit module on the roadmap. Be honest with your enterprise buyer about which path you are taking; both are credible.
How do customers configure their IdP?
Each customer's IT admin downloads your app's SP metadata (an XML file describing your ACS URL and signing certificate) and uploads it to their IdP (Okta, Azure AD, Google Workspace). They then download the IdP metadata and paste it into your SSO settings page. SaaSForge Core's settings UI accepts the IdP metadata XML or URL; the managed SAML layer parses it.
What about SCIM for user provisioning?
SAML handles authentication; SCIM handles directory sync (auto-provisioning and deprovisioning users when they join or leave the customer's org). The two are usually requested together by enterprise buyers but are separate protocols. SaaSForge Core does not ship SCIM today; the SAML SSO Kit module covers SAML, and SCIM is a separate planned module. For most early enterprise deals, JIT provisioning via SAML claims is enough.
Does SSO replace 2FA?
It can, but the policy is the customer's call. Most enterprise IdPs enforce MFA at the IdP level (Okta, Azure AD); when SAML SSO is enabled for a workspace, the customer's MFA policy is the one that applies, and your app's TOTP 2FA is typically disabled for SSO users. SaaSForge Core's auth flow respects this, TOTP is required only for non-SSO users by default.
Will SSO work with the four-role RBAC out of the box?
Yes. The attribute-mapping hook lets you map IdP group claims to SaaSForge Core's four roles (Owner, Admin, Member, Viewer). For customers who do not configure group claims, the default role is configurable per workspace, typically Member, with Owners promoted manually.
Ships in SaaSForge Core

See SaaSForge Core. Skip the deliberation.

Full source code. Lifetime updates. Polar Merchant-of-Record checkout. Private GitHub repo on purchase.