Problem
Section titled “Problem”Sign-in succeeds. The browser redirects back. Then your app calls getProfile() and gets not_authenticated. The session cookie is in the browser's storage (you can see it in DevTools) but it's not being sent to IntelliAuth on the API call.
One of three things, all related to cross-site cookies:
- Different sites — your app is at
app.cymmetri.comand the tenant is atbanking-cymmetri.intelliauth.local. By default, the browser only sends the session cookie to the tenant when it's on the tenant's own page. - SameSite=Strict — the cookie was issued with
SameSite=Strict, and your fetch is from a different site. credentials: 'omit'— your fetch call did not opt into sending credentials.
The first two are configuration on the IntelliAuth side; the third is configuration in your code.
Resolution
Section titled “Resolution”If you control the tenant URL and the app URL
Section titled “If you control the tenant URL and the app URL”Put the app and the tenant on the same registrable domain so the cookie is first-party:
- App at
app.cymmetri.com, tenant atauth.cymmetri.com— both oncymmetri.com, cookies flow naturally. - App at
cymmetri.com, tenant atcymmetri.com/auth/*(via reverse proxy) — same origin entirely.
Then on the IntelliAuth side, the application's session cookie is SameSite=Lax and the browser sends it on top-level navigations + same-site fetches. This is the simplest configuration.
If you can't share a domain (true cross-site)
Section titled “If you can't share a domain (true cross-site)”Configure the application's session cookie as SameSite=None; Secure:
- Applications → your application → Settings → Cookie behaviour.
- Pick "Cross-site (SameSite=None, Secure)".
- Save.
The cookie now sends on cross-site fetches BUT requires HTTPS (the Secure attribute). This means no http://localhost testing in this mode — use https://localhost with mkcert or similar.
In your fetch code
Section titled “In your fetch code”Always use credentials: 'include' for IntelliAuth-bound fetches:
fetch(`${tenantUrl}/api/v1/me/profile`, { credentials: 'include', headers: { 'Authorization': `Bearer ${token}` },})The SDK does this for you. If you're hand-rolling the fetch, do it.
How to diagnose quickly
Section titled “How to diagnose quickly”In the browser DevTools network tab, find the failing request. Look at Request Headers → Cookie. If the IntelliAuth session cookie is in the list, the cookie is reaching the server and something else is wrong. If it's missing, it's a cookie-policy problem — work backwards from the issuing response (the Set-Cookie on /oauth2/token's response) to see the attributes.
Also check Console → Application → Cookies → <tenantUrl>. The cookie should be there with reasonable attributes. If it isn't there at all, the issuing response didn't set it (different problem — likely a TLS or response-handling issue).
Edge cases
Section titled “Edge cases”- iOS Safari is the strictest about cross-site cookies, and the most likely platform to fail when other browsers succeed. Test on iOS Safari early.
- Embedded webviews (in mobile apps) often have third-party cookies disabled. Use the system browser instead (per RFC 8252) — see the native PKCE topic.
- Subdomain mismatch —
app.cymmetri.comandcymmetri.comare different sites. The cookie'sDomainattribute determines which subdomains the cookie reaches.