Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fetching CSRF from headers requires update #94

Open
shivam221098 opened this issue Nov 29, 2022 · 4 comments
Open

Fetching CSRF from headers requires update #94

shivam221098 opened this issue Nov 29, 2022 · 4 comments

Comments

@shivam221098
Copy link

shivam221098 commented Nov 29, 2022

In this line,

csrf_token = request.headers.get(self._access_csrf_header_name)

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.

@ramazanix
Copy link

ramazanix commented Apr 12, 2023

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)

@shivam221098
Copy link
Author

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 🙏

@ramazanix
Copy link

ramazanix commented Apr 13, 2023

@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

@ramazanix
Copy link

@shivam221098 Please, close issue if it helped you

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants