i have a ionic 6 app with angular and i'm using external APIs to login user and retrieve some data.
When the user authenticates, the server responds with a Set-cookie header; everything works fine both on browser and android application.
On iOS looks like the set-cookie header received in the response is doing nothing.
I'm trying also to use cordova-plugin-wkwebview-inject-cookie on my app.component.ts:
this.platform.ready().then(() => {
if (this.platform.is('ios')) {
wkWebView.injectCookie(environment.config.baseUrl, '/');
}
});
but the cookie is not stored, so every next request get 401 response:
After a lot searching about this problem, I found this thread in capacitor github issues;
Long story short: It's not an problem or issue, actually it's a security decision take by Apple, like Thomas Vidas said in the same thread here:
It's several things, the main one being it was a deliberate change from Apple on iOS 14 and up called "Intelligent Tracking Prevention" (ITP) which disables all cookies on domains not listed as an App Bound Domain. It's not due to the capacitor:// protocol. ITP made it so document.cookie calls were intended to silently fail to prevent user tracking. If your server.hostname and App Bound domains are set up properly, it may work but could have other unintended consequences (such as Apple potentially rejecting your app) so we don't recommend it.
So, I recommend you to read the entire thread to get some insights, because it's a think that capacitor team doesn't have a solution.
I hope it will help you!
Related
We now know this is an issue with IOS 11.3, and seems to target only Ipad.
When requesting ressources through appcache, the cookies are discarded. If your ressources are behind some authentication. They will be redirected to your authentication page.
As mentioned by Apple, we tried experimentation feature on/off.
Removing authentication for ressources is not a valid permanent option.
We are looking for solutions while the next version of IOS hopefully fix this problem which seem the case with 11.4 beta 2. Changes are to be as minimal as possible to reduce risks.
Following informations are the process we when through when trying to solve our problem. To this day, no valid solutions have been attempted. Service Workers being the most plausible path.
Day 1
We have an application which was running fine in production for a while (almost a year since last deployment).
Our application use app cache to enable offline mode when wifi is not available.
Our application is mostly used on ipad with safari and some surface pro with chrome. Currently most cases are reported with ipad.
In the last few day, more and more users start to have problem loading the cache. We have been able to reproduce the probleme on an ipad after updating to 11.3 (could not reproduce on iphone 11.3) and using google chrome desktop incognito mode on dev machine. Application work on an older iPad we have which is at version 10.3.3.
--Application Cache Error event: Resource fetch failed (2) http://localhost:63330/client/vendor/kendo-ui/kendo.all.js--
Fact
- It always block on the same files, after some testings it seems to be all files bigger than 1.2Mb, in this case kendo is 4.7Mb and the minified one is 1.7Mb.
- Fiddler does not report any error, all files status response is 200
Guess
1. An update to safari and chrome might have changed
2. An ipad setting might have been changed by admins
3. An update to windows or ios, might have changes something
Since safari and ios follow the same release (29 Mar 2018), they are probably linked and the most likely guess, does anyone have an idea why this might happen?
Could not find much on apple support page of changes for 11.3
https://support.apple.com/en-ca/HT208067
https://support.apple.com/en-ca/HT201222
Update Monday 9 april 2018
We have been able to reproduce the issue both by debugging an Ipad and on the mac mini we have. However, the problem is different and for this reason we currently discarded what we found on Chrome on our desktop in incognito.
Here are the new facts:
Cookies were not provided while downloading file with appcache. The first file request is rejected and redirected to login page.
[Warning] ApplicationCache is deprecated. Please use ServiceWorkers
instead. (192.168.0.152, line 2)
[Error] Failed to load resource: the
server responded with a status of 401 (Unauthorized) (cache.manifest,
line 0)
[Error] Application Cache manifest could not be fetched,
because the manifest had a 401 response.
[Error] 2018-04-09 12:01:51 :
APPLICATION CACHE error
logMsg (logDecorator.js:111)
error (logDecorator.js:128)
(fonction anonyme) (applicationCacheUpdateSrv.js:121)
dispatch (jquery-1.10.2.js:5109)
handle (jquery-1.10.2.js:4780)
- After effect of solving authentication, we have problems with IDBDatabase, might be related to Authorization we removed (currently under investigation)
IndexedDB request error (get all rapports) -> NotFoundError: Failed to
execute 'transaction' on 'IDBDatabase': One of the specified object
stores was not found.
We found this by using Charles Proxy for Mac. For this reason, we removed authentication to our statics files and Home page. This seems to work, but our files would be public which is not really an option.
Similar questions:
Cache-Manifest How to handle authentication cookies?
Update Monday 10 april 2018
IndexDB error are not related. Databases were not initialized properly due to authorization missing.
We currently added an alternative home page where authorization is not required instead of removing authorization from the default home page. It would be called by the manifest cache and downloaded properly.
Update Monday 12 april 2018
We tried to secure the static files, we ended up with adding a token in the query url. While it work and we can authenticate the request (note that since we do not have cookies to authenticate the user, the authentication is far from flawless), the Url is now different than what was requested in the cached Home page and make the custom authentication worthless by itself.
We would need to also rewrite all the url for the cached page base the token genereted by the user. In our cases, it involve throwing out the ASP.Net MVC Bundle feature to maybe make a custom one? At this point, we think it might just be easier to try ServiceWorker since appcache is deprecated. This does not guarantee cookie will be passed on with ServiceWorker...
Update Monday 19 april 2018
We had some return from Apple yesterday. They asked be try Prevent Cross-Site Tracking property (both on and off) in Settings > Safari and also try Experimental feature in Settings > Safari > Advanced > Experimental (mentionning ServiceWorkers, but tried them all)
Unfortunately it didn't change anything for me at the moment.
Note: strikethrough some part that were not related directly to the issue
Update Friday 25 may 2018
Added a section to the top to resume the situation and make the question more to the point.
As of 25 april 2018, we tried iOS 11.4 beta and it seem to resolve the issue. According the the deployement timeline, it should be available in about a month according to this.
However until then moving to service workers might be a good idea.
Here is an example from google.
Here is a video which gives an introduction to the subject
I will add an example if we get to move to Service workers
I tested Universal Links in iOS by turning on Airplane mode and saw that the correct application was opened (instead of a website)
This indicates some level of "caching" the apple-app-site-association.
I want to determine the extent to which this is cached, so I can determine
What UX edge cases are there (e.g. Offline for x days)
What security considerations are there (e.g. MITM / SSLStrip + .well-known/URL)
etc.
Ideally I would like to have details if additional logic is employed (conditional caching if HTTPS employed, DNSSec, etc)
The exact behavior here is (intentionally?) unclear from Apple. Here is my personal experience, gleaned partly from official documentation and partly from helping thousands of apps implement Universal Links at Branch.io.
The apple-app-site-association file is cached once when the app is first installed.
If this initial scrape fails, in almost all situations it will not be reattempted. The only exception to this is if the initial return is a 5xx error, in which case a limited number of retries may occur. This is not well-documented, and is not covered in Universal Links documentation at all. You can find a mention in the Shared Web Credentials docs.
The file is not checked at all when a Universal Link is opened. This is why you are able to get Universal Links behavior in airplane mode.
The file does not expire. Once it is cached, it sticks permanently for as long as the app is installed.
The file will be re-checked when installing an app update.
The file must be accessible via a valid SSL connection at either https://example.com/apple-app-site-association or https://example.com/.well-known/apple-app-site-association. If there are redirects of any kind, this will fail.
It is theoretically possible to MITM the request if you are able to install a new SSL certificate directly on the device in question. Charles Proxy for example uses this approach for debugging. I have never seen or heard of this being exploited, and the damage would be quite limited because the domain still has to be specified inside the app itself.
I found a way to get around the caching issue. The cache is bound to the domain name, so for every time you want iOS to request apple-app-site-association you can create a new subdomain, and configure iOS to use that subdomain as the universal link for your app.
Extremely hacky, but it is the only workaround that worked for me.
I am developing app. It includes login page. After login I receive the response json. I tried the login multiple times with two different accounts.
Lets say account A & B. If I build and run fresh build on device and login with account A. I get the correct response. If I logout and re-login with the account B. In this case, I get the old response of the account A.
The problem remains if I do vice-versa. There is no issue with the web services.
I need to know whether there is issue with response caching in ios. I tried to implement this with the NSURLConnection, NSURLSession, and AFNetworking. The problem stays.
I have implemented the same for the android device. no response issue on android.
Can anybody suggest anything on this situation. Any suggestions are highly appreciated.
NSURLCache has no notion of accounts. You'll have to either tell it to remove all cached items or disable caching. Realistically, caching JSON responses is almost never the right thing to do, so you should probably disable caching for those requests.
I have been serving some mp3s to a small community for years just by linking straight to the MP3 and letting the device's browser handle the playback. All worked fine until users updated their iPhones to iOS 8. Now playing MP3's natively doesn't work. After lots of testing I seem to have narrowed it down to the use of .htaccess.
Here are two identical directories with the same mp3 and directory listing software in them. But one is password protected (U:music P:access).
Normal: http://danielmee.com/dl/
Secured: http://danielmee.com/dl-secure/
I've also tried using a JS player which also broke once behind the secure directory.
What changed in iOS 8 to disable MP3 playback and is there a way to fix it?
The hoops that iOS goes through to play a music file are interesting, to say the least. Looking at a packet trace, the credentials are sent properly for the initial request of the file, but the subsequent partial requests do not have credentials. This is likely a bug in Safari; if you get a free developer account with Apple, you can report the problem to them.
HTTP authentication works this way: the browser makes a request for a resource; the server responds with "401 Authorization Needed" and includes a WWW-Authenticate header indicating the type of authentication — in your case, basic — and the "realm" which is just a way of grouping protected resources. The client re-requests the same resource, adding an Authorization header that contains the username and password — in the case of basic auth, it's just base 64 user:pass. Typically, the browser will cache these credentials and send them without being asked, for every subsequent request within the same realm.
I would like to have my native iOS app send a request with a parameter to a Facebook user on iOS. If they accept, it will launch my native iOS app and pass it the parameter. Is this possible?
I am having marginal success using [facebook dialog:#"apprequests" andParams:dict andDelegate:self]. I am getting the bookmark counter to increment on Facebook iOS app, but I do not see the individual requests. If I tap the bookmark it launches my app but I do not see how I can get the "data" parameter I passed with the request, or even the request_id.
On desktop I see the individual messages under "Requests" section of "Apps and Games". If I accept a request, I can see it pass the request_id to my (simple echo) canvas URL. I read this can be used to fetch the associated data. But, this does not help me on iOS. My app only runs on iOS, so this canvas app will eventually just be a "this app only works on iOS," but it seemed to be necessary to get the requests to flow.
Neither of these are showing me Notifications, so maybe I am doing something basic wrong. Or, is there some other way to pass a message to a Facebook user, with a URL they could click (to launch and feed my app its parameter).
One other odd thing, I do not see how to get rid of the Requests. If I "X" them on the desktop client, it asks me if I want to stop receiving all requests from my app, and if I say no, it only hides them temporarily.
Leif, Hi - I'm the engineer at Facebook who wrote the tutorial you've referenced.
I've taken a look at the issue you've mentioned - this is in fact not a bug in the documentation and is by design.
The incoming url from a request on iOS looks something like this:
fb480369938658210://authorize?expires_in=3600&access_token=BAAG05NeN86IBAC31YWMWRHVrNCAYMy0Rv1OtqZCwdH8QDBUAt5KgZCsIbU0EOZAvMms2tZCANV9sZBWSkEzStDtt4i7YnYZA4bPgGx2XaI5s22iBMxIZAneZAv7ADi3Wi20ZD&target_url=http%3A%2F%2Fm.facebook.com%2Fapps%2Ffriendsmashsample%3Ffb_source%3Dnotification%26request_ids%3D364209433669109%252C379616028785376%252C494409170593789%252C489782271042929%252C328564930575784%26ref%3Dnotif%26app_request_type%3Duser_to_user
This is bundling together several requests, with multiple request ids into a single url.
To get the extra data coupled with this request, it is not required to have the user_id. Hitting graph.facebook.com/*request_id* is enough.
You can actually see this outlined in the documentation here: https://developers.facebook.com/docs/requests/#deleting under the 'Request ID Format' heading.
The code contained in the Friendsmash sample and on the tutorial works correctly - I verified it just now. So it should serve as a good guide to the OP's question.
Thanks!
I have been struggling with this too.
First, the FB iOS SDK requests tutorial is a good start.
However, there are also a few bugs that makes things not work as expected:
It seems that currently, a mobile web url has to be set up for the FB app in order for requestIds to be forwarded from the native FB app to your native app. See this bug report.
The tutorial mentioned above uses an erroneous graph path for the request object. I uses "request-id" where it should be "request-id"_"user-id". I have filed a documentation bug report on that issue.