"""JWT + TOTP 2FA 인증""" from datetime import datetime, timedelta, timezone import pyotp from jose import JWTError, jwt from passlib.context import CryptContext from core.config import settings pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") # JWT 설정 ALGORITHM = "HS256" ACCESS_TOKEN_EXPIRE_MINUTES = 15 REFRESH_TOKEN_EXPIRE_DAYS = 7 def verify_password(plain: str, hashed: str) -> bool: return pwd_context.verify(plain, hashed) def hash_password(password: str) -> str: return pwd_context.hash(password) def create_access_token(subject: str) -> str: expire = datetime.now(timezone.utc) + timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES) payload = {"sub": subject, "exp": expire, "type": "access"} return jwt.encode(payload, settings.jwt_secret, algorithm=ALGORITHM) def create_refresh_token(subject: str) -> str: expire = datetime.now(timezone.utc) + timedelta(days=REFRESH_TOKEN_EXPIRE_DAYS) payload = {"sub": subject, "exp": expire, "type": "refresh"} return jwt.encode(payload, settings.jwt_secret, algorithm=ALGORITHM) def decode_token(token: str) -> dict | None: try: return jwt.decode(token, settings.jwt_secret, algorithms=[ALGORITHM]) except JWTError: return None def verify_totp(code: str) -> bool: """TOTP 코드 검증""" if not settings.totp_secret: return True # TOTP 미설정 시 스킵 totp = pyotp.TOTP(settings.totp_secret) return totp.verify(code)