mirror of
https://github.com/suitenumerique/meet.git
synced 2026-08-31 12:47:58 +00:00
♻️(backend) align CSRF token header with Django conventions
Update the CSRF header naming to follow Django standards, avoiding duplicated client-side logic with inconsistent header names.
This commit is contained in:
@@ -106,7 +106,7 @@ class SessionViewSet(viewsets.ViewSet):
|
|||||||
"""Poll a session for its current state and, if terminal, consume it.
|
"""Poll a session for its current state and, if terminal, consume it.
|
||||||
|
|
||||||
Authenticates the caller using the addonsSid cookie (set by
|
Authenticates the caller using the addonsSid cookie (set by
|
||||||
/init) together with the X-CSRF-Token header, which must match
|
/init) together with the X-CSRFToken header, which must match
|
||||||
the CSRF token issued for that session. The session id alone is not
|
the CSRF token issued for that session. The session id alone is not
|
||||||
sufficient — both must be presented and must correspond.
|
sufficient — both must be presented and must correspond.
|
||||||
|
|
||||||
@@ -127,7 +127,7 @@ class SessionViewSet(viewsets.ViewSet):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
session_id = request.COOKIES.get(settings.ADDONS_SESSION_ID_COOKIE)
|
session_id = request.COOKIES.get(settings.ADDONS_SESSION_ID_COOKIE)
|
||||||
submitted_csrf = request.headers.get("X-CSRF-Token")
|
submitted_csrf = request.headers.get("X-CSRFToken")
|
||||||
|
|
||||||
if not session_id:
|
if not session_id:
|
||||||
return drf_response.Response(
|
return drf_response.Response(
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ def test_init_cookie_authorizes_subsequent_poll():
|
|||||||
|
|
||||||
poll_response = api_client.post(
|
poll_response = api_client.post(
|
||||||
"/api/v1.0/addons/sessions/poll/",
|
"/api/v1.0/addons/sessions/poll/",
|
||||||
HTTP_X_CSRF_TOKEN=csrf_token,
|
HTTP_X_CSRFTOKEN=csrf_token,
|
||||||
)
|
)
|
||||||
|
|
||||||
assert poll_response.status_code == 202
|
assert poll_response.status_code == 202
|
||||||
@@ -180,7 +180,7 @@ def test_poll_rejects_invalid_csrf_token():
|
|||||||
|
|
||||||
poll_response = api_client.post(
|
poll_response = api_client.post(
|
||||||
"/api/v1.0/addons/sessions/poll/",
|
"/api/v1.0/addons/sessions/poll/",
|
||||||
HTTP_X_CSRF_TOKEN="invalid-csrf-token",
|
HTTP_X_CSRFTOKEN="invalid-csrf-token",
|
||||||
)
|
)
|
||||||
|
|
||||||
# SuspiciousOperation translates to 400 via Django's exception middleware.
|
# SuspiciousOperation translates to 400 via Django's exception middleware.
|
||||||
@@ -202,7 +202,7 @@ def test_poll_session_not_found(mock_get_session_data):
|
|||||||
|
|
||||||
poll_response = api_client.post(
|
poll_response = api_client.post(
|
||||||
"/api/v1.0/addons/sessions/poll/",
|
"/api/v1.0/addons/sessions/poll/",
|
||||||
HTTP_X_CSRF_TOKEN=csrf_token,
|
HTTP_X_CSRFTOKEN=csrf_token,
|
||||||
)
|
)
|
||||||
|
|
||||||
assert poll_response.status_code == 404
|
assert poll_response.status_code == 404
|
||||||
@@ -224,7 +224,7 @@ def test_poll_session_corrupted(mock_get_session_data):
|
|||||||
|
|
||||||
poll_response = api_client.post(
|
poll_response = api_client.post(
|
||||||
"/api/v1.0/addons/sessions/poll/",
|
"/api/v1.0/addons/sessions/poll/",
|
||||||
HTTP_X_CSRF_TOKEN=csrf_token,
|
HTTP_X_CSRFTOKEN=csrf_token,
|
||||||
)
|
)
|
||||||
|
|
||||||
assert poll_response.status_code == 400
|
assert poll_response.status_code == 400
|
||||||
@@ -249,7 +249,7 @@ def test_poll_session_authenticated():
|
|||||||
|
|
||||||
poll_response = api_client.post(
|
poll_response = api_client.post(
|
||||||
"/api/v1.0/addons/sessions/poll/",
|
"/api/v1.0/addons/sessions/poll/",
|
||||||
HTTP_X_CSRF_TOKEN=csrf_token,
|
HTTP_X_CSRFTOKEN=csrf_token,
|
||||||
)
|
)
|
||||||
|
|
||||||
assert poll_response.status_code == 200
|
assert poll_response.status_code == 200
|
||||||
@@ -271,7 +271,7 @@ def test_poll_session_authenticated():
|
|||||||
# Server cleared the addonsSid cookie; APIClient drops it → no credentials.
|
# Server cleared the addonsSid cookie; APIClient drops it → no credentials.
|
||||||
poll_response = api_client.post(
|
poll_response = api_client.post(
|
||||||
"/api/v1.0/addons/sessions/poll/",
|
"/api/v1.0/addons/sessions/poll/",
|
||||||
HTTP_X_CSRF_TOKEN=csrf_token,
|
HTTP_X_CSRFTOKEN=csrf_token,
|
||||||
)
|
)
|
||||||
assert poll_response.status_code == 401
|
assert poll_response.status_code == 401
|
||||||
|
|
||||||
@@ -279,7 +279,7 @@ def test_poll_session_authenticated():
|
|||||||
api_client.cookies["addonsSid"] = session_id_cookie.value
|
api_client.cookies["addonsSid"] = session_id_cookie.value
|
||||||
poll_response = api_client.post(
|
poll_response = api_client.post(
|
||||||
"/api/v1.0/addons/sessions/poll/",
|
"/api/v1.0/addons/sessions/poll/",
|
||||||
HTTP_X_CSRF_TOKEN=csrf_token,
|
HTTP_X_CSRFTOKEN=csrf_token,
|
||||||
)
|
)
|
||||||
assert poll_response.status_code == 404
|
assert poll_response.status_code == 404
|
||||||
assert poll_response.json() == {"detail": "Session not found."}
|
assert poll_response.json() == {"detail": "Session not found."}
|
||||||
@@ -307,11 +307,11 @@ def test_poll_two_clients_do_not_interfere():
|
|||||||
# Each client polls its own session.
|
# Each client polls its own session.
|
||||||
poll_a = client_a.post(
|
poll_a = client_a.post(
|
||||||
"/api/v1.0/addons/sessions/poll/",
|
"/api/v1.0/addons/sessions/poll/",
|
||||||
HTTP_X_CSRF_TOKEN=csrf_a,
|
HTTP_X_CSRFTOKEN=csrf_a,
|
||||||
)
|
)
|
||||||
poll_b = client_b.post(
|
poll_b = client_b.post(
|
||||||
"/api/v1.0/addons/sessions/poll/",
|
"/api/v1.0/addons/sessions/poll/",
|
||||||
HTTP_X_CSRF_TOKEN=csrf_b,
|
HTTP_X_CSRFTOKEN=csrf_b,
|
||||||
)
|
)
|
||||||
assert poll_a.status_code == 202
|
assert poll_a.status_code == 202
|
||||||
assert poll_b.status_code == 202
|
assert poll_b.status_code == 202
|
||||||
@@ -319,7 +319,7 @@ def test_poll_two_clients_do_not_interfere():
|
|||||||
# Cross-use (A's cookie + B's CSRF) must be rejected.
|
# Cross-use (A's cookie + B's CSRF) must be rejected.
|
||||||
cross_response = client_a.post(
|
cross_response = client_a.post(
|
||||||
"/api/v1.0/addons/sessions/poll/",
|
"/api/v1.0/addons/sessions/poll/",
|
||||||
HTTP_X_CSRF_TOKEN=csrf_b,
|
HTTP_X_CSRFTOKEN=csrf_b,
|
||||||
)
|
)
|
||||||
assert cross_response.status_code == 400
|
assert cross_response.status_code == 400
|
||||||
|
|
||||||
@@ -336,13 +336,13 @@ def test_poll_two_clients_do_not_interfere():
|
|||||||
):
|
):
|
||||||
poll_a = client_a.post(
|
poll_a = client_a.post(
|
||||||
"/api/v1.0/addons/sessions/poll/",
|
"/api/v1.0/addons/sessions/poll/",
|
||||||
HTTP_X_CSRF_TOKEN=csrf_a,
|
HTTP_X_CSRFTOKEN=csrf_a,
|
||||||
)
|
)
|
||||||
assert poll_a.status_code == 200
|
assert poll_a.status_code == 200
|
||||||
|
|
||||||
poll_b = client_b.post(
|
poll_b = client_b.post(
|
||||||
"/api/v1.0/addons/sessions/poll/",
|
"/api/v1.0/addons/sessions/poll/",
|
||||||
HTTP_X_CSRF_TOKEN=csrf_b,
|
HTTP_X_CSRFTOKEN=csrf_b,
|
||||||
)
|
)
|
||||||
assert poll_b.status_code == 202
|
assert poll_b.status_code == 202
|
||||||
|
|
||||||
@@ -369,14 +369,14 @@ def test_poll_csrf_attack_does_not_disrupt_legitimate_client():
|
|||||||
# Fabricated CSRF token
|
# Fabricated CSRF token
|
||||||
attack_bad_csrf = attacker.post(
|
attack_bad_csrf = attacker.post(
|
||||||
"/api/v1.0/addons/sessions/poll/",
|
"/api/v1.0/addons/sessions/poll/",
|
||||||
HTTP_X_CSRF_TOKEN="attacker-guessed-token",
|
HTTP_X_CSRFTOKEN="attacker-guessed-token",
|
||||||
)
|
)
|
||||||
assert attack_bad_csrf.status_code == 400
|
assert attack_bad_csrf.status_code == 400
|
||||||
|
|
||||||
# Legitimate client's session is still usable.
|
# Legitimate client's session is still usable.
|
||||||
legitimate_poll = legitimate.post(
|
legitimate_poll = legitimate.post(
|
||||||
"/api/v1.0/addons/sessions/poll/",
|
"/api/v1.0/addons/sessions/poll/",
|
||||||
HTTP_X_CSRF_TOKEN=csrf_token,
|
HTTP_X_CSRFTOKEN=csrf_token,
|
||||||
)
|
)
|
||||||
assert legitimate_poll.status_code == 202
|
assert legitimate_poll.status_code == 202
|
||||||
assert legitimate_poll.json() == {"state": "pending"}
|
assert legitimate_poll.json() == {"state": "pending"}
|
||||||
@@ -508,7 +508,7 @@ def test_exchange_success_enables_poll_to_complete():
|
|||||||
# 3. Taskpane's next poll transitions from pending → authenticated.
|
# 3. Taskpane's next poll transitions from pending → authenticated.
|
||||||
poll_response = taskpane.post(
|
poll_response = taskpane.post(
|
||||||
"/api/v1.0/addons/sessions/poll/",
|
"/api/v1.0/addons/sessions/poll/",
|
||||||
HTTP_X_CSRF_TOKEN=csrf_token,
|
HTTP_X_CSRFTOKEN=csrf_token,
|
||||||
)
|
)
|
||||||
assert poll_response.status_code == 200
|
assert poll_response.status_code == 200
|
||||||
response_data = poll_response.json()
|
response_data = poll_response.json()
|
||||||
|
|||||||
Reference in New Issue
Block a user