Cookie not being set on angular client

我的梦境 提交于 2020-08-04 06:33:08

问题


I have a backend app in django python and it is being served on http://localhost:8000.

I have a angular frontend which is being served on http://localhost:4200.

I have disabled CORS on django. On hitting the login api on http://localhost:8000/auth/login/, I am getting a valid response along with the Set-Cookie header.

Here is my angular code to print the cookies:

  this.http.post<any>('http://localhost:8000/auth/login/', this.LoginForm, { observe: 'response' }).subscribe(response => {
   console.log("response is ", response);
   var cookies = this.cookieService.getAll();//('cookies');
   console.log("cookies is :", cookies);

It prints an empty object on console. How do I make this work? I want to use cookies for authentication.


回答1:


You are trying to set cross domain cookies, which will not work straight away. There are a few steps to follow to be able to do that.

  1. Set withCredentials: true when making the authentication request from angular

    this.http.post<any>('http://localhost:8000/auth/login/', this.LoginForm, { observe: 'response', withCredentials: true })

  2. Configure your server to return the following CORS headers: Access-Control-Allow-Credentials: true and Access-Control-Allow-Origin: http://localhost:4200

Note

One of the cookies that you are setting is HttpOnly. As such, you cannot access it from Javascript (see documentation).

You may not need to access the cookies with JS anyway. If you just want to send the cookies in the next API requests, just pass withCredentials: true to HttpClient other api calls

this.http.get('http://localhost:8000/path/to/get/resource',
  { withCredentials: true }).subscribe(response => {



回答2:


Set-Cookies:

In the example in the Question, both client and server are in the same domain, localhost. On deployment, this may not be the case. Let us assume the domains as below,
  • Client : client1.client.com
  • Server: server1.server.com

A http request from the Angular web app in client1.client.com to https://server1.server.com/api/v1/getSomething has Set-Cookie: JSESSIONID=xyz in the response header. The cookie will be set on server1.server.com and NOT on client1.client.com. You can enter server1.server.com in the URL bar and see the cookie being set.

withCredentials:

There is no need for the angular app to read the cookie and send it in the following requests. withCredentials property of http request can be used for this. Refer: https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/withCredentials

Example:

public getSomething(): Observable<object> {
    const httpOptions = {
      withCredentials: true
    };
    return this.http.get(`${this.serverUrl}/getSomething`, httpOptions);
  }

Refer: https://angular.io/api/common/http/HttpRequest

withCredentials will set the cookies from the server's domain in the requests to the server.

As mentioned before Set-Cookie: JSESSIONID=xyz in the response from server1.server.com will be set in server1.server.com. The Angular app in client1.client.com need not read it. withCredentials will take care of it.

cross domain issues:

When the server and client are in different domains, using withCredentials may not work in all browsers, as they are considered as third party cookies.

In my recent testing on May 2020, I found that withCredentials is not working in certain browsers when the client and server are in different domains.

  • In Safari, the issue occurs when "Prevent cross-site tracking" is enabled (by default). The issue is prevented by disabling the same. https://support.apple.com/en-in/guide/safari/sfri40732/mac
  • In Android apps, the issue can be avoided by using Chrome Custom Tabs instead of Android WebView. https://github.com/NewtonJoshua/custom-tabs-client , https://developer.chrome.com/multidevice/android/customtabs

Same domain:

Looks like mainstream browsers are moving to block third-party cookies.

  • Safari - Full Third-Party Cookie Blocking and More
  • Chrome (by 2022) - Building a more private web: A path towards making third party cookies obsolete

The solution is to have both the client and server in the same domain.

  • Client: client1.myapp.com
  • Server: server1.myapp.com

And in the Set-Cookie response include the root domain too. Example: "JSESSIONID=xyz; Domain=.myapp.com; Path=/"

This will make sure the cookies are set in all cases.



来源:https://stackoverflow.com/questions/62674236/cookie-not-being-set-on-angular-client

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!