""" JWT 토큰 유틸리티 Access Token과 Refresh Token의 생성, 검증, 해시 기능을 제공합니다. """ import hashlib from datetime import datetime, timedelta from typing import Optional from jose import JWTError, jwt from app.utils.timezone import now from config import jwt_settings def create_access_token(user_uuid: str) -> str: """ JWT 액세스 토큰 생성 Args: user_uuid: 사용자 UUID Returns: JWT 액세스 토큰 문자열 """ expire = now() + timedelta( minutes=jwt_settings.JWT_ACCESS_TOKEN_EXPIRE_MINUTES ) to_encode = { "sub": user_uuid, "exp": expire, "type": "access", } return jwt.encode( to_encode, jwt_settings.JWT_SECRET, algorithm=jwt_settings.JWT_ALGORITHM, ) def create_refresh_token(user_uuid: str) -> str: """ JWT 리프레시 토큰 생성 Args: user_uuid: 사용자 UUID Returns: JWT 리프레시 토큰 문자열 """ expire = now() + timedelta( days=jwt_settings.JWT_REFRESH_TOKEN_EXPIRE_DAYS ) to_encode = { "sub": user_uuid, "exp": expire, "type": "refresh", } return jwt.encode( to_encode, jwt_settings.JWT_SECRET, algorithm=jwt_settings.JWT_ALGORITHM, ) def decode_token(token: str) -> Optional[dict]: """ JWT 토큰 디코딩 Args: token: JWT 토큰 문자열 Returns: 디코딩된 페이로드 딕셔너리, 실패 시 None """ try: payload = jwt.decode( token, jwt_settings.JWT_SECRET, algorithms=[jwt_settings.JWT_ALGORITHM], ) return payload except JWTError: return None def get_token_hash(token: str) -> str: """ 토큰의 SHA-256 해시값 생성 리프레시 토큰을 DB에 저장할 때 원본 대신 해시값을 저장합니다. Args: token: 해시할 토큰 문자열 Returns: 토큰의 SHA-256 해시값 (64자 hex 문자열) """ return hashlib.sha256(token.encode()).hexdigest() def get_refresh_token_expires_at() -> datetime: """ 리프레시 토큰 만료 시간 계산 Returns: 리프레시 토큰 만료 datetime (로컬 시간) """ return now().replace(tzinfo=None) + timedelta( days=jwt_settings.JWT_REFRESH_TOKEN_EXPIRE_DAYS ) def get_access_token_expire_seconds() -> int: """ 액세스 토큰 만료 시간(초) 반환 Returns: 액세스 토큰 만료 시간 (초) """ return jwt_settings.JWT_ACCESS_TOKEN_EXPIRE_MINUTES * 60