iPhone Safari request doesn't send cookie - javascript

Lets say I have an application on foo.com domain.
I am doing user authorization to api.boo.com using the Fetch method with credentials flag as include and CORS set as well.
After successful authorization I am getting a session cookie. I need that cookie to have an access to another API's methods on api.boo.com domain.
This flow works fine on almost every browser. The problem is on iPhone's Safari. Safari has default option (Settings -> Safari -> Block Cookies) setted as "Allow from Websistes I Visit" with this configuration Safari doesn't send the session cookie when I am calling another API's methods so it looks like I am unauthorized.
The simplest solution is to change the cookie policy to "Always Allow". After that a session cookie is being sent. However, I can't ask every user of my application to do that.
Do you have any ideas how to make this flow working properly on iPhone's Safari?

Related

Auth cookie dissapears after login over HTTPS

I have application written in asp.net MVC (NetFramework 4.7.2).
When I enter my credential and click Login button
POST to login page return 302 (with auth cookie)
REDIRECT to action returning dashboard (with auth cookie)
Everything works over HTTP, I can use my application.
But over HTTPS after dashboard is loaded auth cookie dissapears (there is no code on JS, maybe browser do it). Cookie has enabled flags HttpOnly and Secure. I use the newest Chrome to browser my app.
It's probably related with console error
Clear-Site-Data" header on '': Unrecognized type "*"
I don't why it is added, I never have such header in code. Is it possible to browser do it?
If the browser drops the cookie it will usually write a message to the dev console about why it is dropping it. Most browsers are very specific about the reason for dropping cookies.
In your case, there seems like the response contains this header: Clear-Site-Data. It's a standard header: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Clear-Site-Data The backend must be returning this header for some reason. Then the browser correctly drops the cookie as instructed.
It's interesting though, why the browser complains about the asterisk value. According to the docs this is one of allowed values for this header.

Cookies are set into different domain (Node.js, Angular)

I am doing web app using Angular and Node.js (Express) and I have a problem with cookies - they are set into my backend domain instead of my frontend.
When I make a POST request to /auth endpoint, server will return HttpOnly cookies - one is JWT and the second is refresh token. When I inspect network tab in chrome, I can see that server sent these cookies back, but when I inspect Application > Storage > Cookies, nothing is here.
I find out, that cookies are set on my backend domain. (app-backend.com instead of app.com) They are just simply associated with my backend domain.
Wierd thing is, that my app is working just fine on my computer, but when I switch to my phone, cookies are not sent from there (I am using iPhone with Safari or Chrome). Also, when I ran my app on localhost dev server, everything worked aswell.
I tried to set domain in cookie config to my frontend domain, it is not working at all.
Also, Chrome warns me with this message, I don't know if it has anything to do with my problem
A cookie associated with a cross-site resource at "my-domain" was set without the SameSite attribute. A future release of Chrome will only deliver cookies with cross-site requests if they are set with SameSite=None and Secure. You can review cookies in developer tools under Application>Storage>Cookies and see more details at https://www.chromestatus.com/feature/5088147346030592 and https://www.chromestatus.com/feature/5633521622188032.
Here is my code on github:
Frontend: https://github.com/TenPetr/dashboard
Backend: https://github.com/TenPetr/dashboard_backend
Thanks for your advices.
You are setting the SameSite=None; Secure attributes in your production.json which is correct. However, depending on your version of iOS / Safari you may be hitting an incompatibility issue where the cookies are incorrectly treated as SameSite=Strict.
In your development set-up you are both: not setting SameSite=None; Secure, and might be using URLs that count as the same site anyway, e.g. serving on localhost can lead to some weird cookie behaviour.
I would try testing your production configuration without the SameSite=None attribute. If this then starts to work on Safari, then you are hitting that bug. You can mitigate this by either setting two versions of the cookie, or adding useragent sniffing. There are more details on https://web.dev/samesite-cookie-recipes
Alternatively, you may be hitting Safari cookie policy issues if you are attempting to set cookies from the back-end server when it's not a site the user actually visits.

Cookies don't show up in developer console of Safari/Chrome with Set-Cookie Header, but exist when looking at server logs

I am storing cookies for my web app using the 'Set-Cookie' header response from my python backend.
Here is my ajax call on the client-end to the function:
In developer tools in Chrome and Safari, when I look for the cookies, the cookies don't show up.
On Chrome, the Set-Cookie doesn't even show up in the response header to the network call.
In Safari, the Set-Cookie response header shows up and shows under request/response cookies,
but when I check cookies for the application, nothing shows up.
Furthermore, the cookie data shown in Safari is incorrect: it shows an incorrect expiration date and httpOnly/secure which should both be true.
The cookies seem to not exist, but when I log the server, I see clearly that the cookies exist and they appear
(also safari shows them going back and forth in the request/response headers)which means that the cookies are being properly stored and sent back to the server after every call in the header. I tried earlier to set httpOnly to false and secure to false, but even then the cookies exhibited the same behavior.
These cookies are still under the radar of both developer tools. How can I see the cookies on the browser in developer tools correctly? And what could this problem be?
Have you tried opening a tab to the server https://*.amazonaws.com and checking there instead?
The cookie will be set on the server's domain, but you won't see it in your local server's cookie storage. The reason is that all web storages are bound by same origin policy and your document can only access storages from its own domain, and the server can only set cookies for it's domain.
The rationale here is that if I sent you a link to a rogue document, it can't exfiltrate your SO cookies even if they were accessible from JS, neither sending a request to a rogue server can overwrite cookies on SO.
Try to disable chrome://flags/#network-service and it should work properly.

Samsung internet CORS only sends OPTIONS request

When using the "Samsung internet" browser on an Android device, it fails to do Ajax (some work) requests. After some debugging I saw that the browser only sends the options request (which succeeds) but does not send the corresponding post request afterwards.
You can try yourself by visiting my Dev site, select ok on the confirm prompt, click on login and try to login with random data
https://dev.gameplaylan.de
As mentioned in the comments, it seems like the Samsung internet browser doesn't handle wildcard access-control headers.
So I need to switch to an explicit list...

MobileSafari won't send back Cookies set with CORS

I have a page loading up in MobileSafari which communicated with another server via CORS.
In desktop browsers (tested Chrome and Safari), I am able to log in, get a session cookie, and have that session cookie be sent back for subsequent requests so that I may be authenticated with all API calls.
However, when I login via Mobile Safari, the cookie does not get sent back on subsequent requests.
I'm using Charles Proxy to spy on what's going on, and it tells me:
POST https://myremoteserver.com/sessions.json passes up my login info
It succeeds and response is received with a valid Set-Cookie header.
GET https://myremoteserver.com/checkout.json is requested, without a Cookie request header.
Server responds as if I am not logged in.
I'm using this snippet with Zepto.js to ensure that the withCredentials: true is properly setup on the XHR object. (pardon the coffeescript)
# Add withCredentials:true to the xhr object to send the remote server our cookies.
xhrFactory = $.ajaxSettings.xhr
$.ajaxSettings.xhr = ->
xhr = xhrFactory.apply(this, arguments)
xhr.withCredentials = yes
xhr
And that snippet works great in desktop browsers, and before I added it I was not able to preserve the session cookies in those desktop browsers.
Is there some quirk in MobileSafari that prevents this from working like desktop browsers? Why does it not work in the same way?
Edit!
here is my CORS headers setup in my rails 2.3 app, fairly standard stuff I believe
def add_cors_headers
if valid_cors_domain
headers['Access-Control-Allow-Origin'] = request.headers['HTTP_ORIGIN']
headers['Access-Control-Expose-Headers'] = 'ETag'
headers['Access-Control-Allow-Methods'] = 'GET, POST, PATCH, PUT, DELETE, OPTIONS, HEAD'
headers['Access-Control-Allow-Headers'] = '*,x-requested-with,Content-Type,If-Modified-Since,If-None-Match'
headers['Access-Control-Allow-Credentials'] = 'true'
headers['Access-Control-Max-Age'] = '86400'
end
end
Also today desktop Safari on Mountain Lion started not to send the cookie, behaving just like MobileSafari. I'm not entirely sure if my assessment yesterday was inaccurate, or perhaps Apple is just trolling me...
Also could this be affected by using https:// at the remote url?
I don't know if this solution will work or is acceptable to you but I had the same problem with mobile Safari and a JSONP app. It seemed that Safari was not set to accept third party cookies. I went to Settings > Safari > Accept Cookies and set 'Always' and the problem evaporated. Good luck.
Can I set cookies in a response from a jsonp request?
I believe you are experiencing what I have been seeing in my app. My issue, was caused because iOS Safari, comes with a default option "Prevent Cross-Site Tracking" enabled by default that is causing the browser to block ALL third party cookies, even cookies that are issued by your back-end server from a different domain and CORS is configured correctly.
The only solution to this problem I found was to use a proxy in production like I did in dev. I accomplished this in Azure with Azure Functions and making all request go through a proxy. At that point iOS Safari did not block my cookies everything was set as expected.
I wrote about it in my blog https://medium.com/#omikolaj1/complete-guide-to-deploying-angular-and-asp-net-33a0976d0ec1
You didn't mention whether the remote server is under a different domain or just a different subdomain. I assume is under a different domain.
As #schellsan pointed out you can't set/write cookies to a different domain even if the CORS policy allows it due the 3rd party cookies restriction on safari. It's the latest safari restriction. I guess Firefox is about to do the same.
Workarounds I'm currently evaluating:
Use a redirect on the remote server so that when the client is redirected (the remote URL is in the browser bar) you can set the cookie
Use a custom header
I was running into the same problem.
My setup was:
AngularJS (Ionic) App on Server A with domain a.com
NodeJS with Passport JS as Backend on Server B with domain b.com
The login with the cookie went well on every browser, except Mobile Safari on iOS. Also the change of the mobile cookie (Do not track) settings in iOS did not had any impact on the issue.
Solution was to set a CNAME DNS Record
backend.a.com CNAME b.com
Open an address that sets the cookie via an iFrame - this will set the cookie.

Categories