o2o-castad-backend/app/user/services/jwt.py

123 lines
2.7 KiB
Python

"""
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