Cookies disappear after redirect

You should use the withCredentials option when sending your ajax request to your http://server.com and your server.com should have the Access-Control-Allow-Credentials set to true.

Example code in Node.JS server:

var cors = require('cors');
var corsOptions = {
    origin: '*',
    credentials: true };

app.use(cors(corsOptions));

More on this here: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Credentials

Example code in Angular.JS client
import {RequestOptions, Request, RequestMethod} from '@angular/http';

const options = new RequestOptions({
  method: RequestMethod.Post,
  url: 'https://google.com',
  withCredentials: true
});

More on this here: https://angular.io/api/http/RequestOptions

Also check this out: https://github.com/angular/angular/issues/24283 - it looks like a particular version of Angular had problems with this flag, so unless you're using a more up-to-date version, you might need to set the header explicitly.

The reasoning of this is, unless the server explicitly tells the client "I will accept cookies (set previously on my domain) passed by another domain" - accepting the cookies would be a security issue. More here: https://en.wikipedia.org/wiki/Cross-site_request_forgery


Your description of what is happening does not seem right.

  • http://server.com/login stores a cookie 'auth' and sends a redirect instruction to http://client.com/welcome
  • 'auth' cookie is sent to http://client.com/welcome

That is not (or at least should not be) what is happening. When the browser requests http://server.com/login and gets back in the response a Set-Cookie header, the cookie is set on and restricted to the server.com domain, even if the response is a redirect. If you are seeing the 'auth' cookie sent to client.com then that is a cookie that client.com previously set.

Anyway, it seems that what you really care about is

  • http://client.com/welcome makes an AJAX request to http://server.com/data (CORS enabled), but the cookie 'auth' is not sent

There are a bunch of reasons this can happen.

  • CORS. You mentioned it was CORS enabled, but for the sake of others reading this, you must have the following CORS headers set on server.com
    • Access-Control-Allow-Origin: http://client.com
    • Access-Control-Allow-Credentials: true
  • Note that you cannot get away with using a wildcard for Access-Control-Allow-Origin when you are sending credentials. Also note that the origin has to be an exact match, including scheme (http or https). In practice, what servers generally do is read the Origin header of the request, check it against a white list, and if it allowed, copy the Origin header value from the request to the Access-Control-Allow-Origin header in the response.
  • You must set xhr.withCredentials = true in your XHR request. (See MDN for more details.)

Then after you have done all that, you have one other hurdle in your way. Because you are on client.com and trying to send a cookie to server.com, the server.com cookie is considered a "third-party" cookie. AFAIK all the major browsers have a setting that blocks third-party cookies for privacy, because they are most often used by trackers to gather marketing data for advertising. I believe most of them block third-party cookies by default, but I am not sure of that. For sure lots of people have set their browsers to block third-party cookies.

So you have to tell your visitors to configure their browser to allow third-party cookies from server.com.

BTW, it is not safe to set a cookie on a redirect to a different domain. While it is allowed under the specification AFAIK, there have been issues with browser support. See, for example, this Chrome bug.