Prove registration collision safety
This commit is contained in:
parent
b80de5a1f4
commit
a8f190b7b7
2 changed files with 43 additions and 0 deletions
|
|
@ -354,6 +354,42 @@ class PortalApplicationTests(unittest.TestCase):
|
|||
)
|
||||
self.assertEqual("403 Forbidden", replay["status"])
|
||||
|
||||
def test_public_registration_duplicate_inputs_never_take_over_identity(self):
|
||||
verifier = FakeRegistrationVerification()
|
||||
self.app.registration_verification = verifier
|
||||
self.app.provisioning = FakeProvisioning()
|
||||
self.app.registration_clients = frozenset({"coulomb-social"})
|
||||
self.app.registration_tenants = frozenset({"tenant:coulomb"})
|
||||
self.app.registration_oidc_issuer = "https://kc.example"
|
||||
self.app.registration_password_setup_origins = frozenset({"https://kc.example"})
|
||||
|
||||
def register(username, email):
|
||||
invoke(self.app, "/api/v1/public/registrations", method="POST", body={
|
||||
"username": username, "email": email,
|
||||
"client_id": "coulomb-social", "tenant": "tenant:coulomb",
|
||||
})
|
||||
registration_id = verifier.requested.registration_id
|
||||
verifier.registration_id = registration_id
|
||||
result, _ = invoke(
|
||||
self.app, "/api/v1/public/registrations/verify", method="POST",
|
||||
body={"handle": "x" * 32},
|
||||
)
|
||||
return result, self.app.service.store.registration_session(registration_id)
|
||||
|
||||
first, first_session = register("first.person", "shared@example.test")
|
||||
second, second_session = register("second.person", "shared@example.test")
|
||||
collision, collision_session = register("first.person", "other@example.test")
|
||||
|
||||
self.assertEqual("303 See Other", first["status"])
|
||||
self.assertEqual("303 See Other", second["status"])
|
||||
self.assertNotEqual(first_session.user_id, second_session.user_id)
|
||||
self.assertEqual("409 Conflict", collision["status"])
|
||||
linked = self.app.service.store.find_identity(
|
||||
"https://kc.example", "first.person"
|
||||
)
|
||||
self.assertEqual(first_session.user_id, linked.user_id)
|
||||
self.assertNotEqual(collision_session.user_id, linked.user_id)
|
||||
|
||||
def test_public_registration_rejects_unregistered_client(self):
|
||||
self.app.registration_verification = FakeRegistrationVerification()
|
||||
self.app.registration_clients = frozenset({"coulomb-social"})
|
||||
|
|
|
|||
|
|
@ -197,3 +197,10 @@ verification expiry/replay redaction, peer rate limiting, identity-link
|
|||
collision, cross-tenant denial, lifecycle deletion, audit/outbox redaction,
|
||||
and request correlation. Deployed consumer conformance remains gated on public
|
||||
runtime credentials and activation.
|
||||
|
||||
Duplicate-input conformance now also proves that a verified mailbox reused
|
||||
with a different username creates a distinct local user instead of implicitly
|
||||
linking to an existing account. Reusing an existing provider username fails at
|
||||
the identity-link uniqueness boundary, leaves the original link unchanged, and
|
||||
never transfers that identity to the later registration. The full suite passes
|
||||
131 tests with three environment-dependent skips.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue