Fix OIDC subject collisions by introducing canonical provider-plus-subject principals
- Add canonical_principal(provider, sub) => 'oidc:v1:<provider>:<sub>' - Preserve provider identity across HTTP sessions and WebSockets - Apply principals throughout: game creation/joining/seating, WebSocket views/actions, Redis engine state, match history, leaderboard focus, ratings, /api/me, OpenAPI, and telemetry - Widen identity columns to 1024 chars with schema-only aerich migration (5_20261024221522_canonical_principals.py) - Document provider names as stable security identifiers - Add regression tests: same subject at different providers cannot share games, private hands, join codes, moves, history, or ratings; distinct seat and rating ownership verified - All platform, integration, game, and frontend tests pass; mypy clean
This commit is contained in:
@@ -11,7 +11,7 @@ from httpx import ASGITransport, AsyncClient
|
||||
|
||||
from tavolo.app import app
|
||||
from tavolo.config import settings
|
||||
from tests.helpers import async_test, oidc_user
|
||||
from tests.helpers import async_test, make_principal, oidc_user
|
||||
|
||||
|
||||
class MeRouteTest(unittest.TestCase):
|
||||
@@ -25,7 +25,7 @@ class MeRouteTest(unittest.TestCase):
|
||||
# The email claim the IdP returns is neither stored nor exposed;
|
||||
# no picture claim in this request.
|
||||
self.assertEqual(
|
||||
{"sub": "alice", "name": "alice", "picture": None},
|
||||
{"sub": make_principal("alice"), "name": "alice", "picture": None},
|
||||
response.json(),
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user