What this usually means
The SameSite attribute tells the browser whether to send a cookie with cross-site requests. Modern cookie handling uses schemeful same-site: the site key includes the scheme and registrable domain (eTLD+1). HTTPS subdomains that share an eTLD+1 are normally same-site, but an HTTP URL and an HTTPS URL are cross-site even when the hostname matches. Cookies without an explicit SameSite value are commonly treated as Lax. SameSite=None requires Secure; without it, the browser rejects the cookie.
The first ten minutes — establish facts before touching code.
- 1Open Chrome DevTools (F12) → Application → Storage → Cookies. Check the SameSite column for the cookie in question. Note: 'Lax' or 'Strict' means it won't be sent cross-site.
- 2Use the Network tab to inspect a failing request. Look at Request Headers: if Cookie header is missing, the browser blocked it. Also check the 'Initiator' tab for 'cross-site' warnings.
- 3Run curl with the cookie to see if the server accepts it: curl -v --cookie 'name=value' https://api.example.com/endpoint. If that works, it's a browser SameSite issue.
- 4Test in incognito mode—if it works, the browser likely has a cached stricter policy or existing cookies with SameSite=None without Secure.
- 5Check the server's Set-Cookie header in response: ensure SameSite attribute is present and set correctly (None for cross-site, Lax for most same-site). For None, Secure must be true and HTTPS must be used.
The specific files, logs, configs, and dashboards that usually own this bug.
- searchChrome DevTools → Application → Storage → Cookies: list all cookies with their SameSite values
- searchChrome DevTools → Network → select failing request → Headers → Request Headers: check if Cookie is present
- searchChrome DevTools → Network → select failing request → Headers → Response Headers: look for Set-Cookie
- searchServer-side logs: check if the server is receiving any cookies in the request header
- searchCDN or proxy logs (Cloudflare, Fastly): some CDNs can strip or modify cookies based on SameSite
- searchBrowser console: warnings like 'A cookie associated with a cross-site resource was set without the SameSite attribute'
- searchThird-party cookie blocking settings: chrome://settings/content/cookies (Chrome) or edge://settings/content/cookies
Practical causes, not theory. These are the things you will actually find.
- warningCookie set without SameSite attribute, defaulting to Lax in Chrome 80+, blocking cross-site subrequests
- warningSameSite=None set but Secure flag missing, causing browser to reject the cookie entirely
- warningServer sets SameSite=Strict on a cookie needed for cross-site OAuth redirect (GET) because Strict blocks top-level navigations
- warningCross-site request from a subdomain that is actually different site (e.g., app.example.com vs api.other.com), but developer assumed subdomain is same-site
- warningCookie domain attribute too narrow (e.g., set for 'api.example.com' but request from 'www.example.com' is same-site but cookie not sent due to domain mismatch)
- warningBrowser extensions or privacy settings enforcing strict SameSite (e.g., Chrome's 'Block third-party cookies' overrides SameSite=None)
Concrete fix directions. Pick the one that matches your root cause.
- buildSet SameSite=None; Secure for cookies that must be sent cross-site. Ensure the response is over HTTPS.
- buildFor same-site cookies, use SameSite=Lax or Strict when appropriate. Verify both scheme and registrable domain: HTTPS subdomains under the same eTLD+1 are normally same-site, while HTTP-to-HTTPS and different registrable domains are cross-site.
- buildIf OAuth redirect fails, set the session cookie with SameSite=Lax (allows top-level GET navigations). Do not use Strict for redirect flows.
- buildIf the cookie is needed in iframes or subrequests, set SameSite=None; Secure and ensure the parent page is HTTPS.
- buildUse the Cookie Prefix __Host- or __Secure- to enforce Secure and Path=/ for extra safety, but ensure compatibility.
- buildTest with curl and browser DevTools to isolate server behavior from browser policy. Use controlled HTTP and HTTPS test hosts instead of version-specific browser flags.
A fix you cannot prove is a guess. Close the loop.
- verifiedAfter fix, clear cookies for the site and re-test the flow. Check in DevTools → Application → Cookies that the SameSite column shows the expected value.
- verifiedIn Network tab, confirm the Cookie header is present on the failing request. Also verify Set-Cookie response header includes SameSite=None; Secure.
- verifiedRun the failing scenario in an incognito window to ensure no stale cookies interfere.
- verifiedTest in multiple browsers (Chrome, Firefox, Safari) to confirm consistent behavior.
- verifiedCheck the server logs to ensure the cookie is being received and processed.
- verifiedUse a test like 'https://samesite-sandbox.glitch.me/' to simulate cross-site requests and verify cookie behavior.
Things that make this bug worse or harder to find.
- warningSetting SameSite=None without Secure on HTTP—browsers will reject it.
- warningChanging SameSite to Lax/Strict globally without understanding which requests need cross-site cookies (e.g., login redirects).
- warningClassifying requests by hostname alone. SameSite is schemeful: matching HTTPS subdomains can be same-site, while HTTP and HTTPS versions of the same hostname are cross-site.
- warningForgetting to update the cookie domain attribute when moving from one subdomain to another.
- warningApplying SameSite=Strict on session cookies that are needed for top-level navigation from external sites.
- warningRelying on third-party cookies being enabled by default—privacy trends are blocking them more.
OAuth Login Fails After Chrome Update to SameSite Default Lax
Timeline
- 09:00Users report they cannot log in via Google OAuth. They click 'Sign in with Google', are redirected to Google, then back to our site but remain unauthenticated.
- 09:15Logs show that the callback endpoint receives no session cookie, and DevTools reports a cookie eligibility warning.
- 09:30DevTools shows no explicit SameSite value, so the browser applies its Lax default. The OAuth callback is confirmed as a top-level navigation.
- 09:45The team confirms the callback is a top-level HTTPS GET. A Lax cookie can accompany that navigation, so SameSite alone does not explain the omission.
- 10:00A curl request with the cookie succeeds, proving the server accepts it. DevTools shows the browser is omitting the cookie before the request reaches the application.
- 10:15The Set-Cookie header has no explicit SameSite value, so the browser applies its Lax default. The callback method and navigation type are still compatible with Lax.
- 10:30The cookie attribute audit finds Path=/api while the callback is /oauth/callback. Those paths do not match, so the cookie is ineligible before SameSite is evaluated.
- 10:45A minimal reproduction with Path=/ reproduces the same OAuth navigation and sends the Lax cookie successfully.
- 11:00The public callback is confirmed to use HTTPS, so Secure is not the blocking attribute.
- 11:15The Domain value is valid for the callback host. A leading dot would not change its scope because modern browsers ignore leading dots in Domain values.
- 11:30The cookie Path is changed to /. The original SameSite=Lax policy is retained, and the OAuth callback succeeds.
This composite incident begins with an OAuth callback that reaches the application without its session cookie. DevTools shows a Lax cookie and an HTTPS top-level GET, a combination that should permit the cookie on the navigation.
A complete attribute audit reveals the real mismatch: the cookie is scoped to Path=/api while the callback is /oauth/callback. Because the request path does not match, the browser omits the cookie regardless of SameSite.
The fix changes Path to / and retains SameSite=Lax. The lesson is to verify Domain, Path, Secure, request scheme, navigation type, and method as separate gates instead of treating SameSite as the only cookie policy.
Root cause
Cookie Path attribute mismatch: cookie set with Path=/api but OAuth callback at /oauth/callback, causing browser to omit the cookie regardless of SameSite.
The fix
Changed the session cookie Path to '/' and verified SameSite=Lax (default) works for top-level navigation from cross-site.
The lesson
When a cookie is not sent, always check Path and Domain before SameSite. Use DevTools to see cookie attributes. Isolate with curl and a simple test page. Don't assume SameSite is the only cause.
Modern browsers apply schemeful same-site for SameSite cookies. The site key includes the URL scheme and registrable domain (eTLD+1). For example, https://app.example.com and https://api.example.com are same-site, while http://example.com and https://example.com are cross-site even though the hostname matches.
Ports and paths are not part of the site key. Subdomains that share a registrable domain are same-site only when the scheme also matches. Origin remains a stricter boundary because it additionally considers the full host and port.
The SameSite attribute can be Strict, Lax, or None. Strict: cookie never sent on cross-site requests (including top-level navigations). Lax: cookie sent on cross-site top-level navigations that use a 'safe' HTTP method (GET, HEAD, OPTIONS, TRACE). None: cookie sent on all cross-site requests, but requires Secure flag and HTTPS. If SameSite=None is set without Secure, the cookie is rejected by the browser.
The cookie's Path must match the request URL path. Omitting Domain creates a host-only cookie. Setting Domain=example.com makes the cookie available to that domain and its subdomains; modern browsers ignore a leading dot, so Domain=.example.com has the same scope. A server may set only its current domain or a parent domain that is not a public suffix. Domain and Path eligibility are checked independently from SameSite.
To isolate browser policy from server behavior, first test with curl: curl -v --cookie 'name=value' https://yoursite.com/endpoint. Then use controlled HTTP and HTTPS test hosts under the same registrable domain. If HTTPS-to-HTTPS succeeds but HTTP-to-HTTPS is treated as cross-site, you have confirmed schemeful same-site behavior.
Use DevTools cookie-blocking reasons and a minimal reproduction instead of browser flags that can disappear between releases. Production behavior must work under the browser's current defaults.
Frequently asked questions
What is the difference between SameSite=Lax and SameSite=Strict?
SameSite=Strict: the cookie is never sent on cross-site requests, including top-level navigations. This means if a user clicks a link from an external site to your site, the cookie won't be sent. SameSite=Lax: the cookie is sent on cross-site top-level navigations that use a safe HTTP method (GET, HEAD, etc.). This allows links and redirects to work while still protecting against CSRF from subrequests like images or iframes. For most login flows, Lax is sufficient.
Why is my SameSite=None cookie not being set?
The most common reason is that the Secure flag is missing. SameSite=None requires the cookie to be marked Secure and transmitted over HTTPS. If you set SameSite=None without Secure, the browser will ignore the cookie. Also, ensure the response is over HTTPS. Another reason: the cookie's Domain or Path may conflict, or the cookie size exceeds the browser limit (usually 4KB). Check the Set-Cookie header in DevTools to see if it's rejected.
Does SameSite affect cookies in iframes?
Yes. If your page embeds an iframe from a different site, and you need to send cookies from that iframe to its server, those cookies must have SameSite=None; Secure to be sent with the iframe's requests. If the cookie has SameSite=Lax or Strict, the browser will not send it for cross-site subrequests (like iframe loads). This is a common issue with third-party widgets or payment forms.
How can I debug SameSite issues in Safari or Firefox?
In Safari, go to Develop → Show Web Inspector → Storage → Cookies. You can see the SameSite column (though older versions may not show it). In Firefox, open Developer Tools → Storage → Cookies, and look for the SameSite column. Both browsers may have different default behaviors: Safari historically blocked third-party cookies by default, while Firefox uses Total Cookie Protection. For testing, use Chrome's detailed SameSite warnings in the Console.
Can I use SameSite cookies with APIs that are called from mobile apps?
SameSite is a browser concept; mobile app HTTP clients (like OkHttp, URLSession) do not enforce SameSite. However, if your mobile app uses a WebView to display web content, the WebView may enforce SameSite like a browser. For native API calls, cookies are sent as usual. But if you use cookie-based auth in a mobile app, you should consider token-based auth instead, because cookies may not be stored reliably.