Why Your SAML Entity ID Must Be Stable (And How We Fixed Ours)
Why Your SAML Entity ID Must Be Stable (And How We Fixed Ours)
Release: v1.0.57
The Problem
When you set up SAML-based Single Sign-On in the dashboard, the SSO Configuration page shows you two critical pieces of Service Provider (SP) metadata that you need to register with your Identity Provider:
- ACS URL (Assertion Consumer Service URL) — where your IdP sends the SAML response after authentication.
- Entity ID — a unique, stable identifier for the SP (our platform) registered in your IdP.
In earlier versions of the platform, both of these values were constructed client-side using window.location.origin — that is, whatever domain the browser happened to be on when the page loaded.
This introduced two bugs:
1. Hydration Flash on Page Load
During server-side rendering, window does not exist. This meant the ACS URL and Entity ID fields rendered as empty strings on the server, then filled in once JavaScript ran on the client. The result was a visible flicker — the fields would briefly appear blank before showing the correct values.
2. Wrong Entity ID When Using a Custom Domain
This was the more serious issue. Many organizations access the admin dashboard through a custom domain (for example, org.example.com). When window.location.origin was used as the base, the displayed Entity ID would become:
https://org.example.com/api/auth/sso/{orgSlug}/saml/metadata
This is incorrect. The Entity ID must be stable and must match exactly what was registered with the IdP when SSO was first configured. SAML is strict about this — if the Entity ID presented by the SP at runtime differs from the one the IdP has on record, authentication will fail.
The correct Entity ID is always based on the canonical platform domain, not the domain an admin happens to be browsing from.
The Fix
As of v1.0.57, the ACS URL and Entity ID displayed in the SP details panel are both derived from the NEXT_PUBLIC_APP_URL environment variable — the platform's canonical base URL — rather than window.location.origin.
Entity ID: {NEXT_PUBLIC_APP_URL}/api/auth/sso/{orgSlug}/saml/metadata
ACS URL: {NEXT_PUBLIC_APP_URL}/api/auth/sso/{orgSlug}/saml/callback
This means:
- The values are consistent regardless of which domain or subdomain an admin uses to access the dashboard.
- The values are available at server render time, eliminating the hydration flash.
- The values match what should be registered in the IdP, preventing authentication failures.
What You Should Do
If you configured SAML SSO on an affected version and your dashboard was accessed via a custom domain at the time, your IdP may have been configured with an incorrect Entity ID.
To verify:
- Open Dashboard → Settings → SSO Configuration.
- Check the Entity ID shown in the SP details panel.
- Compare it to the Entity ID registered in your IdP (e.g. in Okta, Azure AD, Google Workspace, etc.).
- If they differ, update the Entity ID in your IdP to match the value shown in the dashboard.
Note: Changing the Entity ID in your IdP is a one-time correction. Once aligned, the value will remain stable going forward.
Background: Why Entity IDs Must Be Stable
The SAML specification treats the Entity ID as a permanent, opaque identifier. IdPs store this value when you configure a SAML application and use it to look up the correct SP configuration on every authentication request. If the Entity ID changes — even subtly — the IdP will reject the request or fail to find a matching configuration.
This is why basing the Entity ID on a runtime value like window.location.origin was problematic: it coupled a security-critical identifier to an environment-specific variable rather than a fixed, canonical one.