I'm building an app that uses Single Sign On for users to log in. After the user enters a successful ID and password, the web side of things returns headers which I grab and store in my app. The WKWebView also sets a cookie that the user successfully logged in. This is what I want to avoid or undo.
The undesired behavior that I'm seeing is that if I log in a user, everything goes well, and then I log them out and go to log back in again, the WKWebView thinks the user is still logged in and takes them to an undesired URL.
In iOS 9, mitigating this is fairly simple:
let config = WKWebViewConfiguration()
config.websiteDataStore = WKWebsiteDataStore.nonPersistentDataStore()
let webView = WKWebView(frame: .zero, configuration: config)
However in iOS 8.4, making making sure the cookies are clear each time the user goes in to load the Single Sign On URL is more complicated.
I've tried approaches where I loop through cookies in NSHTTPCookieStorage.sharedHTTPCookieStorage() and remove them. Unfortunately, the cookie count is 0.
I've also tried removing the /Cookies directory in NSFileManager.defaultManager(). This also does not work.
One thing that kind of worked was doing the following. Although this approach didn't allow me to get the headers because a redirect after login needed to happen and this interfered (in iOS 9+ and 8.4)
req = NSMutableURLRequest(URL: url)
req?.HTTPShouldHandleCookies = false
let webView = WKWebView()
webView.loadRequest(req ?? NSURLRequest(URL: url))
I'd prefer to clear cookies in the deinit of my view that holds my WKWebView if that's a possible solution here.
This might be a longshot, but what about overriding the cookie accept policy to reject all cookies at the time of sign in?
NSHTTPCookieStorage.sharedHTTPCookieStorage().cookieAcceptPolicy = .Never
Another idea would be to manually mange the cookies with a custom WKProcessPool subclass (which is not really documented). I believe that's how Firefox manages any cookie issues.
Even if you mention it, is this the approach you've already tried in your deinit?
let storage = NSHTTPCookieStorage.sharedHTTPCookieStorage()
for cookie in storage.cookies! {
storage.deleteCookie(cookie)
}
Related
I am using 2 ViewControllers with 2 WKWebViews.
The WebViews use a shared WKWebViewConfiguration.
extension WKWebViewConfiguration {
static var Shared : WKWebViewConfiguration{
if sharedConfiguration == nil{
sharedConfiguration = WKWebViewConfiguration()
sharedConfiguration.websiteDataStore = WKWebsiteDataStore.default()
sharedConfiguration.processPool = WKProcessPool()
}
return sharedConfiguration
}
private static var sharedConfiguration : WKWebViewConfiguration!
}
I am passing this on each webView and from what I read this should be the solution for shared Cookies.
But because I am doing a login though the webContent I want to have the webViews SYNCHED if the user is logged in or not.
The problem happens when the user logs in. The steps that I follow are the :
1) I have identify the host and the path, and checking the navigationAction.request.url.host and navigationAction.request.url.path
when the user makes a request, and the request happens ONLY if the credentials are correct (So I know the correct host and path) I create a bool var that indicates that the users has logged in
2) After the WebView didFinish : FINISH , I call a func that reloads the webViews that have to get refreshed but the WebViews are not acting like they have the cookies.
3) after some seconds(different everytime) ,adding manual the code .reload() the web views in each preview , the webViews are synched.
I am working on iOS 9 since these are the requirements.
It looks that the cookies are asynced, and eventually they arrive to the shared processPool or websiteDataStore from my understanding.
Anyone have a solid solution?
You don't need to share same web configuration, you just need to share processPool and KWebsiteDataStore.default() after creating each webview configuration. To verify you can check cookies from Safari developer tool.
As #PS mentioned no workaround is working for him to sync cookies. I also encounter the same problem. but I tried some unexpected things to fix this issue and that is work 100%
Cookie sync takes some time to sync with cookie store for wkwebview. so my fix is just made dummy web request that will sync cookie on app start and after that, wherever you have to use your sign In or Sign Out call you can use without making any further modification.
I have a simple iOS Swift App
let url = URL(string: "https://www.mycustompage.com")!
webView.load(URLRequest(url: url))
In Info.plist I allowed all privacy-location permissions.
On https://www.mycustompage.com there is a HTML button which locates the user.
Now I have the problem that my app asks twice for the location permissions.
Once for the app and once for the WKWebView.
How can I disable the request for the WebView!?
Thanks
I'm guessing that this is because your webpage is asking for location and safari is basically another app running inside your viewcontroller. One way to bypass this is to simply not ask for the user location in your webpage. instead ask for the user location in the app, then inject then location into your webview with javascript using evaluateJavaScript(_:completionHandler:). Obviously you need to wait until you have both the location and for the page to be full loaded before you make the javascript call.
I'm using some WKWebViews within my apps.
Basically, I have a first WKWebView and the user should be able to create another one WKWebView without any cookies so he/she wouldn't be logged in any account he logged in before on the first WKWebView.
It's like an incognito browsing mode.
But I can't see anything that would allow me to do that with WKWebView.
I think it's not possible as this bug suggests :
https://bugs.webkit.org/show_bug.cgi?id=140191
But maybe someone found a workaround ?
Any help would be really appreciated.
After reading Apple's documentation, I finally got it to work.
I just initialise the WKWebView with a non-persistent WKWebsiteDataStore like that :
let configuration = WKWebViewConfiguration()
configuration.websiteDataStore = WKWebsiteDataStore.nonPersistentDataStore()
let webView = WKWebView(frame: CGRectZero, configuration: configuration)
I am developing iOS app that loads a webpage using UIWebView
The web page sets four cookies:
Two for Google Analytics, _ga and _gat
One for my web application unique vistors counter
One for my webpage to detect whether user has voted or not.
If this cookie available then display the poll results.
From Firefox's Storage Inspector I see all my cookies as expected, see screenshot:
However, from iOS I printed NSHTTPCookieStorage.sharedHTTPCookieStorage().cookies from inside webViewDidFinishLoad and there is only two of four expected cookies, also iOS users can vote as many times as they wanted because cookies are not detected (or not stored in iOS device):
if let cookies = NSHTTPCookieStorage.sharedHTTPCookieStorage().cookies {
for c in cookies {
print("*******************")
print("name: \(c.name)")
print("domain: \(c.domain)")
print("value: \(c.value)")
print("path: \(c.path)")
print("expiresDate: \(c.expiresDate)")
}
}
Why my iOS app does not detect my custom cookies and only detects my Google Analytics ones?
NOTE 1: I have also added this code to my app:
func applicationDidBecomeActive(application: UIApplication) {
NSHTTPCookieStorage.sharedHTTPCookieStorage().cookieAcceptPolicy = NSHTTPCookieAcceptPolicy.Always
}
NOTE 2: My backend is SharePoint web application
A few ideas:
The device's Safari "Block Cookies" settings override any changes to the cookieAcceptPolicy. The default policy of this setting on the device is "Allow from Websites I Visit," which depending on your iOS device's version, allows third-party cookies. Testing with iOS 9.3.x shows that third party cookies are persisted in a UIWebView with the default settings, but do not persist with the settings "Allow from Current Website Only" or "Always Block."
Check if the device persists your cookie with the different Safari cookie settings.
Additionally, does your cookie have an expiration date set? I've found that cookies without an expiration date set are treated as session cookies in a UIWebView, which only persist with the lifecycle of the web view that received it.
I have an app that uses Instagram Integration. The App has been in the App Store for a few months with multiple version all working fine. Suddenly, the latest version I submitted to Apple was rejected because apple doesn't like the fact that Safari is launched for a User to Login to Instagram. As per their words, they care about the user experience.
The problem is I need to request an Access Token and that is how I know it has to be done. Since my App was rejected, I can't be the only one who may have faced this so I thought I should ask. Does any one know of some other method perhaps I don't know of whereby you can authenticate a users Instagram and get the required Access Token, without Launching Safari?
EDIT #1: The only other option I can think of is to use a UIWebView within my app to open the Instagram authentication process. I tried this and it just seems to be mad slow and the callback process to my app doesn't seem to initiate. So I don't know if I'm doing something wrong.
EDIT #2: Doing more research as to why the Instagram login is not working in my UIWebView, it seems to be something with how the UIWebView handles Cookies, apparently it does not recognize Cookies or something along those lines. I still don't know what exactly to do to fix this, so if anyone has a solution please provide.
Looks like this is something that could help you. You haven't given many infos about your app so I can't think of something outside the box, but try looking into Instagram iPhone Hooks and see if you can use them to trigger login when the user does something.
I'm sure this can be optimized a little bit, I probably do not need the for loop. But either way, I've spent almost a day on this issue and just don't want to touch it anymore since I was finally able to get this to work by doing the following before loading the UIWebView:
var req = NSURLRequest(URL: NSURL(string: urlString)!)
var cookies = NSHTTPCookieStorage.sharedHTTPCookieStorage().cookies as! [NSHTTPCookie]
var reqCookies:[AnyObject] = []
for aCookie in cookies {
reqCookies += [aCookie]
}
var headers = NSHTTPCookie.requestHeaderFieldsWithCookies(reqCookies)
self.webView.loadRequest(req)