fixup! ✨(backend) introduce a token exchange endpoint for iframe embeds

This commit is contained in:
lebaudantoine
2026-10-08 20:12:03 +02:00
parent fc905c654d
commit 3dc25d8ea7
4 changed files with 35 additions and 3 deletions
+5 -1
View File
@@ -303,7 +303,11 @@ class UserViewSet(viewsets.GenericViewSet):
POST /api/v1.0/users/exchange-access-token/ for a JWT access token,
equivalent to session-cookie authentication and never exposed in a URL.
"""
client_id = (request.auth or {}).get("client_id", "unknown")
if not request.auth or not request.auth.get("client_id"):
raise drf_exceptions.AuthenticationFailed("Invalid application token.")
client_id = request.auth["client_id"]
code = TransitCodeService().create_code(request.user, client_id=client_id)
+1 -1
View File
@@ -27,7 +27,7 @@ class TransitCodeService:
digest = hashlib.sha256(code.encode("utf-8")).hexdigest()
return f"{settings.TRANSIT_CODE_CACHE_PREFIX}:{digest}"
def create_code(self, user, client_id="unknown"):
def create_code(self, user, client_id):
"""Generate a transit code for a user, and store it.
The code expires after TRANSIT_CODE_TTL seconds.
@@ -17,7 +17,7 @@ def test_create_code_returns_unique_opaque_codes():
user = UserFactory()
service = TransitCodeService()
codes = {service.create_code(user) for _ in range(5)}
codes = {service.create_code(user, "my-app") for _ in range(5)}
assert len(codes) == 5
for code in codes:
@@ -207,3 +207,31 @@ def test_api_users_transit_code_rejects_addons_token():
response = client.post("/external-api/v1.0/users/transit-code/")
assert response.status_code == 401
@pytest.mark.parametrize("auth", [None, {}, {"client_id": ""}, {"client_id": None}])
def test_api_users_transit_code_missing_client_id(auth):
"""No transit code should be minted without a client_id in the token."""
user = UserFactory()
client = APIClient()
client.credentials(HTTP_AUTHORIZATION="Bearer token")
with (
mock.patch(
"core.external_api.authentication.ApplicationJWTAuthentication.authenticate",
return_value=(user, auth),
),
mock.patch(
"core.external_api.permissions.HasRequiredUserScope.has_permission",
return_value=True,
),
mock.patch.object(
TransitCodeService, "create_code", return_value="code"
) as mock_create_code,
):
response = client.post("/external-api/v1.0/users/transit-code/")
assert response.status_code == 401
assert response.json() == {"detail": "Invalid application token."}
mock_create_code.assert_not_called()