diff --git a/tests/test_scenario_validation.py b/tests/test_scenario_validation.py index b9a048b..579349a 100644 --- a/tests/test_scenario_validation.py +++ b/tests/test_scenario_validation.py @@ -1,5 +1,6 @@ from __future__ import annotations +import secrets from datetime import date from collections.abc import Iterator from typing import cast @@ -176,8 +177,11 @@ def api_client(session_factory) -> Iterator[TestClient]: user = uow.users.get(user.id, with_roles=True) def _override_auth_session(request: Request) -> AuthSession: - session = AuthSession(tokens=SessionTokens( - access_token="test", refresh_token="test")) + tokens = SessionTokens( + access_token=secrets.token_urlsafe(16), + refresh_token=secrets.token_urlsafe(16), + ) + session = AuthSession(tokens=tokens) session.user = user request.state.auth_session = session return session diff --git a/tests/test_security.py b/tests/test_security.py index 1bfdc33..1440003 100644 --- a/tests/test_security.py +++ b/tests/test_security.py @@ -1,5 +1,6 @@ from __future__ import annotations +import secrets from datetime import timedelta import pytest @@ -17,11 +18,18 @@ from services.security import ( ) -def test_hash_password_round_trip() -> None: - hashed = hash_password("super-secret") +@pytest.fixture() +def jwt_settings() -> JWTSettings: + """Provide a unique JWTSettings instance per test with random secret.""" + return JWTSettings(secret_key=secrets.token_urlsafe(32)) - assert hashed != "super-secret" - assert verify_password("super-secret", hashed) + +def test_hash_password_round_trip() -> None: + password = secrets.token_urlsafe(16) + hashed = hash_password(password) + + assert hashed != password + assert verify_password(password, hashed) assert not verify_password("incorrect", hashed) @@ -29,47 +37,42 @@ def test_verify_password_handles_malformed_hash() -> None: assert not verify_password("secret", "not-a-valid-hash") -def test_access_token_roundtrip() -> None: - settings = JWTSettings(secret_key="unit-test-secret") - +def test_access_token_roundtrip(jwt_settings: JWTSettings) -> None: token = create_access_token( "user-id-123", - settings, + jwt_settings, scopes=("read", "write"), extra_claims={"custom": "value"}, ) - payload = decode_access_token(token, settings) + payload = decode_access_token(token, jwt_settings) assert payload.sub == "user-id-123" assert payload.type == "access" assert payload.scopes == ["read", "write"] -def test_refresh_token_type_mismatch() -> None: - settings = JWTSettings(secret_key="unit-test-secret") - token = create_refresh_token("user-id-456", settings) +def test_refresh_token_type_mismatch(jwt_settings: JWTSettings) -> None: + token = create_refresh_token("user-id-456", jwt_settings) with pytest.raises(TokenTypeMismatchError): - decode_access_token(token, settings) + decode_access_token(token, jwt_settings) -def test_decode_expired_token() -> None: - settings = JWTSettings(secret_key="unit-test-secret") +def test_decode_expired_token(jwt_settings: JWTSettings) -> None: expired_token = create_access_token( "user-id-789", - settings, + jwt_settings, expires_delta=timedelta(seconds=-5), ) with pytest.raises(TokenExpiredError): - decode_access_token(expired_token, settings) + decode_access_token(expired_token, jwt_settings) -def test_decode_tampered_token() -> None: - settings = JWTSettings(secret_key="unit-test-secret") - token = create_access_token("user-id-321", settings) +def test_decode_tampered_token(jwt_settings: JWTSettings) -> None: + token = create_access_token("user-id-321", jwt_settings) tampered = token[:-1] + ("a" if token[-1] != "a" else "b") with pytest.raises(TokenDecodeError): - decode_access_token(tampered, settings) + decode_access_token(tampered, jwt_settings) diff --git a/tests/test_user_model.py b/tests/test_user_model.py index b03552c..c7d2941 100644 --- a/tests/test_user_model.py +++ b/tests/test_user_model.py @@ -1,5 +1,6 @@ from __future__ import annotations +import secrets from collections.abc import Iterator import pytest @@ -32,16 +33,17 @@ def session(engine) -> Iterator[Session]: def test_user_password_helpers() -> None: + new_password = secrets.token_urlsafe(16) user = User( email="user@example.com", username="example", password_hash=User.hash_password("initial"), ) - user.set_password("new-secret") + user.set_password(new_password) - assert user.password_hash != "new-secret" - assert user.verify_password("new-secret") + assert user.password_hash != new_password + assert user.verify_password(new_password) assert not user.verify_password("wrong")