I am desperately trying to add a custom cookie to a WKWebView
instance (without using Javascript or similar workarounds).
From iOS 11 and upwards, Apple provides an API to do this: The WKWebView
s WKWebsiteDataStore
has a property httpCookieStore
.
Here is my (example) code:
import UIKit
import WebKit
class ViewController: UIViewController {
var webView: WKWebView!
override func viewDidLoad() {
webView = WKWebView()
view.addSubview(webView)
super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
let cookie = HTTPCookie(properties: [
HTTPCookiePropertyKey.domain : "google.com",
HTTPCookiePropertyKey.path : "/",
HTTPCookiePropertyKey.secure : true,
HTTPCookiePropertyKey.name : "someCookieKey",
HTTPCookiePropertyKey.value : "someCookieValue"])!
let cookieStore = webView.configuration.websiteDataStore.httpCookieStore
cookieStore.setCookie(cookie) {
DispatchQueue.main.async {
self.webView.load(URLRequest(url: URL(string: "https://google.com")!))
}
}
}
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
webView.frame = view.bounds
}
}
After this, if I use webView.configuration.websiteDataStore.httpCookieStore.getAllCookies(completionHandler:)
I see that my cookie is in the list of cookies.
However, when inspecting the webview using Safari's developer tools (using a iOS Simulator of course) the cookie does not show up.
I also tried to inspect the traffic using a HTTP proxy (Charles in my case) to see if the cookie in included in my HTTP requests. It is not.
What am I doing wrong here? How can I add a cookie to WKWebView
(on iOS versions 11 and up)?
Since then, we've recommended that you adopt WKWebView instead of UIWebView and WebView — both of which were formally deprecated. New apps containing these frameworks are no longer accepted by the App Store.
A WKWebView object is a platform-native view that you use to incorporate web content seamlessly into your app's UI. A web view supports a full web-browsing experience, and presents HTML, CSS, and JavaScript content alongside your app's native views.
WKWebView is an in-app browser that displays web content. It doesn't share cookies or web site data with other WKWebView instances, or with the Safari browser.
The code above has no effect with the new web view since each WKWebView instance has its own cookie storage represented by WKHTTPCookieStore class.
A bit late but I want to share a solution that worked for me, I hope it helps someone facing the same issue on iOS 12 as well.
Here is the simplified workflow I used:
To do that I have created an extension of WKWebViewConfiguration:
extension WKWebViewConfiguration {
static func includeCookie(cookie:HTTPCookie, preferences:WKPreferences, completion: @escaping (WKWebViewConfiguration?) -> Void) {
let config = WKWebViewConfiguration()
config.preferences = preferences
let dataStore = WKWebsiteDataStore.nonPersistent()
DispatchQueue.main.async {
let waitGroup = DispatchGroup()
waitGroup.enter()
dataStore.httpCookieStore.setCookie(cookie) {
waitGroup.leave()
}
waitGroup.notify(queue: DispatchQueue.main) {
config.websiteDataStore = dataStore
completion(config)
}
}
}
And for my example I have used it as follows:
override func viewDidLoad() {
self.AddWebView()
}
private func addWebView(){
let preferences = WKPreferences()
preferences.javaScriptEnabled = true
preferences.javaScriptCanOpenWindowsAutomatically = true
let cookie = HTTPCookie(properties: [
.domain: COOKIE_DOMAIN,
.path: "/",
.name: COOKIE_NAME,
.value: myCookieValue,
.secure: "TRUE",
.expires: NSDate(timeIntervalSinceNow: 3600)
])
//Makes sure the cookie is set before instantiating the webview and initiating the request
if let myCookie = cookie {
WKWebViewConfiguration.includeCookie(cookie: myCookie, preferences: preferences, completion: {
[weak self] config in
if let `self` = self {
if let configuration = config {
self.webView = WKWebView(frame: CGRect(x: 0, y: 0, width: self.view.frame.size.width , height: self.view.frame.height), configuration: configuration)
self.view.addSubview(self.webView)
self.webView.load(self.customRequest)
}
}
}
}
Any request to google.com
redirects to www.google.com
.
You would need to add www.
to the domain field of the cookie. If the domain or the path doesn't match the request, the cookie won't be sent.
You can add the cookies explicitly.
let url = URL(string: "https://www.google.com")!
var request = URLRequest(url: url)
if let cookies = HTTPCookieStorage.shared.cookies(for: url) {
request.allHTTPHeaderFields = HTTPCookie.requestHeaderFields(with: cookies)
}
self.webView.load(request)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With