swiftcookieswkwebviewwkhttpcookiestore

How can I persists cookies across app restarts with WKWebView / WKHTTPCookieStore


I have a requirement to persist my cookies across application restarts.

Originally when using UIWebView I was able to achieve this with an extension on UserDefaults

import Foundation

extension UserDefaults {
    typealias CookieProperties = [HTTPCookiePropertyKey: Any]

    private static let cookieKey = "app_cookie_jar"

    func storeCookies() {
        guard let cookies = HTTPCookieStorage.shared.cookies else { return }
        let cookiePropertiesArray = cookies.compactMap { $0.properties }
        set(cookiePropertiesArray, forKey: UserDefaults.cookieKey)
        synchronize()
    }

    func fetchCookies() {
        let cookiePropertiesArray = value(forKey: UserDefaults.cookieKey) as? [CookieProperties]
        cookiePropertiesArray?.forEach {
            if let cookie = HTTPCookie(properties: $0) {
                HTTPCookieStorage.shared.setCookie(cookie)
            }
        }
    }
}

I would then call this in various life cycle methods

func applicationWillEnterForeground() {
    defaults.fetchCookies()
    ...    
}

func applicationDidEnterBackground() {
    defaults.storeCookies()
    ...    
}

However now my application is using WKWebView and I have the same requirement. I am currently sharing the cookie store between the different web views in my app by way of a shared singleton WKProcessPool

class ProcessPool {
    static let shared = WKProcessPool()
}

However on a restart, some cookies are not persisted. Mainly cookies that do not have an exp date and cannot be updated on the server to have one.

The extension above is using HTTPCookieStorage however I need to achieve something of the same fashion (or better) using WKHTTPCookieStore and am unsure how.

I was hoping to do something like this

func storeCookies() {

    let __cookies = WKHTTPCookieStore()

    __cookies.getAllCookies { cookies in
        ....
    }
}

But I do not believe WKHTTPCookieStore can be invoked in this way.

I am also very aware of the issues around sensitive data such as cookies in UserDefaults, this is not a production app and long before release will have this functionality removed and replaced with a proper, secure solution. This is sadly just where we are with the product at this point in time.


Solution

  • You need to access WKWebsiteDataStore first, this will give you access to the cookie store.

    func storeCookies() {
    
        let __cookies = WKWebsiteDataStore.default()
        __cookies.httpCookieStore.getAllCookies { cookies in
            print(cookies)
        }
    }