1

I'm trying to access my backend API using a URLSessionDataTask. Part of this includes accessing cookies stored using Safari.

For example, the php code in the backend for http://api.example.com/v1/getCookies is

echo $_COOKIE["myCookieName"];

The cookies do exist on iOS Safari, yet when a URLSessionDataTask request is made to the website

let url: URL = URL(string: "http://api.example.com/v1/getCookies")!

let task = Foundation.URLSession(
    configuration: URLSessionConfiguration.default,
    delegate: self,
    delegateQueue: OperationQueue.main
).dataTask(with: url)

task.resume()

Instead of the value of the cookie being sent as a response to the request, the response is that the cookie is unset. It seems as if cookies from URLSessions are separate than cookies in Safari.

The cookie is stored under the domain .example.com, and the path /.

Is there any way that I can access cookies set on Safari from my app? For example, I'd like something like this to work (I'm doing something more complicated, but this essentially shows what I would like to work)

  1. User visits example.com and chooses a nickname
  2. The user's chosen nickname is stored in a cookie
  3. The user decides to download the example.com mobile app
  4. The app makes a request to example.com, and the nickname that is stored in the cookie is returned

Is there any way to do something like this? neither HTTPCookie.cookies nor HTTPCookieStorage.shared.cookies seem to work.

Jojodmo
  • 23,357
  • 13
  • 65
  • 107

3 Answers3

2

Coockies can not be shared between different applications but in case you use a web browser inside your app it can be achived.

in case you want to intercept cookies from web view or SFSafariViewController in order to use them for other request via URLSession you should implement custom URL Protocol. See for more details https://www.raywenderlich.com/59982/nsurlprotocol-tutorial as result any request/response inside your app can be intercepted (even from web view or any URL sessions) and cookies and other headers will be available for you. For example, you can start the authentication from web view, intercept cookies from response and use them for other requests in your app.

Dmitry A.
  • 588
  • 8
  • 13
  • Thanks! Do you know of any way to put that view in the "background", so to speak, so that the user can still interact with the app and they don't notice anything? – Jojodmo Apr 29 '17 at 23:59
  • You can do this web view invisible. Load into it what you need and even forse it to run some JS on the loaded page. Even if this script does not exist in the page you can create JS script as String and using method evaluateJavaScript:completionHandler: run it. For example submit a form. – Dmitry A. Apr 30 '17 at 00:08
  • So, for example, I could create a web view, call the evaluateJavaScript method, and then immediately dismiss the web view, making it invisible to the user? And this would also work if the user did not have wifi or cell service, or were on airplane mode, correct? – Jojodmo May 01 '17 at 05:01
  • There is no need to make web view visible at all. It can be invisible from start. But in case your app does not have connection to network how to you want to send requests? – Dmitry A. May 01 '17 at 13:25
  • I phrased that weirdly... I tried something with a web view before this, and I was able to make it invisible, yet it was on top of the current view controller, so that if the user had bad internet connection they wouldn't be able to use the app – Jojodmo May 01 '17 at 14:11
0

Try with this configuration.

var configuration = URLSessionConfiguration.default
configuration.httpShouldSetCookies = true
configuration.httpCookieAcceptPolicy = NSHTTPCookieAcceptPolicy.OnlyFromMainDocumentDomain
A.Sen
  • 1
  • 2
0

I am not entirely sure this is what you try to achieve, but you can make a request with an ephemeral session:

Ephemeral sessions are similar to default sessions, but do not write caches, cookies, or credentials to disk.

This way the cookie won't be stored, and the server will therefore respond with a new cookie each time. Hopefully this will make it return the cookie you want inside the URLSession response. In code:

let task = Foundation.URLSession(
    configuration: URLSessionConfiguration.ephemeral,
    delegate: self,
    delegateQueue: OperationQueue.main
).dataTask(with: url)
Eric
  • 1,210
  • 8
  • 25
  • Unfortunately, that doesn't work either, and it's as if the cookies that were set using Safari no longer exist when accessing the webpage using a `URLSession`. – Jojodmo Apr 29 '17 at 23:43