html icon indicating copy to clipboard operation
html copied to clipboard

navigator.cookieEnabled in third-party contexts

Open arichiv opened this issue 1 year ago • 10 comments

The attribute navigator.cookieEnabled is “true if the user agent attempts to handle cookies according to HTTP State Management Mechanism” according to the spec, and in first-party contexts this holds true cross-browser (though sometimes ‘true’ is returned even where trying to use document.cookie would throw an exception). More than 40% of sites loaded in Chrome use this API in some context.

In third-party contexts the functionality diverges. Safari returns true if the browser has cookies enabled, even though Safari has blocked cookies in third-party contexts since 2020. In Firefox and Chromium-based browsers the attribute is false in third-party contexts if unpartitioned cookie access is blocked.

What should we do about this divergence? There are a few potential paths:

  1. Do nothing and allow the meaning in browsers to continue to diverge.
    • This is what we have been doing, but by this point the exact choices major vendors are taking around third-party cookies are known and/or implemented so some action seems reasonable.
  2. Mark the function as undefined in third-party contexts (not that it returns undefined, but that the meaning is undefined) and/or deprecated.
    • This is similar to (1) but modifies the spec to clarify that behavior between vendors diverges so the function is not a consistent source of similar meaning.
  3. Always return false in third-party contexts.
    • This is likely to break existing pages dependent on vendor-specific behavior.
  4. Always return true in third-party contexts.
    • This is likely to break existing pages dependent on vendor-specific behavior.
  5. Stick to the current definition on the spec for both first- and third-party contexts.
    • This aligns with what Safari is currently doing, but would require changes in Firefox and Chrome that might break pages dependent on their current behavior.
  6. Note that in third-party contexts true is returned if and only if access to unpartitioned cookies is possible.
    • This aligns with what Firefox and Chrome are currently doing, but would require changes in Safari that might break pages dependent on its current behavior.

Regardless of which path is taken, we should push developers to consider using document.hasStorageAccess() which is available cross-browser and behaves consistently (returns true if unpartitioned cookies are accessible in a third-party context). Although this is not a 1:1 replacement, distilling all of the context needed on which kinds of cookies can or cannot be distilled into a single boolean In many cases developers may need to attempt usage of document.cookie itself to understand the lay of the land (as some already do).

Independently (not in scope for this proposal, but worth contemplating)

It would be nice if information about what ‘Cookie Rules’ exist in a given context were available. Cookies have many possible attributes, and different browsers have different requirements around when cookies can be set. For example: in Chrome it’s not possible to set SameSite=None without Secure, in Safari setting a persistent cookie via JavaScript caps the Max-Age to 7 days, and if CHIPs is required then third-party contexts can only set cookies with the Partitioned attribute. It seems likely based on divergent approaches by vendors that the set of requirements and limitations placed on cookies set in different contexts will only increase. It may be worth taking time to build a cross-browser API that exposes this information in some format. One could imagine a W3C Specification with an append-only enum of discrete rules a given context had to respect to use cookies. For example a developer could call something like document.getCookieRules() and check: if the resulting list contained the PARTITIONED_REQUIRED to know if cookies had to be partitioned to be set/read or if HTTPONLY_REQUIRED to know that cookies can only be set/read via HTTP Header and not in JavaScript.

arichiv avatar Apr 05 '24 15:04 arichiv

@johannhof @cfredric @sbingler @DCtheTall @bvandersloot

arichiv avatar Apr 05 '24 15:04 arichiv

When we discussed https://github.com/privacycg/storage-access/issues/171 I think I assumed 5.

It seems a bit weird if cookieEnabled returns false when partitioned cookies work.

annevk avatar Apr 05 '24 16:04 annevk

I think there's still a question of whether navigator.cookieEnabled means:

  • "does this UA support cookies (of any kind) in principle"
    • This seems like it is both 4 and 5? I'm not clear on how those differ, admittedly.
  • "does this UA support (possibly partitioned) cookies in this context"
    • This option isn't listed above.
  • "does this UA support unpartitioned cookies in this context"
    • This is 6 above.

