0

I have seen lots of questions and answers on how to permanently store a cookie in an iOS web application... But I can't seem to even get this one set.

The application runs beautifully in a real desktop browser, but fails when running inside of an iOS app.

I have a rails web service UI that the app communicates, but all of the app logic and code is on the client using Backbone, jQuery, etc...

A form submits the user login information to the web service via an AJAX POST:

$.ajax({url: 'http://mydomain.fake/login',
            type: 'POST',
            data: data,
            xhrFields: { withCredentials: true },
            success: successFunc,
            error: errorFunc});

The server then authenticates the user and FOR NOW sends back an encrypted permanent cookie with the user's identity:

def login
  @account = Account.find_by(email: params[:email]).try(:authenticate, params[:password])
  unless @account.nil? || @account == false
    cookies.permanent.signed[:user] = @account
    return head :ok
  end
  head :unauthorized
end

Connecting to the app with safari and checking the response to this call I get back the appropriate cookie header:

Set-Cookie  user=<encrypted string>; path=/; expires=Fri, 29 Sep 2034 01:50:31 -0000

Now when checking document.cookie there is nothing there. Looking on in the resources on the left of Safari, there are no cookies. And when refreshing, the same symptoms as above, and the application has no idea who the user is and returns them back to the login page...

Does anyone have any idea why the application cannot store the cookie. I am not closing and re-opening the application, so this is not an issue with the known (safari deletes the cookies on close) or (applications are sandboxed) or (an expiration time on the cookie has not been set). I am thoroughly confused.

UPDATE:

I added the CORS headers to the web server, though they seem not to be needed, but no difference was achieved. I'm still at a loss for how something that usually just-works isn't, and would love any help/pointers/links/anything that might help get me back on track. I am currently stuck.

UPDATE:

I switched from using jQuery to a phonegap plugin that uses native Obj-C to make a request to the server. The request succeeded, but still no cookie is set. I am convinced I am doing something very wrong here.

UPDATE:

I now have tried using jQuery cookie to set an encrypted string sent by the server and setting it that way. It works, but only if I don't set the domain on the cookie.

$.cookie('user', data.token, {
         expires: new Date(2014,12,31), 
         domain: 'localhost', 
         path: '/'});

I'm sure that this is a CORS security feature where you cannot set another domain other than the domain you are working on. But my test server is at localhost:3000 and my test app is running from localhost:63342 so I was setting the cookie domain to localhost. This wouldn't pass my desktop browser testing so I never did try it in iOS since I can't even get it to work here.

So I guess to modify my question How should I authenticate my users to the webservice and store something (like a token) so that I can identify users on subsequent visits...

Update: I do have these headers set in my web service. I set the Allow-Origin to another domain I own because I can't list out every origin of every user. Unless should it be set to localhost or something for them?

'Access-Control-Allow-Origin' => '<what should I put here>',
'Access-Control-Request-Method' => '*',
'Access-Control-Allow-Credentials' => 'true',
'Access-Control-Allow-Methods' => 'GET, POST, PATCH, PUT, DELETE, OPTIONS, HEAD',
'Access-Control-Allow-Headers' => 'Origin, Accept, Content-Type, Cookie'

Either way the webview produces no CORS errors, unlike actual safari or a desktop browser (even if I don't have them set at all).

SnareChops
  • 13,175
  • 9
  • 69
  • 91
  • I believe the Access-Control-Allow-Origin header response should be set (after being validated against your allowed list of origins) to the requested Origin – steve Jul 12 '16 at 00:03

2 Answers2

0

There are two possibilities here:

  1. Because the cookie is coming cross domain, you need to set "Block third-party cookies" to "No" in your browser settings.
  2. As you are getting the appropriate cookie in the header, it might be applied to the domain you are requesting. You could use the code from Cooper Maruyama in this question to make the cookie available to your domain.
Community
  • 1
  • 1
tnt-rox
  • 5,400
  • 2
  • 38
  • 52
  • I can't ask all of my users to set "Block third-party cookies" to "No", and it's also inside of a native app, not in safari or a browser. I am however setting the appropriate setting in the native iOS code for this with no result. As for the domain of the cookie, I need it to stay in the domain of which it was requested as this is the web service where the app will be retrieving all of its data. The native page domain is the phone itself, the app pages get served from file:// on the device. – SnareChops Oct 02 '14 at 13:32
  • @SnareChops indeed asking your users to not block 3rd parties is not optimal. If you are using jQuery to access the domain then you are using webview, which is an instance of safari. Did you try "Cooper Maruyama's" solution linked above? .. Also.. the data you are retrieving is from another domain, so the cookie belongs to that, other domain. – tnt-rox Oct 02 '14 at 13:38
  • Correct that webview is an instance of safari, and yes I want to keep the cookie in it's originating domain of the web service. This link above's solution was what I had attempted in my first update. Both using the jQuery.cookie plugin and vanilla js `document.cookie` – SnareChops Oct 02 '14 at 14:06
  • Ok.. 1 step at a time.. so just to verify you have the following headers set : Access-Control-Allow-Origin, Access-Control-Allow-Credentials and Access-Control-Allow-Methods. Make sure Access-Control-Allow-Methods has "POST, OPTIONS" – tnt-rox Oct 02 '14 at 14:18
0

you cannot reliably use cookies with phonegap. It really isn't worth pushing in that direction... Something to do with phonegap being special and its an app but not an app and if its really an app why would it use cookies because its not really a webpage anymore its a magical webview and I digress...

You're not doing anything wrong, its phonegap. It will not save cookies.

I assume you are using phonegap because you say you used a phonegap plugin in one of your updates..

Instead use localstorage or sessionstorage. In our app we use a combination of local storage and a XSRF-TOKEN we save there to keep our requests in check

window.localStorage.setItem("key", "value");

window.localStorage.getItem("key")

window.localStorage.removeItem("key")

and session storage, which will disappear when the app closes

window.sessionStorage.setItem("key", "value");

window.sessionStorage.getItem("key")

window.sessionStorage.removeItem("key")
  • Thank you very much! I greatly appreciate the explanation. I like the idea of having an XSRF-TOKEN. Would there be a way to use the Rails XSRF-Token generator to satisfy this? – SnareChops Oct 03 '14 at 14:46
  • Ours is generated on our Java run server and put into the header, I would see no issue in having the same done in Rails. –  Oct 05 '14 at 06:07