Reputation: 652
The following response
header doesn't set the cookie in browser:
Access-Control-Allow-Origin: *
Allow: GET, HEAD, OPTIONS
Content-Length: 7
Content-Type: application/json
Date: Tue, 27 Apr 2021 15:58:02 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.9.4
Set-Cookie: csrftoken=r5r2YcZZvJKs79cbLd24VSyNscpUsxJB6UuWiWO2TXriy6B4r8KDZrwSDyI091K1; expires=Tue, 26 Apr 2022 15:58:02 GMT; Max-Age=31449600; Path=/; SameSite=Lax
Vary: Accept, Cookie, Origin
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
My request
headers:
Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-GB,en-US;q=0.9,en;q=0.8
Cache-Control: no-cache
Connection: keep-alive
Host: 127.0.0.1:8000
Origin: http://localhost:3000
Pragma: no-cache
Referer: http://localhost:3000/
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="90", "Google Chrome";v="90"
sec-ch-ua-mobile: ?0
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.85 Safari/537.36
I am new to Django, react and "http header" related stuff.
My django dev server runs at:
http://127.0.0.1:8000/
and my react dev server runs at:
http://127.0.0.1:3000
/api/csrf/
explicitly, to set the csrf token.# URL: /api/csrf/
class CSRFGet(APIView):
"""
Explicitly set csrf cookie
"""
@method_decorator(ensure_csrf_cookie)
def get(self, request):
return Response('hello')
I call this endpoint, when useProvideAuth
hook is mounted.
function useProvideAuth() {
const [token, setToken] = useState(null);
const login = (username, password) => {
return axios.post(
'/auth/',
{
username: username,
password: password
})
.then(response => {
setToken(response.token)
})
}
useEffect(()=> {
axios.get(
'/csrf/'
)
},[])
return {
token,
login,
}
}
Now, when i make a request to any page, it redirects to login page, and i can see api/csrf/
responds with:
Set-Cookie: csrftoken=LgHo2Y7R1BshM4iPisi5qCXhdHyAQK7hD0LxYwESZGcUh3dXwDu03lORdDq02pzG; expires=Tue, 26 Apr 2022 06:29:23 GMT; Max-Age=31449600; Path=/; SameSite=Lax
But, the cookie is not set at all. Why is it so?
Is my approach for getting csrf cookie correct? Please let me know, if i am making any security vulnerability with this approach.
Upvotes: 1
Views: 2222
Reputation: 652
Turns out the issue was, i was using http://127.0.0.1:8000
to make api calls, where as my server was on http://localhost:8000
. Because of this, host
and origin
, in my request
headers didn't match the same domain.
Cookies can be allowed to be used under same domain, with different ports and subdomains, unlike Same-Origin
policy, but cannot be used cross-domains.
In my case, I guess http://127.0.0.1:8000
& http://localhost:8000
were considered different domains, and thus the browser was not setting my cookie.
Thanks Anas Tiour, for stating about Allow-Credentials
. I had tried that too, but still had no luck until i found out the actual reason.
Upvotes: 2
Reputation: 1432
Could you try adding the following to the django-cors-headers
configuration and retry?
CORS_ALLOW_CREDENTIALS = True
Also, please note that the above configuration would probably not work if you are allowing all origins. See this Mozilla documentation: Credential is not supported if the CORS header ‘Access-Control-Allow-Origin’ is ‘*’
If you face such error, I suggest setting:
CORS_ALLOWED_ORIGINS = [
"http://127.0.0.1:3000",
]
or something fancier like:
CORS_ALLOWED_ORIGIN_REGEXES = [
r"^http://127.0.0.1:[0-9]{1,4}$",
]
Finally, make sure that you are using a django-cors-headers
version >= 3.5 since the 2 above configuration had different aliases back then.
Let me know if it works, I am very curious.
Upvotes: 1