Files
core/auth/jwtcodec.py

98 lines
4.1 KiB
Python
Raw Normal View History

2025-07-31 18:55:59 +03:00
import datetime
import logging
from typing import Any, Dict, Optional
2023-10-30 22:00:55 +01:00
2023-10-26 22:38:31 +02:00
import jwt
2023-10-30 22:00:55 +01:00
2025-07-31 18:55:59 +03:00
from settings import JWT_ALGORITHM, JWT_ISSUER, JWT_REFRESH_TOKEN_EXPIRE_DAYS, JWT_SECRET_KEY
2023-10-26 22:38:31 +02:00
class JWTCodec:
2025-07-31 18:55:59 +03:00
"""
Кодировщик и декодировщик JWT токенов.
"""
2022-09-03 13:50:14 +03:00
@staticmethod
2025-07-31 18:55:59 +03:00
def encode(
payload: Dict[str, Any],
secret_key: Optional[str] = None,
algorithm: Optional[str] = None,
expiration: Optional[datetime.datetime] = None,
) -> str | bytes:
"""
Кодирует payload в JWT токен.
Args:
payload (Dict[str, Any]): Полезная нагрузка для кодирования
secret_key (Optional[str]): Секретный ключ. По умолчанию используется JWT_SECRET_KEY
algorithm (Optional[str]): Алгоритм шифрования. По умолчанию используется JWT_ALGORITHM
expiration (Optional[datetime.datetime]): Время истечения токена
Returns:
str: Закодированный JWT токен
"""
logger = logging.getLogger("root")
logger.debug(f"[JWTCodec.encode] Кодирование токена для payload: {payload}")
# Используем переданные или дефолтные значения
secret_key = secret_key or JWT_SECRET_KEY
algorithm = algorithm or JWT_ALGORITHM
# Если время истечения не указано, устанавливаем дефолтное
if not expiration:
expiration = datetime.datetime.now(datetime.timezone.utc) + datetime.timedelta(
days=JWT_REFRESH_TOKEN_EXPIRE_DAYS
)
logger.debug(f"[JWTCodec.encode] Время истечения не указано, устанавливаем срок: {expiration}")
# Формируем payload с временными метками
payload.update(
{"exp": int(expiration.timestamp()), "iat": datetime.datetime.now(datetime.timezone.utc), "iss": JWT_ISSUER}
)
2025-05-29 12:37:39 +03:00
2025-05-20 00:00:24 +03:00
logger.debug(f"[JWTCodec.encode] Сформирован payload: {payload}")
2025-05-29 12:37:39 +03:00
2022-10-23 12:33:28 +03:00
try:
2025-07-31 18:55:59 +03:00
# Используем PyJWT для кодирования
encoded = jwt.encode(payload, secret_key, algorithm=algorithm)
token_str = encoded.decode("utf-8") if isinstance(encoded, bytes) else encoded
return token_str
2022-10-23 12:33:28 +03:00
except Exception as e:
2025-07-31 18:55:59 +03:00
logger.warning(f"[JWTCodec.encode] Ошибка при кодировании JWT: {e}")
2025-05-20 00:00:24 +03:00
raise
2022-09-03 13:50:14 +03:00
@staticmethod
2025-07-31 18:55:59 +03:00
def decode(
token: str,
secret_key: Optional[str] = None,
algorithms: Optional[list] = None,
) -> Dict[str, Any]:
"""
Декодирует JWT токен.
Args:
token (str): JWT токен
secret_key (Optional[str]): Секретный ключ. По умолчанию используется JWT_SECRET_KEY
algorithms (Optional[list]): Список алгоритмов. По умолчанию используется [JWT_ALGORITHM]
Returns:
Dict[str, Any]: Декодированный payload
"""
logger = logging.getLogger("root")
logger.debug("[JWTCodec.decode] Декодирование токена")
# Используем переданные или дефолтные значения
secret_key = secret_key or JWT_SECRET_KEY
algorithms = algorithms or [JWT_ALGORITHM]
2025-05-29 12:37:39 +03:00
2022-10-23 12:33:28 +03:00
try:
2025-07-31 18:55:59 +03:00
# Используем PyJWT для декодирования
decoded = jwt.decode(token, secret_key, algorithms=algorithms)
return decoded
2022-11-01 00:05:10 +03:00
except jwt.ExpiredSignatureError:
2025-07-31 18:55:59 +03:00
logger.warning("[JWTCodec.decode] Токен просрочен")
raise
except jwt.InvalidTokenError as e:
logger.warning(f"[JWTCodec.decode] Ошибка при декодировании JWT: {e}")
raise