5

I am setting an http only cookie from the server and I can see that the cookie gets set, but when I send requests to the server the cookie isn't included.

On the server end CORS is set to:

  1. Allow origins: http://localhost:4200
  2. Allow headers: X-Requested-With, Accept, Observe, Content-Type, and Authorization
  3. Allow methods: GET, POST, HEADER, PUT, DELETE, and OPTIONS
  4. Allow credentials: true

I can see that the cookie is set, but requests to the server after setting the cookie are not including the cookie.

An example of how I am requesting from the server is:

getUserInfo(): Observable<User> {
    const httpOptions = {
        headers: new HttpHeaders({
            'Content-Type': 'application/json'
        }),
        withCredentials: true
    };

}

As you can see I have withCredentials set to true, but my cookie is still not being sent.

Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Connection: keep-alive
Host: localhost:8080
Origin: http://localhost:4200
Referer: http://localhost:4200/login
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.80 Safari/537.36

What else do I need to do to get the cookie to send?

daedsidog
  • 1,732
  • 2
  • 17
  • 36
paul41
  • 576
  • 7
  • 17

1 Answers1

2

If your cookie settings are correct on the server, and still Angular is not sending the cookie previously set by the server, then probably this is happening because your running and testing this with Angular's development server on port 4200, while the API server is running on a different port.

The browser will automatically send the cookie along with the request to the server, only if the cookie's "Domain" attribute matches the domain of the URL being requested (when a cookie is set, it can be assigned a "Domain" attribute that restricts the cookie to a specific subdomain or domain), and when a request is made to a URL that matches the cookie's domain.

In the question above, it is possible that you're angular development server (and the Angular app) are running on http//localhost:4200, where the API server is running, for example, on http//localhost:3000. In such case, since the port is a part of the domain, the browser won't attach the cookie along with the request to your API.

To solve this, you can add proxy settings to your Angular app:

  1. Change the domain to a prefix in all direct URLs in the angular app. I.e. change http//localhost:3000/your-api-route to the /api/your-api-route. For example:
// Change
this.http.get<User>('http://localhost:3000' + '/auth/whoami', { withCredentials: true });
this.http.post<User>('http://localhost:3000' + '/auth/whoami', null, { withCredentials: true });

// To
this.http.get<User>('/api' + '/auth/whoami', { withCredentials: true });
this.http.post<User>('/api' + '/auth/whoami', null, { withCredentials: true });     
  1. Create a file proxy.conf.json in your project's src/ folder.

  2. Add the following content to the new proxy file, with pathRewrite - that is used to remove the /api prefix we added when we replaced http://localhost:3000 with /api:

{
  "/api": {
    "target": "http://localhost:3000",
    "secure": false,
    "pathRewrite": {
            "^/api": ""
        }
  }
}
  1. In the CLI configuration file, angular.json, add the proxyConfig option to the serve target:
...
  "architect": {
    "serve": {
      "builder": "@angular-devkit/build-angular:dev-server",
      "options": {
        "browserTarget": "your-application-name:build",
        "proxyConfig": "src/proxy.conf.json"
      },
...
  1. To run the development server with this proxy configuration, call ng serve.

Now, the browser will automatically attach a cookie set using the 'set-cookie' header by a server running on http://localhost:3000 to any request going from your angular app (running on http://localhost:4200) to a server running on http://localhost:3000.

Note that you'd need to change http://localhost:3000 in production. You'd probably need multiple proxy settings, one for each environment. However, if your Angular app is served by the API server (i.e. a static directory served by the server on the same port), then the proxy settings won't be needed.

Lorraine R.
  • 1,545
  • 1
  • 14
  • 39