Search code examples
reactjsdjangohttpcorsdjango-cors-headers

CORS, HttpOnly, CSRFCookie; Django; ReactJS


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) => {

        }
      )

Solution

  • 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'
    ]