Safari on iOS 11.4 not sending cookies on POST requests - ajax

I've been using the same code for years and things have been working very well on every browser so far:
$.ajax({
url: '/test.php',
data: parameters,
dataType: 'html',
type: 'post'
})
However, since my users started to upgrade to iOS 11.4, those who use the Private mode of Safari are having an issue with "being disconnected" from my website.
This is because ajax POST requests aren't sending any Cookies, apparently. A whole new session is created as part of that POST request (new cookies created, etc).
However, that doesn't affect anything on the GET requests themselves. They stay with the same cookies (and therefore same session), even though new cookies were set as part of the ajax POST request. It's like those ajax POST requests are "sandboxed", not affecting anything else.
Any ideas? Is this a bug on Safari on iOS 11.4 ?

We worked through a similar issue and figured out that it was actually related to Service Workers. From what I can tell, it's a bug in the latest version of Safari's implementation of Service Workers that causes some cookies not to be passed on POST in Private mode. For now, we have disabled our Service Worker and site functionality has returned to normal for those users.
Not sure if this is your problem or not, but it sounds very similar. Hope this helps!

Related

Mobile device doesn't use cookie

For some reason the mobile authentication detection stoped working. When I access a location containing a form on my page, the form should call (via ajax) for additional information to fill the fields, the server returns depending on user authentification. It worked well for nine months, but stoped working for mobile devices, however it still works for desktop browser access. Mobile and desktop use exactly the same access route, arguments, urls, view function ... everything. The one difference that I noted (after some 8 hours on this issue) when I looked up the request.META, is that desktop sends cookie information, mobile doesn't. However cookies are enabled on mobile and desktop browser. I tested this with Chrome mobile and (a freshly installed) Firefox on mobile, the result is exactly the same.
How is this possible? Why does the form when initializing on desktop send the cookie info and when initializing on mobile don't send it?
Here is a previous version of this question (written before I noticed the cookie difference and thought it was an api issue) containing technical details that I don't consider to be relevant for the particular question of how does the same functionality behave some differently on mobile and desktop.
EDIT: I really don't know what code to show, but probably the ajax request could be relevant. I am really lost here. This is the react-js service I use to load form initials, it's the one that arrives without cookie information when send form mobile device, and with cookie if send from desktop device, to the server. I am not aware to have added anything or changed this in anyway in the past nine months, it always worked only like this:
loadFormInitials = (typ,genderRelevant,auth) => {
$.ajax({
url: UserConstants.BASE_URL+'elements/?item=setup&auth='+auth,
method: 'GET',
dataType: 'json',
success: (result) => {
var data = JSON.parse(result.initial_data);
FormActions.loadFormInitialsAction(data,typ,genderRelevant);
});
}
Mobile companies sometime alter HTTP requests with their heavy caching.
You'd probably want to try again with HTTPS requests, not sure it'll fix though.

if ios6 safari is caching ajax calls, is it caching passwords? security risk?

Following on from the thread
Is Safari on iOS 6 caching $.ajax results?
If io6 safari is caching the results from non unique ajax calls then it must also be caching the call itself. Would this then mean it is caching usernames and passwords in a login situation thereby posing a security risk?
Short version: If you're sending usernames and passwords over the wire in plaintext, you've already opened a huge security hole.
Long version: Browsers will cache based on URI, so if you're sending user/pass as GET variables, then yes it will cache and yes it is a security risk. However, even if the browser didn't cache this, you're still doing something wrong. A third party need only look at the HTTP header to see what the user/pass is.
If you are sending this as POST, it is a bit harder to find the username/password. The browser will not cache the request as the URL is always the same. However, it is still possible to read the content of the request and find the user/pass.
To be the most secure, use HTTPS and pass the values via POST. The entire HTTP request is encrypted, including the headers. However, the browser will still cache the URL, so using GET variables is still a bad idea.
Example from the jQuery documentation on using POST with ajax:
$.ajax({
type: "POST",
url: "some.php",
data: { name: "John", location: "Boston" }
}).done(function( msg ) {
alert( "Data Saved: " + msg );
});

Multiple AJAX posts to Web Service that returns value. Should I synchronize?

My website is sending ajax posts to my web service, and the web service in return will return a json and that json will be further use in success callback.
Now, here's my problem, when my website is sending multiple ajax posts, it seems that those json that the web service returned gets jumbled up.
I'm thinking on synchronizing either the ajax posts or the web service (REST)? I've read that you don't need to synchronize REST services, is that true? If synchronizing is the solution, where should I synchronize it? Will async: false in ajax synchronize the posts?
Thanks.
I thought about including some codes:
Web Service:
#POST
#Override
#Produces("application/json")
#Consumes("application/json")
public Customer create(Customer cust){
custManager.save(cust);
return custManager.getCust(custManager.getCount());
}
AJAX:
$.ajax({
url: custURL,
type: 'POST',
data: JSON.stringify(sdata),
dataType: 'json',
contentType: 'application/json; charset=utf-8',
success: function(json){
var cust = JSON.parse(JSON.stringify(json));
var newId = cust.id;
updateCustId(oldId, newId);
}
});
What it does is it post to web service the data of the customer, and the web service designates an id for it and it return it to the client to update its customer id. That's not it all, I'm also updating other tables that is reference to the old customer id to the new generated from server, and after updating these other tables, it also will be send to the web service. The tables I'm talking about is web sql, its queries too works asynchronously. So end result is sometimes the ids got jumbled up and the other tables were send to the web service but the customerid it used is still the old one (I've used callbacks, ensured that it needed to be updated first before it will be sent to the server).
making my ajax calls async: false to make them synchronous and not get jumbled together works.
I don't think your problem is asynchrony, specifically. It sounds like you have some bug in your web-service implementation. What you describe should work fine.
Multiple Ajax requests are completely independent. Back end servers should treat each request separately.
You may have a problem way back in having data shared between threads on your web-application, which is causing problems with simultaneous access to the same data. If so this is the point to fix, and (in the worst case), put a mutex around just the small bit of code that is doing the cross-contamination.
If you find that data is leaving the server okay, but it is corrupted in your application, then the bug lies there.
I would strongly advise against trying to mask what sounds like a significant back-end bug by making a whole chunk of your app synchronous. Fix the underlying corruption issue, if that issue is caused by something that just cannot be made thread safe, then lock just that tiny bit.
Your question about REST is a bit irrelevant. REST services vs other architectures don't change whether code needs to be synchronous or not. When you use Ajax, you are using the HTTP protocol, which is intended to be asynchronous and stateless. A web-application of any style that requires synchronous access by clients is a big red flag of something wrong, in my view.
Beyond that general advice, you'll need to ask specific code-based questions for more detail.

