Is it possible to set a cookie in an iPhone Application that persists, so that later when the user is in Mobile Safari, that cookie can be sent to a webserver?
** Update 2017 **
A lot of changes to security mechanisms and cross-app communication were introduced to iOS in the recent years since this was first answered.
The below code no longer works on current iOS releases since Safari no longer accepts javascript:... in URLs and frameworks like NSURL catch these and return nil.
The one alternative that still works is to either host a website and have Safari open it or integrate such a HTML page in your app and run a small http server to host it on demand.
**iOS up to 6.x **
Since Apple has forced the sandboxing on all app store applications
there's currently no easy way to realize your request.
You could however open a special http://-URL from your application containing javascript to place a cookie:
NSString jsURL = #"javascript:function someFunction(){ /* your javascript code here */ } someFunction();void(0)";
[[UIApplication sharedApplication] openURL:[NSURL URLWithString: jsURL]];
Using javascript in URLs has been used by different iPhone applications to cross communicate
with MobileSafari (for example instapaper).
Another option would be to include a static HTML page in your app or on your server and instruct MobileSafari to open it.
The page in turn could set the permanent cookie.
Hope this helps!
I believe this is made easy by using the ASIHTTPRequest Library. It encapsulates the use of the global cookie store.
http://allseeing-i.com/ASIHTTPRequest/How-to-use
You can make requests with this library which will accrue cookies, and then these cookies will affect other requests later.
I use this to great effect in accessing authenticated APIs within my iPhone app.
The documentation for NSCookieStorage suggests that it would be such a mechanism. But whether "all applications" really includes Mobile Safari or not, your experimentation will have to determine....
See also the general documentation for the URL Loading System.
I'm new at iPhone development, but wouldn't opening a UIWebView allow your server to set a cookie on the browser so then when the user visits the site with Safari the cookie would be readable to your web server? Perhaps a hidden or small UIWebView? I can't tell what the use case is from your question.
Related
I have an application that may access authenticated content. I know that the webview can't handle authentication so I do some NSConnection magic to make it work (something similar to this)
The thing is that there is some content that can be accessible using this web view, but there is some other content that event after a sucessfull authentication, the web view is not able to load.
BUT.. if I enter the same url with mobile safari, enter the needed credentials and then I go back to my app, the WebView seems to load the content fine.
I tried reviewing the cookies before and after the auth in Safari is done using this code
[[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies];
and the cookies are the same.
As far as I understand that code will retrieve the cookies my app generates and not the ones available in iOS, so apparently this is not the way to look for a hint...
Any ideas?
Recently, i've lurked for the same question over the internet, and the answer is "no" =(.
Objects of UIWebView class and Safari or other browsers live apart and are sandboxed.
Here is official position about cookies.
TO the best of my understanding, Cookies can not be sent with the first request from a Webview, but can be sent with subsequent requests to the same URL, if and only if, the first request was successful.
This causes problems with authentication services that require cookies to authenticate on the first request to the URL.
Possibly user credentials are stored via keychain api. Keychain is shared between apps, so stored login/pass in Safari can appear in your app UIWebView.Can you elaborate this as i also need this.
I use asiHttpRequest library to do data get and post.
I have built a login function with it to login to my site, after that, if I launcher a URL from my app to use mobile safari app browse the site, it still remains not authenticated.
I guess the reason is that my app does not share the same cookie storage with safari, is that correct? is that possible I share the cookies with other apps, especially the Safari?
You can NOT share cookies in your App with Mobile Safari. As #erpayo said, it's in Sandbox.
Maybe add a UIWebView into your App is the best solution. Do not open an URL in Mobile Safari but open it in the UIWebView. It can get your cookies.
no, it's not.
Cookies are sandboxed.
Maybe you can make some server side tracking using query string parameters, but it will become a security hole
I am building a mobile app with jQueryMobile and I intend to deploy it onto iPhone thanks to PhoneGap.
My question is : how can I authenticate myself with Foursquare using the OAuth2 protocol in my jQueryMobile app ? One solution would be to use the useragent flow of OAuth2 but this would force the iPhone to launch Safari and thus not stay within the app. Are there any better solutions than this ?
For an iPhone-based or client-side application like you would have in PhoneGap,
Foursquare recommends one of these methods.
If you have no substantive server code, you can embed a web browser and use the token flow, redirecting the user to a dummy page on your domain. You can then grab the token off of the URL and close the browser. We have sample Android and iOS code for your reference.
If you have a server as part of your application, you can use the server flow above, possibly in an embedded browser. Similar to the Facebook API, you can add display=touch to your authorize or authenticate URLs to get a mobile optimized interface.
An alternative to the above is to use the server flow and an external browser, but redirect to a custom URI handler that brings the user back to our application. You can embed the secret in your application and exchange the provided code for an access token. PLEASE take steps to obfuscate your client secret if you include it in released code, and be prepared to rotate it if needed.
https://developer.foursquare.com/docs/oauth.html
This could probably be handled with the ClientBrowser plugin for PhoneGap or just adapting the sample code they have provided into PhoneGap plugins.
One of the core intentions of OAuth2 is to not allow browserless authentication flow like we did with XAuth in the past. Service providers want consumers to see what permissions they are signing off on, and want control of that process.
I'm not very experienced with Phonegap, as I'm a native developer, but if there's a way of instantiating a UIWebView and showing it to the user, you could at least keep the web interaction 'inside' of the application. Given phonegap is basically showing a UIWebView this should be possible. It is possible to examine the source of the html within a UIWebView using
- (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script
Maybe I'm missing something, but from Apple's documentation for NSHTTPCookieStorage, I can't help but wonder how this is safe to use.
Does this mean that cookie storage is shared across all apps on the iPhone? If my app makes an Http call that results in some cookies being saved, do all apps now have access to these cookies?
Methods like:
cookiesForURL: Returns all the
receiver's cookies that will be sent
to a specified URL.
make it look even more suspicious.
Can someone explain how this is OK, and what the class does?
Also, assuming my understanding is flawed and this is indeed sandboxed per-app, do calls made using NSURLRequest automatically save/retrieve cookies from this store or is it the developers responsibility to set request headers before dispatching the request?
Your application only has access to cookies within its own sandbox.
From http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/URLLoadingSystem/Concepts/URLOverview.html:
iPhone OS Note: Cookies are not shared by applications in iPhone OS.
I guess you're confused by the fact that you can access cookies from other domains/urls.
That's is technically true because your native app is "a browser" when you use UIWebView.
If you load www.siteA.com and www.siteB.com in your UIWebView, both domain's cookies are available to your objc code.
All apps, including mobile safari has it's own CookieJar and none of them can access the other one.
I'm trying to glue information from a web page to an iPhone app that said web page suggests to download. I control both the web page and the downloadable app.
Scenario is like this:
User visits my web page, on which I recognize the user (he may have logged in, and I store his info in a cookie). I then present a link to him to an app in the App Store that he should download for "enhanced experience" of this web service of mine.
Now, when the user launches the downloaded app on his iPhone, I like to re-identify the user who previously visited said web page.
All would be easy if an iPhone app could read Safari's cookies. But it can't.
A somewhat lame solution could be that the web server stores the visitor's IP address and uses that to recognize him once he launches the iPhone app. But that's not reliable.
Another one would be to give the user a token (code) that he needs to remember and then re-enter in the app. Still quite awkward, I think.
Any better suggestions?
Simply put, you can't do this.
One thing you could consider is a custom URL scheme to launch the app. You could send the user an email that uses this custom link. However there's a couple of problems with this:
the user may not have the account that they used to register for your site set up on their iPhone. This might seem unlikely, but say the user signed up for your site 5 years ago with their Hotmail account and they have since switched to Gmail.
it's unlikely that the email would fit into their workflow. They would probably download the app and just launch it by touching the icon instead of clicking a link in a received email.
You could also put the custom URL as a link on your web page, but again, this won't fit into the workflow because they have to go to the App Store app to do the download.
Consider this - if you've got some sort of website that has an authentication step, it's probably a fair bet to say that the user is the type of person who already has an application such as Facebook installed on their iPhone. They are already used to the paradigm of having to enter their credentials into an application despite the fact that they may have already done it in Safari.
If you could read the unique iPhone device ID from javascript on your web page, you could look for that again when the application connected...
But I cannot find any means of reading this from Javascript in Mobile Safari, I thought I'd post in case there is a way now to give you another option to consider.
OK, we found a somewhat working solution: The html code can create a cookie. Later, when the app runs, it can't directly read that cookie, of course (due to the sandboxing of iPhone apps). However, it can connect to the server, then open a http URL pointing to the server and including a unique token that it has gotten from the server beforehand. This leads to launching Safari, accessing the server. The server can now read the aforementioned cookie and finally establish the connection with the help of the token.
Just stumbled over this question and I'm curious if you thought about using a UIWebView.
Where the question is - does UIWebView share cookies with safari?
If it does the rest should be easy.
UIWebView's DON'T share cookies with Safari. So unfortunately that is not an option.