Safari ITP and Storage Access API: why does cross-site cookie auth work on localhost but not in production?
0 reputation · 21 Oct 2021, 16:48 UTC
0 reputation · 21 Oct 2021, 16:48 UTC
A web app embeds a cross-site authentication flow where a frontend on one origin sets SameSite=None; Secure cookies for an API on another. On localhost everything works: cookies are stored and sent as expected. Once deployed to production domains over HTTPS, Safari stops sending the cookies and the session appears lost.
My understanding is that Intelligent Tracking Prevention treats localhost as a first-party context, so its machine-learning classification never engages during local development. In production, the API domain may be classified as cross-site, blocking third-party cookies unless document.requestStorageAccess() is called after a transient user gesture. What remains unclear is how to design and test around this boundary:
35775 reputation · 22 Oct 2021, 02:35 UTC
Safari's Intelligent Tracking Prevention (ITP) explicitly exempts localhost from third-party cookie restrictions to prevent development bottlenecks. In production, however, ITP treats cookies from a different origin as third-party and blocks them by default, regardless of the SameSite=None; Secure attributes, if the browser classifies the interaction as cross-site tracking.
While ITP uses machine-learning heuristics to identify trackers, the primary trigger for your production failure is the cross-site context. In Safari, a cookie is considered third-party if the domain setting the cookie differs from the domain in the address bar. Localhost is treated as a first-party context by default, which is why your authentication flow works locally but fails on production domains.
document.requestStorageAccess() covers all cookies for the requesting origin. It does not need to be re-requested per individual cookie.Since you cannot reproduce ITP's classification database on localhost, you must shift your verification to a staging environment.
app-staging.example.com and api-staging.example.com) over HTTPS.document.hasStorageAccess() to programmatically determine if the browser is currently blocking your cookies.document.requestStorageAccess().Set-Cookie header is being ignored or if the cookie is missing from the request headers.If a user denies the Storage Access prompt, there is no programmatic way to force cookie access. The only documented fallbacks are:
api.example.com and app.example.com). This allows the use of SameSite=Lax and avoids the third-party classification entirely.Diagnostic Detail Needed: Are your frontend and API domains sharing a common root domain (e.g., app.example.com and api.example.com), or are they entirely different registered domains?
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.