If we choose the first bullet, every modern browser would return true unconditionally, IIUC. If we choose the second bullet, Chromium-based browsers would return true unconditionally, while Safari/Firefox would take Storage Access, user settings, etc. into account (based on caniuse). If we choose the last bullet, then the UA would take Storage Access, user settings, etc., into account.

Is an API that always returns true especially useful? I'm not sure that that's the best option here.

(It may be that that's the only viable option based on existing usage, though. It's plausible that this API is a relic from another time, and has lost its utility but has enough usage that it must still exist.)

cfredric avatar Apr 08 '24 17:04 cfredric

I guess the specification doesn't explicitly mention end user preferences, but that's what I would expect to be taken into account. In particular because of "and false if it ignores cookie change requests" (which is true if the end user has disabled cookies for that website or in general).

annevk avatar Apr 08 '24 17:04 annevk

I think I'm in camp "Build a better alternative that reflects the complexity of the situation and then fully deprecate and remove navigator.cookieEnabled". A lot of the discussions and misunderstandings we're having here are due to the overly simplistic nature of a single boolean for expressing cookie blocking / partitioning rules.

I like where Ari's "Cookie (Storage?) Capabilities API" idea is going, though I think it should include an HTTP request header variant to also solve the problem outlined in https://github.com/privacycg/storage-partitioning/issues/32

cc @shuranhuang @krgovind

johannhof avatar Apr 10 '24 11:04 johannhof

When we discussed privacycg/storage-access#171 I think I assumed 5.

It seems a bit weird if cookieEnabled returns false when partitioned cookies work.

Just to be sure @annevk, you're speaking as a spec editor here right? If so, is there a position that WebKit has you could share?

I'm asking as WebKit, to my understanding, returns true in third-party contexts where no cookies could be set (at least prior to some call to requestStorageAccess). I'm not trying to argue WebKit is uniquely inconsistent for doing this, there are edge cases in Chrome where true is returned despite cookies not being settable, just trying to see if there is some common ground vendors could implement after a spec change or if this API will remain an 'agree to disagree' area.

arichiv avatar Apr 10 '24 12:04 arichiv

It seems a bit weird if cookieEnabled returns false when partitioned cookies work.

Ditto.

Given that this hangs on navigator, I would expect this has to do with the cookie settings for a given UA, not with the context being used. So I would expect it to be true unless a user-preference to disable cookies has been set. If I follow that is what Safari does, and is a reasonable interpretation of the spec.

bvandersloot-mozilla avatar Apr 10 '24 13:04 bvandersloot-mozilla

It seems we all basically agree on what the spec currently says, but given Safari seems to align while Chrome and Firefox differ, do any of us feel the spec should say something else?

Put another way, @bvandersloot-mozilla do you think cookieEnabled should return true in Firefox in 3p contexts where unpartitioned cookie access is blocked (yet the browser/origin-level cookie setting is enabled)? Or should the spec change?

arichiv avatar Apr 11 '24 13:04 arichiv

Put another way, @bvandersloot-mozilla do you think cookieEnabled should return true in Firefox in 3p contexts where unpartitioned cookie access is blocked (yet the browser/origin-level cookie setting is enabled)?

Not sure what you mean by "(yet the browser/origin-level cookie setting is enabled)" but I agree with " cookieEnabled should return true in Firefox in 3p contexts where unpartitioned cookie access is blocked" generally.

bvandersloot-mozilla avatar Apr 11 '24 13:04 bvandersloot-mozilla

I have metrics in chrome M125 to measure usage of cookieEnabled in third-party contexts. Once I have some data from that I'll write up a proposal to align Chrome with the spec as it currently exists instead of proposing a change to the spec. The timeline for that might be quite long depending on usage.

arichiv avatar Apr 11 '24 14:04 arichiv