fastapi-jwt-auth
fastapi-jwt-auth copied to clipboard
Fetching CSRF from headers requires update
In this line,
https://github.com/IndominusByte/fastapi-jwt-auth/blob/a6c06193319da0e4976c7472966f3a2891e0d50c/fastapi_jwt_auth/auth_jwt.py#L549
the code is trying to get CSRF_TOKEN from the headers and treating response.headers as a dict object which is true. But the headers don't contain the default "X-CSRF-Token". It contains the key-value pair with cookies as key and all cookie info as a string separated by ;.
So whenever someone tries to get CSRF token the code is unable to find the key "X-CSRF-Token" in the headers but now it's inside key cookies, which needs to be parsed for extracting CSRF_TOKEN.
That's why whenever someone uses csrf_protect as True, they get a Missing CSRF Token error every time
I can see the code is not updated for the last 2 years. That might be the reason that it is not in compliance with the browser's headers.
My friend, @shivam221098, its Double Submit Cookie Pattern. You need to repeat your csrf_access_token from Authorize.cookies in request' header by X-CSRF-Token.
Example:
cookies = response.cookie
headers = {'X-CSRF-Token': cookies.get('csrf_access_token')}
response = await client.post('your_path', headers=headers)
Thanks for the info @Ramazan2002. Is that csrf verification works for you?
If yes, Can you share the sample function which you have implemented? That would be a help 🙏
@shivam221098 For example I use it in my tests.
correct_cookies: list[str] = [
"access_token_cookie",
"csrf_access_token",
"csrf_refresh_token",
"refresh_token_cookie",
]
user_data = {"username": "Sam", "password": "sam_password"}
@pytest.mark.asyncio
async def test_logout(client: AsyncClient):
"""
Trying to log out
"""
# creating_user
response = await client.post("/users/", json=user_data)
assert response.status_code == 201
assert exact_schema(user) == response.json()
assert response.json().get("username") == user_data["username"]
# authorization
response = await client.post("/auth/login/", json=user_data)
assert response.status_code == 200
assert exact_schema(success) == response.json()
assert list(response.cookies.keys()) == correct_cookies # Check that correct_cookies set in your browser cookie
cookies = response.cookies
response = await client.delete("/auth/logout/")
assert response.status_code == 401
assert exact_schema(error) == response.json()
assert response.json().get("detail") == "Missing CSRF Token" # Checking that I get error when send request without X-CSRF-Token in headers
headers = {"X-CSRF-Token": cookies.get("csrf_access_token")}
response = await client.delete("/auth/logout/", headers=headers)
assert response.status_code == 200
assert exact_schema(success) == response.json()
assert len(response.cookies) == 0
@shivam221098 Please, close issue if it helped you