diff --git a/auth/utils.py b/auth/utils.py index 4bded89..9615d69 100644 --- a/auth/utils.py +++ b/auth/utils.py @@ -34,9 +34,17 @@ def verify_password(password: str, hash_: str) -> bool: class JWTUtils: """JWT token utilities""" + @staticmethod + def _get_secret_key() -> str: + secret = os.getenv('JWT_SECRET_KEY') + if not secret: + raise ValueError("JWT_SECRET_KEY environment variable is not set") + return secret + @staticmethod def create_tokens(user_id: str, username: str) -> Tuple[str, str]: """Create access and refresh tokens""" + secret_key = JWTUtils._get_secret_key() access_token = jwt.encode( { 'user_id': user_id, @@ -44,7 +52,7 @@ def create_tokens(user_id: str, username: str) -> Tuple[str, str]: 'exp': datetime.utcnow() + timedelta(hours=1), 'type': 'access' }, - os.getenv('JWT_SECRET_KEY', 'jwt-secret'), + secret_key, algorithm='HS256' ) @@ -55,7 +63,7 @@ def create_tokens(user_id: str, username: str) -> Tuple[str, str]: 'exp': datetime.utcnow() + timedelta(days=30), 'type': 'refresh' }, - os.getenv('JWT_SECRET_KEY', 'jwt-secret'), + secret_key, algorithm='HS256' ) @@ -65,9 +73,10 @@ def create_tokens(user_id: str, username: str) -> Tuple[str, str]: def decode_token(token: str) -> Optional[dict]: """Decode and verify token""" try: + secret_key = JWTUtils._get_secret_key() payload = jwt.decode( token, - os.getenv('JWT_SECRET_KEY', 'jwt-secret'), + secret_key, algorithms=['HS256'] ) return payload diff --git a/tests/test_auth_utils.py b/tests/test_auth_utils.py new file mode 100644 index 0000000..1112a1f --- /dev/null +++ b/tests/test_auth_utils.py @@ -0,0 +1,44 @@ +import os +import sys +from unittest.mock import MagicMock + +# Mock external dependency cache_db before auth.utils is imported +sys.modules['cache_db'] = MagicMock() +sys.modules['cache_db.redis_client'] = MagicMock() +sys.modules['cache_db.models'] = MagicMock() + +import pytest +from auth.utils import JWTUtils + + +def test_jwt_utils_requires_secret_key(): + """Test that JWTUtils raises ValueError when JWT_SECRET_KEY is not set.""" + os.environ.pop("JWT_SECRET_KEY", None) + with pytest.raises(ValueError, match="JWT_SECRET_KEY environment variable is not set"): + JWTUtils.create_tokens("user123", "testuser") + + with pytest.raises(ValueError, match="JWT_SECRET_KEY environment variable is not set"): + JWTUtils.decode_token("some.jwt.token") + + +def test_jwt_utils_create_and_decode_tokens(): + """Test creating and decoding JWT tokens when JWT_SECRET_KEY is configured.""" + os.environ["JWT_SECRET_KEY"] = "super-secret-key-for-testing" + try: + access_token, refresh_token = JWTUtils.create_tokens("user123", "testuser") + assert access_token is not None + assert refresh_token is not None + + decoded = JWTUtils.decode_token(access_token) + assert decoded is not None + assert decoded["user_id"] == "user123" + assert decoded["username"] == "testuser" + assert decoded["type"] == "access" + + decoded_refresh = JWTUtils.decode_token(refresh_token) + assert decoded_refresh is not None + assert decoded_refresh["user_id"] == "user123" + assert decoded_refresh["username"] == "testuser" + assert decoded_refresh["type"] == "refresh" + finally: + os.environ.pop("JWT_SECRET_KEY", None)