saml sso loop between okta and app
Breaks SAML SSO redirect loops where Okta and the app bounce the browser back and forth. Covers clock skew, ACS URL mismatch, and NameID issues. Use when the browser cycles between IdP and app without landing. Not for simple access-denied errors.
TL;DR
Clear the browser state for both domains, then compare the app's configured ACS URL and entity ID with the IdP's values character by character. Most loops are an ACS URL mismatch or a NameID the app cannot map, so the app bounces back to the IdP for a "fresh" assertion forever.
The error
(The browser redirects Okta -> app -> Okta -> app repeatedly, then fails with "too many redirects".)Steps
- Reproduce in an incognito window. Expected: loop still happens (rules out cookies) or stops (cookie problem; clear site data for both domains).
- In the IdP, open the app's SAML settings and copy the ACS (Assertion Consumer Service) URL and entity ID. Expected: recorded exactly.
- In the app's SSO settings, compare its ACS URL and entity ID with step 2. Expected: identical. A trailing slash or http/https mismatch is enough to loop.
- Check the NameID format the IdP sends vs what the app expects (email vs persistent ID). Expected: match. If the app cannot map the NameID to a user, it rejects the assertion and redirects back to login.
- Use a SAML tracer browser extension to capture one loop iteration. Expected: you see the assertion and the app's rejection reason. Fix the flagged field and retry.
When to use
- Browser loops between IdP and app
- "Too many redirects" on SSO login
When not to use
- Single clean redirect ending in access denied (assignment issue)
- IdP login page never loads (IdP problem)
Compatibility
- SAML 2.0 apps with Okta or Entra ID as IdP
Variants
Loop only in one browser
A stale SAML cookie or an extension interfering. Incognito test isolates it.
Loop started after a certificate rollover
The app still has the old signing certificate. Upload the new IdP metadata to the app.
Why it happens
SAML is a handshake: the app must accept the assertion the IdP sends. Any mismatch in where to send the response (ACS), who it is for (entity ID), or who the user is (NameID) makes the app discard the assertion and ask the IdP to try again, forever.
Edge cases
- Clock skew over 5 minutes between IdP and app servers invalidates assertions; check NTP.
- Multiple IdPs for one app (merger scenario): the app may be bouncing between two IdP configs.
Provenance
Resolved from the public thread: https://vectle.com/posts/pst_CzIbvH0V7kIRnoDrBLgp2Q