Summary: | Tracking blocking breaks remembering login on editor.construct.net | ||
---|---|---|---|
Product: | WebKit | Reporter: | Ashley Gullen <ashley> |
Component: | DOM | Assignee: | Nobody <webkit-unassigned> |
Status: | RESOLVED WONTFIX | ||
Severity: | Normal | CC: | beidson, bfulgham, cdumez, sihui_liu, webkit-bug-importer, wilander |
Priority: | P2 | Keywords: | InRadar |
Version: | Other | ||
Hardware: | Unspecified | ||
OS: | Unspecified |
Description
Ashley Gullen
2019-10-07 09:59:24 PDT
I loaded editor.construct.net. It only uses resources from *.construct.net and clicking on Login results in cookies set for both editor.construct.net and account.construct.net that persist for months. The cookies are set for .construct.net which means they span the whole website. I can't do a full login to test what happens from that point since I don't have an account. Can you you please test yourselves and answer these questions: 1. Which domains are involved in the login? Specifically if any non-construct.net domain is involved. 2. Which kinds storage are involved in the login? Cookies? LocalStorage? IndexedDB? 3. Do you see any state change as a result of the login? Or is nothing accepted? Thanks! I pointed out signing up an account is free and pretty quick so you should be able to straightforwardly test this yourself. To answer your questions: 1. Only editor.construct.net (top frame) and account.construct.net (login frame) 2. The login state is remebered using IndexedDB. 3. I'm not sure what state you're referring to here exactly. As far as I can tell nothing is allowed to be written to IndexedDB. OK, so you're using IndexedDB. AFAIK, WebKit blocks IndexedDB in cross-origin contexts. In Web Inspector's console, execute this in your "login" iframe (you can pick frame in the lower right corner of the Inspector): 1. document.location.origin Output: "https://account.construct.net" 2. window.indexedDB Output: IDBFactory {open: function, deleteDatabase: function, cmp: function} 3. window.indexedDB.open("TestDatabase", 3); Output: SecurityError: IDBFactory.open() called in an invalid security context My advise is to catch errors in your IndexedDB code and see if you are being blocked. I already knew that was happening when I filed this issue. The point is this worked in Safari 12 and now Safari 13 is falsely blocking a legitimate use case, where the user is entering their login details in a frame, so surely are signalling their interest in that origin. Safari 13 should allow this case and not block it. Also, we already identify that we're being blocked, but what can we do about it? It's not clear there's any workaround. Cc'ing Brady. Brady, the reporter claims this is a regression/change from Safari 12. Did anything in the security checks of cross-origin use of IDB change lately? (In reply to John Wilander from comment #7) > Cc'ing Brady. > > Brady, the reporter claims this is a regression/change from Safari 12. Did > anything in the security checks of cross-origin use of IDB change lately? None that I know of? Sihui? (In reply to Brady Eidson from comment #8) > (In reply to John Wilander from comment #7) > > Cc'ing Brady. > > > > Brady, the reporter claims this is a regression/change from Safari 12. Did > > anything in the security checks of cross-origin use of IDB change lately? > > None that I know of? > > Sihui? We use the same logic to check if we should throw SecurityError. Maybe some condition value has changed due to other security changes. Need to take a deeper look. (In reply to Ashley Gullen from comment #5) > I already knew that was happening when I filed this issue. The point is this > worked in Safari 12 and now Safari 13 is falsely blocking a legitimate use > case, where the user is entering their login details in a frame, so surely > are signalling their interest in that origin. Safari 13 should allow this > case and not block it. Which version of Safari does this work? I tested on Safari 12.0(14606.1.36.9) and I saw the same error. Urgh, I just tried Safari 12 and it's the same there - so I guess this part of our app has been broken for a while now and we only just noticed. Is there a workaround though? How can we make sure an iframe the user enters their login details to is allowed to save to IndexedDB? (In reply to Ashley Gullen from comment #11) > Urgh, I just tried Safari 12 and it's the same there - so I guess this part > of our app has been broken for a while now and we only just noticed. > > Is there a workaround though? How can we make sure an iframe the user enters > their login details to is allowed to save to IndexedDB? As mentioned, Safari blocks IDB for cross-origin frames. As far as I know, that’s always been the case. Only the first party domain can use IDB. If you want one of your domains to use IDB, that domain needs to be first party, i.e. be top frame. Resolving as Won’t Fix since this behavior is by design and not a regression in Safari 13. So is it the case that Safari always unconditionally blocks IndexedDB access in cross-origin iframes with no workaround? Even if the user interacts with them? (In reply to Ashley Gullen from comment #14) > So is it the case that Safari always unconditionally blocks IndexedDB access > in cross-origin iframes with no workaround? Even if the user interacts with > them? That is my understanding, yes. Brady, who is cc’d, knows for sure. We've tried implementing document.requestStorageAccess() in a user gesture (when clicking the login button) and we can see the request is granted. However after reloading the page, IndexedDB is still blocked, so the login is still forgotten despite the user's preference. If there is no workaround, we are incentivized to tell users to turn off the "Prevent cross-site tracking" setting for Safari to remember their logins. This is a global switch that affects all their browsing. I doubt this is the outcome Apple want. The Storage Access API, as implemented in WebKit, only opens up cookie access. Since your iframe is same-site, i.e. has the same registrable domain as the top frame, it does not need to call the Storage Access API. The iframe has cookie access from the get go. IndexedDB is blocked in cross-origin contexts. You need to use another mean of persistence for your login credentials if you persist the login in a cross-origin iframe. This blocking behavior is not new and your login mechanism has likely never worked in Safari. That’s probably due to lack of testing which is unfortunate. Telling users to turn off all privacy protections in their browser is not the right course of action. Why doesn't the storage access API provide access to IndexedDB? Couldn't that be supported? The purpose of using a cross-origin frame is to hide the storage from the main origin, where we have to run third-party scripts that shouldn't have access to the storage. I don't know what other options we have to persist a login token on the client, other than to weaken our security by allowing third-party scripts access to login tokens. So long as we can't identify a way it's possible to solve this, telling our users to disable "Prevent cross-site tracking" appears to be the only option we have. (In reply to Ashley Gullen from comment #18) > Why doesn't the storage access API provide access to IndexedDB? Couldn't > that be supported? You’re welcome to file it as an enhancement request. The reason why is that IDB has always been blocked this way in WebKit. Cookies, however, used to be accessible cross-site but are no longer when ITP blocks them. Therefore we invented the Storage Access API to support existing use cases. > The purpose of using a cross-origin frame is to hide the storage from the > main origin, where we have to run third-party scripts that shouldn't have > access to the storage. I don't know what other options we have to persist a > login token on the client, other than to weaken our security by allowing > third-party scripts access to login tokens. So long as we can't identify a > way it's possible to solve this, telling our users to disable "Prevent > cross-site tracking" appears to be the only option we have. The standard/common way of achieving this is through Secure, HttpOnly cookies. They are not exposed to JavaScript and are also not transferred into the web content process which means they are protected against speculative execution attacks. You can also scope cookies to the host, i.e. including the subdomain, which ensures only requests to that host see the cookie. |