Cookie not set after HTTP request with Set-Cookie response header - laravel

Context: I'm trying to couple a separate frontend (Nuxt.js) with a Laravel backend. Session (logged in user etc.) is maintained by the backend and should be stored and updated in the frontend using cookies. I am making API calls using Axios.
I am currently running my frontend on localhost:3000 and my backend on 127.0.0.1:8000. When I make API calls from the frontend, I get the following headers in the response:
Access-Control-Allow-Credentials:true
Access-Control-Allow-Origin:http://localhost:3000
Cache-Control:no-cache, private
Connection:close
Content-Type:application/json
Date:Sun, 15 Oct 2017 13:05:24 GMT
Host:127.0.0.1:8000
Set-Cookie:laravel_session=fuqQf1fX3ZwQYl7xORGPopgZhD4qw5Mfi8lFrHTJ; expires=Sun, 15-Oct-2017 15:05:24 GMT; Max-Age=7200; path=/;
Vary:Origin
X-Powered-By:PHP/7.0.10
From what I understand, the browser should now set/update the laravel_session cookie. However, when I check the cookies in Chrome devtools, nothing changes.
Are the different URLs (or at least ports) an issue here? Am I missing some kind of header or directive that is required? I've done some research but haven't found a solution yet.

Related

Asgard CMS Laravel application accessed through VPN not setting cookies

I have a Asgard CMS Laravel application that I am accessing through my company's VPN network, as the server its running on, is not accessible from outside the private network.
Whenever I go to the login page, I do not see the laraval_session cookies set. The HTTP header shows the following values
Set-Cookie:HttpOnly;Secure
Transfer-Encoding:chunked
X-Content-Security-Policy:default-src 'self';
X-Content-Type-Options:nosniff
X-Frame-Options:SAMEORIGIN
As you would notice, a normal Asgard CMS application running fine will have some cookies set like
Set-Cookie:XSRF-TOKEN=<cookie value>; expires=Fri, 15-Jul-2016 10:29:57 GMT; Max-Age=7200; path=/
Set-Cookie:laravel_session=<cookie value>; expires=Fri, 15-Jul-2016 10:29:57 GMT; Max-Age=7200; path=/; httponly
We see above two cookies (XSRF-TOKEN, laravel_session) are being set on an application running fine.
However in my application none of these cookies are set on the login page. Due to this token mismatch error occurs after the user tries to login, as a new token gets generated, and the one in the form is the old one.
Also note that additional headers (X-Content-Security-Policy, X-Content-Type-Options, X-Frame-Options) show up which are not there in case of normal functional laravel application.
Once we access this application outside the network, it continuously shows up this error.
Any clues on how to get the cookies show up properly, and to make my laravel application to run as normal.

Does if-no-match need to be set programmatically in ajax request, if server sends Etag

My question is pretty simple. Although while searching over, I have not found a simple satisfying answer.
I am using Jquery ajax request to get the data from a server. Server
hosts a rest API that sets the Etag and Cach-control headers to the GET requests. The Server also sets CORS headers to allow the Etag.
The client of the Api is a browser web app. I am using Ajax request to call the Api. Here are the response headers from server after a simple GET request:
Status Code: 200 OK
Access-Control-Allow-Origin: *
Cache-Control: no-transform, max-age=86400
Connection: Keep-Alive
Content-Encoding: gzip
Content-Type: application/json
Date: Sun, 30 Aug 2015 13:23:41 GMT
Etag: "-783704964"
Keep-Alive: timeout=15, max=99
Server: Apache-Coyote/1.1
Transfer-Encoding: chunked
Vary: Accept-Encoding
access-control-allow-headers: X-Requested-With, Content-Type, Etag,Authorization
access-control-allow-methods: GET, POST, DELETE, PUT
All I want to know is:
Do I need to manually collect the Etag from response headers sent from the server and attach an if-no-match header to ajax request?OR the Browser sends it by-default in a conditional get request when it has an 'Etag'
I have done debugging over the network console in the browser and It
seems the browser is doing the conditional GET automatically and
sets the if-no-match header.
if it is right, Suppose, I created a new resource, and then I called the get request. It gives me the past cached data for the first time. But when I reload the page, It gives the updated one. So I am confused that, If the dataset on the server-side has changed and it sends a different Etag, Why doesn't the browser get an updated data set from the server unless I have to reload
Also in case of pagination. Suppose I have a URL /users?next=0. next is a query param where the value for the next changes for every new request. Since each response will get its own 'Etag'. Will the browser store the 'Etag' based on request or it just stores the lastest Etag of the previous get request, irrespective of the URL.
Well, I have somehow figured out the solution myself:
The browser sends the if-no-match header itself when it sees url had the e-tag header on a previous request. Browser saves the e-tag with respect to that URL, so it does not matter how many requests with different URLs happen.
Also, a trick to force the browser to fetch a conditional-get to check the e-tag:
Set the max-age header to the lowest (for me 60s works great)
once the cache expires, thebrowser will send a conditional-get to check if the expired cached resource is valid. If the if-no-match header matches with e-tag. The server sends the response back with 304: Not-Modified header. This means the expired cached resource is valid and can be used.

