Loading src/portal_service/adapters/keycloak/token_verifier.py +1 −0 Changes for src/portal_service/adapters/keycloak/token_verifier.py: 1 added line, 0 removed lines. Original line number Diff line number Diff line Loading @@ -87,6 +87,7 @@ class KeycloakTokenVerifier: # The realm's audience mapper puts our client_id in `aud`, so a token minted # for another client in the same realm is refused here. audience=self._settings.client_id, leeway=30, ) except jwt.ExpiredSignatureError as exc: raise TokenExpiredError("Token has expired") from exc Loading tests/unit/test_verification.py +9 −1 Changes for tests/unit/test_verification.py: 9 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -3,6 +3,7 @@ JWT verification: the real decode path (signature, issuer, expiry, claims) and what happens when Keycloak's signing keys cannot be fetched. """ import time from typing import Callable import jwt Loading @@ -29,7 +30,14 @@ def test_decode_expired_token_raises( verifier: KeycloakTokenVerifier, make_token: Callable[..., str] ) -> None: with pytest.raises(TokenExpiredError): verifier.verify_access_token(make_token(expires_in=-10)) verifier.verify_access_token(make_token(expires_in=-60)) def test_decode_tolerates_clock_skew( verifier: KeycloakTokenVerifier, make_token: Callable[..., str] ) -> None: claims = verifier.verify_access_token(make_token(iat=int(time.time()) + 5)) assert claims.sub == "user-123" def test_decode_wrong_issuer_raises( Loading Loading
src/portal_service/adapters/keycloak/token_verifier.py +1 −0 Changes for src/portal_service/adapters/keycloak/token_verifier.py: 1 added line, 0 removed lines. Original line number Diff line number Diff line Loading @@ -87,6 +87,7 @@ class KeycloakTokenVerifier: # The realm's audience mapper puts our client_id in `aud`, so a token minted # for another client in the same realm is refused here. audience=self._settings.client_id, leeway=30, ) except jwt.ExpiredSignatureError as exc: raise TokenExpiredError("Token has expired") from exc Loading
tests/unit/test_verification.py +9 −1 Changes for tests/unit/test_verification.py: 9 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -3,6 +3,7 @@ JWT verification: the real decode path (signature, issuer, expiry, claims) and what happens when Keycloak's signing keys cannot be fetched. """ import time from typing import Callable import jwt Loading @@ -29,7 +30,14 @@ def test_decode_expired_token_raises( verifier: KeycloakTokenVerifier, make_token: Callable[..., str] ) -> None: with pytest.raises(TokenExpiredError): verifier.verify_access_token(make_token(expires_in=-10)) verifier.verify_access_token(make_token(expires_in=-60)) def test_decode_tolerates_clock_skew( verifier: KeycloakTokenVerifier, make_token: Callable[..., str] ) -> None: claims = verifier.verify_access_token(make_token(iat=int(time.time()) + 5)) assert claims.sub == "user-123" def test_decode_wrong_issuer_raises( Loading