How to pass cookie to NSUrlSession? - ios

For iOS, I have written a custom delegate and implementation of NSUrlSession. It is working fine for Http urls. But when I try to download image resources from a HTTPS source that has been authenticated and which require a Cookie to be passed, the download fails with a NSUrlErrorCode -1013 or -1002.
NSMutableUrlRequest req = new NSMutableUrlRequest(new NSUrl(uri.ToString()));
req.Headers = dictHeaders;//
NSUrlSessionDownloadTask newTask = session.CreateDownloadTask(req);
activeDownloads.Add(newTask);
newTask.Resume();
So in the NSUrlSessionDownloadDelegate I have implemented the DidReceiveChallenge method but am not passing anything there currently because I want to pass the cookie from my initial login as above.
NSUrlSession uses shared session for the complete app but my initial login API is done using RestSharp.RestClient which fetches the cookie that I can use throughout the app.
So my question is how do I pass the cookie to NSUrlSession ?

As far as I know, all work with cookies goes through NSHTTPCookieStorage class https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSHTTPCookieStorage_Class/index.html. You can use cookieAcceptPolicy to configure how cookies are used in your application and even manually add/remove cookies if needed.
NSURLSession will take cookie from NSHTTPCookieStorage.

Related

WkWebView sometimes loses the session variable

I have a Ruby on Rails backend web application. I use iOS application as a web client (WKWebView) written in swift. The authentication token is stored as a session cookies variable on the backend:
session['token'] = generate_token
The problem is that accidentally this session variable is lost and the flow is redirected to login page.
The WKWebView is not closed, just used to process HTTP requests.
I'm not able to figure out, why this accidentally happens.
Since you are using just a webView and not default Safari browser meaning you are making your custom browser hence you are responsible to handle things like caching your token for the current session. My suggestion, if you want the token to be stored and used only once then create a variable something like
let accessToken = "your json web token"
Then pass it as a header when making a request to your server.
If you want to maintain access then you might want to save your token in keyChain or userDefaults depending on the level of security.
Navigation and other user interactions
As I mentioned, using wkwebView meaning you are making your own browser so you have to detect subsequent requests as the user interact with your web pages. For navigation, you have to use WKNavigationDelegate methods.
If WKNavigationDelegate does not solve your problem then you have to make use of Javascript events ie.. post an event when user visit a certain page and use WKScriptMessageHandler to respond to those events by passing the acess token etc..

In background NSURLSession why are secure cookies lost?

I'm developing an app that logs into a HTTPS website. After authentication, the website sends a final cookie that is marked as 'Secure'.
The app works when I use defaultSessionConfiguration() for NSURLSession().
When I change one line in the app to use the backgroundSessionConfigurationWithIdentifier() then I can't proceed past the authentication stage. I do get a webpage showing that I am authenticated but subsequent requests return the login page.
It appears that the "authentication successful cookie" is not present in the shared cookie storage.
This cookie is the only cookie that the website marks as "Secure". Note that this HTTPS website does all it transactions via HTTPS.
TL;DR
What does the NSURLSession background session do differently from the default session to lose a Secure cookie??
EDIT: I've done some more work.
When NSURLSession redirects using the backgroundSessionConfiguration it appears to ignore cookies that were sent in the Header of the redirect? (I think the cookie being "Secure" may not be critical.)
The redirect works correctly when the defaultSessionConfiguration is specified.
It turns out that this is a known bug. Apple r. 16,852,027.
The backgroundSession is known to ignore new cookies on redirect. The solution is to use a defaultSession to get the cookies and then continue using backgroundSession.
See Apple Developer Forum post

How to use AFNetworking to save cookies permanently forever, until the app is deleted from the iPhone?