Web app doesn't work in Internet Explorer

My application works beautifully on Chrome, Firefox, Safari, and Opera, but fails on Internet Explorer 11 (I haven't tried earlier versions yet). Basically, I find that I cannot log in. I have narrowed the problem down to an issue with cookies. On login attempt, I get through to the server fine, and the response is the exact same as with any other browser. But for whatever reason, even though the Set-Cookie header is set, the cookie is not saved and sent on the next request to the server. My application has a (mostly) RESTful backend, and so authenticates on most requests. This obviously fails because the cookie is not set!
This problem persists whether served from localhost or from a real server. I should mention that it is a cross origin request, but the proper headers are in place (and they work on other browsers)
The response headers (when served from localhost) are as follows:
Response HTTP/1.1 200 OK
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers accept, content-type
Access-Control-Allow-Methods POST, PATCH, DELETE
Access-Control-Allow-Origin http://localhost:8000
Cache-Control no-cache,no-store
Content-Length 68
Content-Type application/json
Date Thu, 05 Mar 2015 20:00:20 GMT
Frame-Ancestors none
Server waitress
Set-Cookie session-id=ZqANyJ4KRUFoOaVgtGs/hcX+fxjMcCVM0kdRqF4riHglfAeBJJK56X9wn0XsNdPwUg; Domain=; HttpOnly;
Strict-Transport-Security max-age=31536000;
X-Frame-Options deny
I cannot figure out why this doesn't work solely in IE11! The app is not in an iframe, and the cookie actually appears in the cookies tab in the IE developer tools when I click on the network request, but it is not subsequently sent along with the next ones.
Some of my attempted solutions were:
Adding the Cache-Control header
Removing the HttpOnly flag from the cookie
Adding the Domain flag to the cookie (set as localhost or 127.0.0.1)
Removing Headers like X-Frame-Options, Frame-Ancestors, and Strict-Transport-Security
Tried multiple computers
Changed security settings to accept all cookies
All failed. Ideas?

Will ETag work without cache-control header set by web server

My server returns the following headers for a file:
Accept-Ranges:bytes
Connection:Keep-Alive
Content-Length:155
Content-Type:text/css
Date:Thu, 06 Feb 2014 18:32:44 GMT
ETag:"99000000061b06-9b-4f1c118fdd2f1"
Keep-Alive:timeout=5, max=100
Last-Modified:Thu, 06 Feb 2014 18:32:37 GMT
As you can see, it doesn't return cache-control header, however it returns ETag and Last-Modified headers.
My question is whether browser is going to cache the requested file? I can observr that during the following requests the browser sends ETag:"99000000061b06-9b-4f1c118fdd2f1" in headers and server returns status code 304.
And second question: Will browser cache resource and request it with ETag if Cache-control is set to no-cache?
For first part of question - It is up to your browser (its implementation and configuration) if the response will be cached and when will be revalidated. The only (standardized) difference between browser behaviour with validation headers and behaviour without validation headers is that former one can reduce traffic with server using validation.
Second question: Yes. Browser will cache resource but every time you open the page browser will ask origin server if resource was not modified. If not modified server will respond 304 and browser will display cached content. Otherwise server will send new content.
My guess would be ETag can serve as cache-control: no-cache.

Setting cookies through a CORS request

I'm porting a client-side library for an API from JSONP to CORS.
I have set all the correct headers in the server and done all the indicated things in the client, but I have a problem regarding cookies.
That API auth method works with cookies. With JSONP, it made a GET request to the API with the API key as a parameter. Then the server set a cookie at api.io.holalabs.com (API URL), so the next time it does a call to the API the server requests the cookie and make the login.
The problem is that, although I see Set-Cookie in the headers, the cookie is not set at api.io.holalabs.com so the login fails.
These are my headers:
Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version
Access-Control-Allow-Methods:GET
Access-Control-Allow-Origin:http://holalabs.com
Access-Control-Expose-Headers:X-Api-Version, X-Request-Id, X-Response-Time
Connection:close
Content-Length:13
Content-MD5:RjkY1fW5i5MKifxPk+r4tg==
Content-Type:application/json
Date:Fri, 13 Apr 2012 16:06:56 GMT
Server:nginx/1.0.14
Set-Cookie:apikey.sig=DYyrzLFUfJSjsmK5crkxHQg-rxQ; path=/; httponly
X-Api-Version:1.0.0
X-Request-Id:c78b4223-1caf-42db-a99e-b075bdc10ea5
X-Response-Time:2
EDIT: Using cookies in a API is a horrible idea, so now we are using a header to auth the user. Issue closed!
Issue is supposedly closed, but if anyone encounters this problem and need to use cookies, here's one possible explanation and solution:
Explanation
The session ID is sent as a cookie, and since the request is cross-domain, it's considered a third party cookie by the browser. Several browsers will block third-party cookies, and the session is lost.
Solution
Generate the session ID on the client (in the browser), use Javascript sessionStorage to store the session ID then send the session ID with each request to the server.
(Details: Javascript Cross-Domain Request With Session)

Resources