Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SFSafariViewController Remove OAuth2 Cookie

I have an iOS application that authenticates with Uber API using OAuth2 in a UIWebView. When upgrading to iOS 9, I run in to the issue of ATS blocking the https request for the login page. I then added an exception for the Uber login page, but then noticed the login page makes several other requests to Facebook, Amazon Web Services, and other websites, all getting blocked by ATS.

I don't want to have to maintain a list of exceptions for the the Uber login page, as Uber can easily change their page and my app won't have the correct exceptions. So I decided to give SFSafariViewController a shot.

I am able to complete OAuth2 process with the SFSafariViewController, the problem is there is some type of cookie being stored from Uber when the authentication completes. If I want to authenticate a different account and I bring up the SFSafariViewController again, the cookie is picked up from the previous authentication, and there is no chance to authenticate a different account. I got around this with the UIWebView by deleting the cookie through NSHTTPCookieStorage, but I don't see a way to delete the cookie from SFSafariViewController.

like image 589
duncanc4 Avatar asked Sep 22 '15 16:09

duncanc4


2 Answers

For iOS 9 and onwards the best choice is to use the WKWebView class available in the WebKit Framework

which provides a WKWebsiteDataStore that can be used to delete cookies/caches used by the webview, see for example: https://stackoverflow.com/a/31803708/313113 or https://stackoverflow.com/a/32491271/313113

According to the docs: SFSafariViewController shares cookies and other website data with Safari and because it runs outside your app's process (for security reasons) you cannot modify it's state from inside your app. See this answer: https://stackoverflow.com/a/34136074/313113 from someone who contacted Apple customer support and got the following reply:

SFSafariViewController runs outside of my App's process and in order to be secure my App can not modify SFSafariViewController's state. In other words, my App can not clear credentials stored by SFSafariViewController.

like image 88
Alex Bitek Avatar answered Nov 18 '22 12:11

Alex Bitek


So I ran into this same issue and saw your question when searching for how to solve this. In my case the best solution I came up with was doing the logout stuff for in the app and then presenting a SFSafariViewController pointed at our logout url. I then used this to close the SFSafariViewController as soon as it was done loading:

extension AlertsTableViewController: SFSafariViewControllerDelegate {

    public func safariViewController(_ controller: SFSafariViewController, didCompleteInitialLoad didLoadSuccessfully: Bool) {
        if controller == logoutSVC {
            controller.dismiss(animated: false)
        }
    }

}

I stored the SFSafariViewController in logoutSVC so I only run this code if this is the logout SFSafariViewController. In your case it sounds like you just did an API call to revoke the OAuth token which is a little nicer since it doesn't show to the user at all but this is good for instances where you don't have such access. One more thing, for some reason I had to call the dismiss(animated: false) method on the SFSafariViewController instead of actual current UIViewController for some reason. Took me a sec to figure out why it wasn't working for me.

like image 3
Brian F Leighty Avatar answered Nov 18 '22 10:11

Brian F Leighty