Post

Replies

Boosts

Views

Activity

`WKHTTPCookieDataStore` cookie data loss and synchronization issues seen at scale
Hello, I am investigating a WKWebView cookie reliability issue with WKWebsiteDataStore.default() / persistent website data, and I would like to request a supported public API to force persistent cookie durability. We set persistent cookies from native code through the public WKHTTPCookieStore API: let dataStore = WKWebsiteDataStore.default() let cookieStore = dataStore.httpCookieStore await cookieStore.setCookie(cookie) The cookies have Max-Age / maximumAge set, so these are persistent cookies, not session-only cookies. Reproduction pattern: Use WKWebsiteDataStore.default(). Clear existing cookies. Set a persistent cookie through WKHTTPCookieStore.setCookie. After setCookie completes, terminate WebKit's NetworkProcess soon afterward. Create or reuse a WKWebView with the same WKWebsiteDataStore.default(). Load a same-origin page or trigger a same-origin fetch. I also have reproducible WebKit source-level test cases for this, in the style of TestWebKitAPI / WKHTTPCookieStore tests. The tests exercise persistent WKWebsiteDataStore.default() cookies, terminate the NetworkProcess after the cookie mutation, and then verify that a top-level load, same-origin fetch, and WKHTTPCookieStore cookie read can miss the cookie on an unpatched WebKit build. Observed result: The next top-level HTTP request, and sometimes a same-origin fetch, can omit the cookie that was just set. After the NetworkProcess is relaunched, WKHTTPCookieStore.allCookies() can also fail to show the recently set cookie. If I wait long enough after the cookie mutation before terminating the NetworkProcess, the problem disappears. In local simulator testing, this lines up with CFNetwork appearing to debounce/coalesce persistent cookie writes in an approximately 2-to-10 second window. That makes this look like setCookie completion means the current NetworkProcess / CFNetwork cookie store accepted the cookie in memory, but the persistent cookie backing store has not necessarily been written yet. If the NetworkProcess dies before that delayed write, the replacement NetworkProcess appears to reload stale cookie state from disk. This is especially painful for apps that bridge native authentication state into WKWebView. The app sees setCookie complete, assumes the cookie is ready, and then a later WebKit NetworkProcess termination can cause authenticated web requests to be sent without the expected auth cookie. We believe that, at scale, this is a mechanism causing a baseline of about 5% of our HTTP requests, as measured by HAProxy, to lack cookies that should be present. We know those cookies should be present because we duplicate the same values as URLRequest headers under different keys, and the headers are present while the corresponding Cookie header entries are missing. The API gap is that there does not appear to be a supported public equivalent of Android WebView's CookieManager.flush(). There is no public way for an app to say: "I just mutated persistent WKWebView cookies; please synchronously/asynchronously flush the persistent cookie store before I proceed." Request: Please expose a public flush API for persistent WKHTTPCookieStore / WKWebsiteDataStore cookies, for example an async API shaped like: try await websiteDataStore.httpCookieStore.flush() or: try await websiteDataStore.flushCookies() The important behavior would be: after WKHTTPCookieStore.setCookie / deleteCookie completes, an app can explicitly request durability; the flush completion should mean persistent cookie state has been handed to the backing persistent store, not merely accepted by the current NetworkProcess; if flushing is impossible because the relevant process/state is gone, the API should fail or report that, rather than silently succeeding; the API should be safe for App Store apps and should not require private SPI. Question: Are there any recommended supported patterns today for forcing persistent WKWebView cookies to reach durable storage after native WKHTTPCookieStore mutations? Is there an official supported way to force or observe cookie durability for persistent WKWebsiteDataStore cookies? If not, is the recommended approach simply to re-apply critical cookies before loads and tolerate NetworkProcess loss as unrecoverable app-side state? This issue is not just theoretical. It affects auth/session reliability when WebKit's NetworkProcess is terminated before the backing persistent cookie write completes. Apps can reduce unnecessary cookie churn, but without a flush API there is no supported way to close the durability window after setting important persistent cookies.
Topic: Safari & Web SubTopic: General
2
0
541
2w
Unable to load CSS fonts from WKURLSchemeHandler in a https website
I am trying to cache fonts natively in a hybrid app, so that CSS hosted in an https website loaded in WKWebView through loadRequest can reference them like this for a performance boost: @font-face { font-family: 'MyFont'; src: url('my-assets://Gordita-bold-subset.woff') format('woff'); font-weight: normal; font-style: normal; } The problem happens when I register a WKURLSchemeHandler for my-assets. The handler never gets called and the Safari Web Insepctor shows this: [blocked] The page at https://www.x.com/ requested insecure content from my-assets://Gordita-bold-subset.woff. This content was blocked and must be served over HTTPS. Interestingly enough, if we try to serve content with <img src="my-assets://test.png" this restriction does not apply. Are there any workarounds other than using the private API WKProcessPool._registerURLSchemeAsSecure?
Topic: Safari & Web SubTopic: General
1
0
100
Jun ’25
WKWebView randomly does not send out cookies from WKWebSiteDataStore to our servers
PLATFORM AND VERSION iOS Development environment: Xcode 16.2, macOS 15.3.2 Run-time configuration: iOS 15-18 This happens in iOS, and leads to to the hybrid home page showing users as wrongly unauthenticated, since the at cookie is missing. For context, we have a JWT token that is stored in the Keychain, and on app launch, before any WKWebViews are created, we synchronize this to the WKWebsiteDataStore as an at cookie. We have analytics instrumentation on our websitef to show that WKWebView randomly refuses to send out any cookies. – The following is a snippet from an explanation to the WebKit Slack: We are having an issue on iOS, in which WKWebView loads pages (and even subsequent reloads) without any cookies, even though we have stored cookies in WKWebsiteDataStore.default() before hand right after application launch and becoming a key window. We reference this object, store it as a singleton, (as well as a process pool), and then all webview configurations are initialized with the same data store, the same process pool, every call on the main thread. From reading the source code, it seems that if the internal IPC logic fails, the APIs for deleting and setting data records and cookies fail without any feedback in completion handlers. This bug often happens when returning from the background on iOS after a few hours. Sometimes it happens on cold launches of the app. We have mitigated a similar issue (no cookies being sent) by implementing webViewWebContentProcessDidTerminate and reloading the webview ourselves, we found that whatever webview does to reload if that method is not implemented leads to cookies not being used. There have been multiple reports of WKWebView losing cookies in recent iOS versions, and we have tried to implement all of the workarounds listed. Setting a maximumAge to the cookies we store, and doing a _ = await websiteDataStore.dataRecords(ofTypes: Set([WKWebsiteDataTypeCookies])) before accessing or modifying websiteDataStore.httpCookieStore Question: is it safe to work with WKWebsiteDataStore before a WKWebView is added as a view, if so are there any timing considerations? Are there any logs that we can take a look at, this issue is very hard to reproduce, about 2% of our users face it at scale? Is there anything that could be happening within our process (runloop issues, timing) that could be causing this issue? See multiple reports from other companies that have faced the issue: "Now the Thermonuclear Problem with WKWebViewDataStorage" https://medium.com/axel-springer-tech/synchronization-of-native-and-webview-sessions-with-ios-9fe2199b44c9 STEPS TO REPRODUCE They don't exist, because the issue only happens at scale. We just know that no cookies are sent for a small percentage of requests. We believe this to be an issue in which Webkit fails to communicate internally with whatever IPC mechanisms it has. We have not been able to reproduce this issue consistently. The best we can give is that it happens after a few hours that the app is in the background. This happens regardless of whether the WKWebsiteDataStore is persistent or not, but seems to be much worse when it is persistent. Thus we have disabled persistnet data stores and relied on nonPersistent. The issue is bad enough that we are trying to move away from relying on cookies for iOS and just use request headers which we can only set on the top level request of WKWebView. DTS Case-ID: 13154329
Topic: Safari & Web SubTopic: General
2
1
239
Apr ’25
`WKHTTPCookieDataStore` cookie data loss and synchronization issues seen at scale
Hello, I am investigating a WKWebView cookie reliability issue with WKWebsiteDataStore.default() / persistent website data, and I would like to request a supported public API to force persistent cookie durability. We set persistent cookies from native code through the public WKHTTPCookieStore API: let dataStore = WKWebsiteDataStore.default() let cookieStore = dataStore.httpCookieStore await cookieStore.setCookie(cookie) The cookies have Max-Age / maximumAge set, so these are persistent cookies, not session-only cookies. Reproduction pattern: Use WKWebsiteDataStore.default(). Clear existing cookies. Set a persistent cookie through WKHTTPCookieStore.setCookie. After setCookie completes, terminate WebKit's NetworkProcess soon afterward. Create or reuse a WKWebView with the same WKWebsiteDataStore.default(). Load a same-origin page or trigger a same-origin fetch. I also have reproducible WebKit source-level test cases for this, in the style of TestWebKitAPI / WKHTTPCookieStore tests. The tests exercise persistent WKWebsiteDataStore.default() cookies, terminate the NetworkProcess after the cookie mutation, and then verify that a top-level load, same-origin fetch, and WKHTTPCookieStore cookie read can miss the cookie on an unpatched WebKit build. Observed result: The next top-level HTTP request, and sometimes a same-origin fetch, can omit the cookie that was just set. After the NetworkProcess is relaunched, WKHTTPCookieStore.allCookies() can also fail to show the recently set cookie. If I wait long enough after the cookie mutation before terminating the NetworkProcess, the problem disappears. In local simulator testing, this lines up with CFNetwork appearing to debounce/coalesce persistent cookie writes in an approximately 2-to-10 second window. That makes this look like setCookie completion means the current NetworkProcess / CFNetwork cookie store accepted the cookie in memory, but the persistent cookie backing store has not necessarily been written yet. If the NetworkProcess dies before that delayed write, the replacement NetworkProcess appears to reload stale cookie state from disk. This is especially painful for apps that bridge native authentication state into WKWebView. The app sees setCookie complete, assumes the cookie is ready, and then a later WebKit NetworkProcess termination can cause authenticated web requests to be sent without the expected auth cookie. We believe that, at scale, this is a mechanism causing a baseline of about 5% of our HTTP requests, as measured by HAProxy, to lack cookies that should be present. We know those cookies should be present because we duplicate the same values as URLRequest headers under different keys, and the headers are present while the corresponding Cookie header entries are missing. The API gap is that there does not appear to be a supported public equivalent of Android WebView's CookieManager.flush(). There is no public way for an app to say: "I just mutated persistent WKWebView cookies; please synchronously/asynchronously flush the persistent cookie store before I proceed." Request: Please expose a public flush API for persistent WKHTTPCookieStore / WKWebsiteDataStore cookies, for example an async API shaped like: try await websiteDataStore.httpCookieStore.flush() or: try await websiteDataStore.flushCookies() The important behavior would be: after WKHTTPCookieStore.setCookie / deleteCookie completes, an app can explicitly request durability; the flush completion should mean persistent cookie state has been handed to the backing persistent store, not merely accepted by the current NetworkProcess; if flushing is impossible because the relevant process/state is gone, the API should fail or report that, rather than silently succeeding; the API should be safe for App Store apps and should not require private SPI. Question: Are there any recommended supported patterns today for forcing persistent WKWebView cookies to reach durable storage after native WKHTTPCookieStore mutations? Is there an official supported way to force or observe cookie durability for persistent WKWebsiteDataStore cookies? If not, is the recommended approach simply to re-apply critical cookies before loads and tolerate NetworkProcess loss as unrecoverable app-side state? This issue is not just theoretical. It affects auth/session reliability when WebKit's NetworkProcess is terminated before the backing persistent cookie write completes. Apps can reduce unnecessary cookie churn, but without a flush API there is no supported way to close the durability window after setting important persistent cookies.
Topic: Safari & Web SubTopic: General
Replies
2
Boosts
0
Views
541
Activity
2w
Unable to load CSS fonts from WKURLSchemeHandler in a https website
I am trying to cache fonts natively in a hybrid app, so that CSS hosted in an https website loaded in WKWebView through loadRequest can reference them like this for a performance boost: @font-face { font-family: 'MyFont'; src: url('my-assets://Gordita-bold-subset.woff') format('woff'); font-weight: normal; font-style: normal; } The problem happens when I register a WKURLSchemeHandler for my-assets. The handler never gets called and the Safari Web Insepctor shows this: [blocked] The page at https://www.x.com/ requested insecure content from my-assets://Gordita-bold-subset.woff. This content was blocked and must be served over HTTPS. Interestingly enough, if we try to serve content with <img src="my-assets://test.png" this restriction does not apply. Are there any workarounds other than using the private API WKProcessPool._registerURLSchemeAsSecure?
Topic: Safari & Web SubTopic: General
Replies
1
Boosts
0
Views
100
Activity
Jun ’25
WKWebView randomly does not send out cookies from WKWebSiteDataStore to our servers
PLATFORM AND VERSION iOS Development environment: Xcode 16.2, macOS 15.3.2 Run-time configuration: iOS 15-18 This happens in iOS, and leads to to the hybrid home page showing users as wrongly unauthenticated, since the at cookie is missing. For context, we have a JWT token that is stored in the Keychain, and on app launch, before any WKWebViews are created, we synchronize this to the WKWebsiteDataStore as an at cookie. We have analytics instrumentation on our websitef to show that WKWebView randomly refuses to send out any cookies. – The following is a snippet from an explanation to the WebKit Slack: We are having an issue on iOS, in which WKWebView loads pages (and even subsequent reloads) without any cookies, even though we have stored cookies in WKWebsiteDataStore.default() before hand right after application launch and becoming a key window. We reference this object, store it as a singleton, (as well as a process pool), and then all webview configurations are initialized with the same data store, the same process pool, every call on the main thread. From reading the source code, it seems that if the internal IPC logic fails, the APIs for deleting and setting data records and cookies fail without any feedback in completion handlers. This bug often happens when returning from the background on iOS after a few hours. Sometimes it happens on cold launches of the app. We have mitigated a similar issue (no cookies being sent) by implementing webViewWebContentProcessDidTerminate and reloading the webview ourselves, we found that whatever webview does to reload if that method is not implemented leads to cookies not being used. There have been multiple reports of WKWebView losing cookies in recent iOS versions, and we have tried to implement all of the workarounds listed. Setting a maximumAge to the cookies we store, and doing a _ = await websiteDataStore.dataRecords(ofTypes: Set([WKWebsiteDataTypeCookies])) before accessing or modifying websiteDataStore.httpCookieStore Question: is it safe to work with WKWebsiteDataStore before a WKWebView is added as a view, if so are there any timing considerations? Are there any logs that we can take a look at, this issue is very hard to reproduce, about 2% of our users face it at scale? Is there anything that could be happening within our process (runloop issues, timing) that could be causing this issue? See multiple reports from other companies that have faced the issue: "Now the Thermonuclear Problem with WKWebViewDataStorage" https://medium.com/axel-springer-tech/synchronization-of-native-and-webview-sessions-with-ios-9fe2199b44c9 STEPS TO REPRODUCE They don't exist, because the issue only happens at scale. We just know that no cookies are sent for a small percentage of requests. We believe this to be an issue in which Webkit fails to communicate internally with whatever IPC mechanisms it has. We have not been able to reproduce this issue consistently. The best we can give is that it happens after a few hours that the app is in the background. This happens regardless of whether the WKWebsiteDataStore is persistent or not, but seems to be much worse when it is persistent. Thus we have disabled persistnet data stores and relied on nonPersistent. The issue is bad enough that we are trying to move away from relying on cookies for iOS and just use request headers which we can only set on the top level request of WKWebView. DTS Case-ID: 13154329
Topic: Safari & Web SubTopic: General
Replies
2
Boosts
1
Views
239
Activity
Apr ’25