coulomb-social/tests/test_identity_regressions.py
tegwick 57a329949f Audit actual scope and implement safe corpus transfer tooling
Assistant: codex
Assistant-Model: gpt-6.1-sol
Assistant-Session: 01a10e2d-a5ef-7e92-b03d-b1694e915680
2026-10-06 09:54:33 +02:00

57 lines
2.4 KiB
Python

"""Independent negative checks requested by CSOC-IN-0002."""
from unittest.mock import patch
import pytest
from django.urls import reverse
from coulomb_social.apps.identity import views
from coulomb_social.apps.members.models import Member
@pytest.mark.django_db
def test_consumed_callback_state_cannot_be_replayed(client, settings):
settings.OIDC_ENABLED = True
settings.OIDC_ISSUER = "https://issuer.test"
settings.OIDC_CLIENT_ID = "test-client"
settings.OIDC_REDIRECT_URI = "https://app.test/auth/callback/"
session = client.session
session[views.SESSION_OIDC_STATE] = "single-use-state"
session[views.SESSION_OIDC_VERIFIER] = "verifier"
session.save()
with (
patch.object(views.oidc, "exchange_code", return_value={"access_token": "synthetic"})
as exchange,
patch.object(views.oidc, "fetch_userinfo", return_value={}),
patch.object(views.oidc, "claims_from_token_response", return_value={"sub": "new"}),
patch.object(views, "establish_session") as establish,
):
callback = reverse("identity:callback") + "?code=code&state=single-use-state"
assert client.get(callback).status_code == 302
assert client.get(callback).status_code == 400
assert exchange.call_count == 1
assert establish.call_count == 1
assert views.SESSION_OIDC_STATE not in client.session
assert views.SESSION_OIDC_VERIFIER not in client.session
@pytest.mark.django_db
def test_same_email_different_identity_cannot_take_over_member(client, settings):
settings.DEBUG = True
settings.OIDC_ENABLED = False
login = reverse("identity:dev_login")
client.post(login, {"issuer": "https://first.test", "subject": "original",
"email": "shared@example.test", "name": "Original"})
original = Member.objects.get(subject="original")
original_user_id = original.user_id
client.post(reverse("identity:logout"))
client.post(login, {"issuer": "https://second.test", "subject": "different",
"email": "shared@example.test", "name": "Different"})
original.refresh_from_db()
other = Member.objects.get(subject="different")
assert original.user_id == original_user_id
assert original.display_name == "Original"
assert other.pk != original.pk
assert other.user_id != original.user_id
assert str(client.session["_auth_user_id"]) == str(other.user_id)
assert Member.objects.count() == 2