Can someone please show me how to save cookies FOREVER using AFNetworking for iOS? I'm using ios7 but I think this should not matter?
The use case is that upon successful authentication with a webservice, it gives me two cookies that I need to pass along with every single request. These cookies never expire, or expire years from now. As long as I have the cookies with each HTTPS request, the user doesn't have to login again. I understand that AFNetworking automatically persists cookies until you quit the app, but I need the cookies to last forever until the user deletes the app from their phone.
1) Upon successful authentication, the webservice hands me two cookies. How do I access them? Do I go straight to NSHTTPCookie storage and grab the cookie by its name, or is there an AFNetworking "way" to do this?
2) How do I save these two magic cookies permanently so that my subclass of AFHTTPClient passes these two magic cookies along with each request? Do I just save them inside a keychain or NSUserDefaults or NSURLCredentialsStorage? Or again is there an AFNetworking way to do this? I read about a setAuthorization() method inside AFNetworking but I'm not sure if this applies to username/password and cookies as well.
3) How do I delete these cookies the AFNetworking way?
Thanks!!
AFNetworking doesn't do anything explicitly with cookies so there is no "AFNetworking way" of dealing with cookies. You'll work with NSHTTPCookie and NSHTTPCookieStorage.
In my projects I didn't need to do anything specific to the requests to get them to work with cookies. If you need different request behavior than AFNetworking provides by default, you override requestWithMethod:path:parameters: in your AFHTTPClient subclass.
To get the cookies returned from an AFJSONRequest, for example
NSURLRequest* request = <some request returned from your AFHTTPClient subclass>
AFJSONRequestOperation* op = [AFJSONRequestOperation JSONRequestOperationWithRequest:request
success:^(NSURLRequest* request, NSHTTPURLResponse* response, id userData) {
NSArray* cookies = [NSHTTPCookie cookiesWithResponseHeaderFields:[response allHeaderFields] forURL:url];
}
failure:...
This answer says to set an expiration date on the cookie. If you want to persist the cookies yourself, you can convert the cookies to a dictionary and save that. This answer says to use the keychain.
NSMutableDictionary* cookieDictionary = [NSMutableDictionary dictionaryWithDictionary:cookiePrefs];
for (NSHTTPCookie* cookie in cookies) {
[cookieDictionary setValue:cookie.properties forKey:cookie.name];
}
Remove the cookies from the NSHTTPCookieStorage. There is some trickiness to watch out for. If you've saved the cookies yourself, delete the stored values however is appropriate.
NSArray* cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookiesForURL:theUrl];
for (NSHTTPCookie* cookie in cookies) {
[[NSHTTPCookieStorage sharedHTTPCookieStorage] deleteCookie:cookie];
}

iOS6 getting and setting cookie to a UIWebView

I have a HTML5 web app using cookie for authentication. In iOS6 it face some problem receiving cookie from server that the outbound request will not have cookie inside header as before. I come up with idea to request session id from a http request, and put into some where (maybe NSHTTPCookieStorage?) and then all request from UIWebView will contain cookie, then most of the html5 code don't have to change..
Is it the correct way to go? if yes, how to implement this? thanks.

Does NSURLConnection automatically persist cookies sent from server?

I logged into my tornado backend from ios and sent back a secure_cookie and i noticed that i could also request other information as long as i validated the secure_cookie that i set. How long does NSURLConnection persist the cookie or will the cookie be deleted once they close the app?
This is mentioned in the Apple docs:
The URL loading system automatically sends any stored cookies
appropriate for an NSURLRequest. unless the request specifies not to
send cookies.
A few facets to your question.
To start with, NSURLConnection will, by default, manage cookies based on the settings for the device. It will save the cookies to the store and send them as appropriate (when the domain matches an existing cookie). This means if you make a request from a URL with a cookie saved in the cookie store, it will be sent. This explains the behavior you mentioned. Generally, with the default settings, the cookie will persist for quite a while.
This initial statement, however, maybe is not helpful for your needs. I am assuming you may want to have control over the expiration of (or keep around "forever") this secure_cookie field so your app does not have to authenticate further in the future.
In this case, NSHTTPCookieStorage is the place to look. This class will allow you to both retrieve:
[[NSHTTPCookieStorage sharedHTTPCookieStorage] cookiesForURL:[NSURL URLWithString:#"http://example.com"]]
and set:
[[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie] (plus setting up the cookie dictionary object)
Based on experience and the feedback of others online, you should note that the cookie storage is not always 100% reliable. If you would like to be sending a specific cookie and value to the server, you should store that value with your app (prefs or Core Data, for example), and reset the cookie with the appropriate NSHTTPCookieStorage at each startup.
You have to look into the cookie cache management from here
This will help you to better understand how the caching for cookie is handled.
There is another very good description, where it's mentioned that you can get the cookie from headers fields and then you have full control of it. If you want, store and use when application launched again.
I hope this should help you to solve it.

Resources