phonegap: cookie based authentication (PHP) not working [webview]

I'm working on a mobile web-app using sencha touch, HTML5 and phonegap as a wrapper.
I'm using PHP-Authentication (Cookie) and ajax-requests. Everything works fine on safari or chrome, but after the deployment with phonegap (webview) it does't work anymore...
Any help would be appreciated :)
Some more details:
All data for my app is loaded via ajax requests to my server component "mobile.php".
I use basic PHP-Auth to autenticate the user:
AJAX-Request [username, password] -> mobile.php
-> Session established (cookie)
All other requests if auth was successful
What's the difference between a normal safari website and the webview?
i figured it out:
you have to change the phonegap_delegate.m file and add the following to the init method:
- (id) init
{
/** If you need to do any extra app-specific initialization, you can do it here
* -jm
**/
//special setting to accept cookies via ajax-request
NSHTTPCookieStorage *cookieStorage = [NSHTTPCookieStorage
sharedHTTPCookieStorage];
[cookieStorage setCookieAcceptPolicy:NSHTTPCookieAcceptPolicyAlways];
return [super init];
}
it enables webview to accept cookies from ajax requests
If your Phonegap AJAX requests are not firing callbacks like they're supposed to, this may be the reason.
If the response you're getting attempts to set cookies and you haven't done Michael's fix then your (jquery) AJAX request will fail quietly -- neither success: nor error: callbacks will fire despite the fact that the server actually received the request and sent a response. It appears you must do this even if you don't care about the cookies.
I hope this helps someone.
I didn't care about the cookies but just spent a few hours trying to figure out why the callbacks didn't fire!
There is a solution that works on android too:
Install plugin https://github.com/wymsee/cordova-HTTP to perform arbitrary HTTP(S) requests.
Replace XMLHttpRequest with the plugin alternative (cordovaHTTP.get or cordovaHTTP.post):
cordovaHTTP.post("https://example.com/login", {email: 'xyz#example.com', passwd: "s3cr3t"}, {}, function(response) {
console.log('success');
console.log(response);
}, function(response) {
console.log('failure');
console.log(response);
});
The response will contain status, data and response.headers["Set-Cookie"], that can be parsed for name, value, domain, path and even HttpOnly flags ;-)
Said cookie can be saved in LocalStorage and sent in subsequent requests (see cordovaHTTP.setHeader() or header parameter of .get/.post methods) to simulate an authenticated user on a desktop browser.
Best ways to store get and delete cookie its working fine in my app which is on live
To store value in cookie
window.localStorage.setItem("key", "value");
To Get value in cookie
var value = window.localStorage.getItem("key");
To Delete cookie value
window.localStorage.removeItem("key");
window.localStorage.clear();

Can you reliably set or delete a cookie during the server side processing of an Ajax (XHR) call?

I have done a bit of testing on this myself (During the server side processing of a DWR Framework Ajax request handler to be exact) and it seems you CAN successfully manipulate cookies, but this goes against much that I have read on Ajax best practices and how browsers interpret the response from an XmlHttpRequest. Note I have tested on:
IE 6 and 7
Firefox 2 and 3
Safari
and in all cases standard cookie operations on the HttpServletResponse object during Ajax request handling were correctly interpreted by the browser, but I would like to know if it best practice to push the cookie manipulation to the client side, or if this (much cleaner) server side cookie handling can be trusted.
I would welcome answers both specific to the DWR Framework and Ajax in general.
XMLHttpRequest always uses the Web Browser's connection framework. This is a requirement for AJAX programs to work correctly as the user would get logged out if the XHR object lacked access to the browser's cookie pool.
It's theoretically possible for a web browser to simply share session cookies without using the browser's connection framework, but this has never (to my knowledge) happened in practice. Even the Flash plugin uses the Web Browser's connections.
Thus the end result is that it IS safe to manipulate cookies via AJAX. Just keep in mind that the AJAX call might never happen. They are not guaranteed events, so don't count on them.
In the context of DWR it may not be "safe".
From reading the DWR site it says:
It is important that you treat the HTTP request and response as read-only. While HTTP headers might get through OK, there is a good chance that some browsers will ignore them.
I've taken this to mean that setting cookies or request attributes is a no-no.
Saying that, I have code which does set request attributes (code I wrote before I read that page) and it appears to work fine (apart from deleting cookies which I mentioned in my comment above).
Manipulating cookies on the client side is rather the opposite of "best practice". And it shouldn't be necessary, either. HttpOnly cookies weren't introduced for nothing.

Resources