Home > Net >  CORS, HttpOnly, CSRFCookie; Django; ReactJS
CORS, HttpOnly, CSRFCookie; Django; ReactJS

Time:07-23

I am developing a webApp. My backend is on xxx.xxx.xxx.xxx:8000 and my frontend is on xxx.xxx.xxx.xxx:3000. I am using Django and ReactJS. I have configured my CORS policies on the backend to allow only my fronted to make requests.

So. Whenever I have to get CSRF cookies from my backend they come in a response under Set-Cookie with HttpOnly flag.

My question is if we are not supposed to extract HttpOnly cookies with the JS how come I still can do that with my ReactJS app. However, whenever I remove that flag I cannot set or retrieve those cookies from the header anymore. Whta is wrong? Or what is right?

Help me to understand that please.

my django CORS setup:

# CSRF Cookie Settings
CSRF_COOKIE_AGE: Optional[int] = None

CSRF_TRUSTED_ORIGINS = [
    'http://localhost:3000',
    'http://xxxx.xxxx.xxxx.xxxx:3000'
]

CSRF_COOKIE_HTTPONLY = True

# CORS(cross origin resource sharing) settings
CORS_ORIGIN_ALLOW_ALL = False

CORS_ALLOW_CREDENTIALS = True

CORS_ALLOWED_ORIGINS = [
    'http://localhost:3000',
    'http://xxxx.xxxx.xxxx.xxxx:3000',
]

CORS_ALLOW_METHODS = [
'DELETE',
'GET',
'PATCH',
'POST',
'PUT',
]


my reactjs request:

fetch("http://xxxx.xxxx.xxxx.xxxx:8000/get_csrf",{
      method: 'GET',
      mode: 'cors',
      credentials:'same-origin',
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json'
      }
    })
      .then(response => {
        console.log(...response.headers)
        response.json()
      })
      .then(
        (result) => {
          console.log(this.getCookie('csrftoken'))
        },

        (error) => {

        }
      )

CodePudding user response:

TL;DR

You cannot.

More details

My backend is on xxxx.xxxx.xxxx.xxxx:8000 and my frontend is on xxxx.xxxx.xxxx.xxxx:3000.

Note that your request is cross-origin.

Be aware that the Fetch Standard (the de facto CORS specification) categorises Set-Cookie as a forbidden response-header name. Therefore, regardless of the server's CORS configuration, browsers do not allow a client to read such headers from the response to a cross-origin request.

The MDN Web Docs about the Set-Cookie response header, which may be a nonauthoritative source of truth but is easier to read than the Fetch Standard, contains this clarifying warning:

Browsers block frontend JavaScript code from accessing the Set-Cookie header, as required by the Fetch spec, which defines Set-Cookie as a forbidden response-header name that must be filtered out from any response exposed to frontend code.

CodePudding user response:

So I have gathered a bit more information and have found out how to set it up correctly.

  1. Yes, we cannot access HttpOnly cookies.
  2. Need to have credentials:'include' in the fetch JS request.
  3. Need to have mode: 'cors' in the fetch JS request.
  4. In Django settings.py:
CORS_ORIGIN_ALLOW_ALL = False

CORS_ALLOW_CREDENTIALS = True

CORS_ALLOWED_ORIGINS = [
    'http://localhost:3000',
    'http://xxx.xxx.xxx.xxx:3000',
]

CORS_ALLOW_METHODS = [
    'DELETE',
    'GET',
    'PATCH',
    'POST',
    'PUT',
]

CORS_EXPOSE_HEADERS = [
    'Date'
]

  • Related