Skip to content

Commit de2465c

Browse files
committed
RSPEED-2326: feat(auth): store RH Identity data in request.state
Store RHIdentityData instance in request.state.rh_identity_data during authentication, enabling downstream endpoints to access org_id and system_id for telemetry without modifying AuthTuple. Signed-off-by: Major Hayden <major@redhat.com>
1 parent d5db1ad commit de2465c

2 files changed

Lines changed: 30 additions & 1 deletion

File tree

src/authentication/rh_identity.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,9 @@ async def __call__(self, request: Request) -> AuthTuple:
247247
# Validate entitlements if configured
248248
rh_identity.validate_entitlements()
249249

250+
# Store identity data in request.state for downstream access
251+
request.state.rh_identity_data = rh_identity
252+
250253
# Extract user data
251254
user_id = rh_identity.get_user_id()
252255
username = rh_identity.get_username()

tests/unit/authentication/test_rh_identity.py

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ def create_auth_header(identity_data: dict) -> str:
9393
return base64.b64encode(json_str.encode("utf-8")).decode("utf-8")
9494

9595

96-
def create_request_with_header(header_value: Optional[str]) -> Request:
96+
def create_request_with_header(header_value: Optional[str]) -> Mock:
9797
"""Helper to create mock Request with x-rh-identity header.
9898
9999
Create a mock FastAPI Request with an `x-rh-identity` header for tests.
@@ -109,6 +109,7 @@ def create_request_with_header(header_value: Optional[str]) -> Request:
109109
"""
110110
request = Mock(spec=Request)
111111
request.headers = {"x-rh-identity": header_value} if header_value else {}
112+
request.state = Mock()
112113
return request
113114

114115

@@ -326,6 +327,31 @@ async def test_system_authentication_success(
326327
assert skip_check is False
327328
assert token == NO_USER_TOKEN
328329

330+
@pytest.mark.asyncio
331+
@pytest.mark.parametrize(
332+
"fixture_name,expected_user_id",
333+
[
334+
("user_identity_data", "abc123"),
335+
("system_identity_data", "c87dcb4c-8af1-40dd-878e-60c744edddd0"),
336+
],
337+
)
338+
async def test_rh_identity_stored_in_request_state(
339+
self, fixture_name: str, expected_user_id: str, request: pytest.FixtureRequest
340+
) -> None:
341+
"""Test RH Identity data is stored in request.state for downstream access."""
342+
identity_data = request.getfixturevalue(fixture_name)
343+
auth_dep = RHIdentityAuthDependency()
344+
header_value = create_auth_header(identity_data)
345+
mock_request = create_request_with_header(header_value)
346+
347+
await auth_dep(mock_request)
348+
349+
assert hasattr(mock_request.state, "rh_identity_data")
350+
rh_identity = mock_request.state.rh_identity_data
351+
assert isinstance(rh_identity, RHIdentityData)
352+
assert rh_identity.get_user_id() == expected_user_id
353+
assert rh_identity.get_org_id() == "321"
354+
329355
@pytest.mark.asyncio
330356
async def test_missing_header(self) -> None:
331357
"""Test authentication fails when header is missing."""

0 commit comments

Comments
 (0)