토큰 로직 수정

feature-BGM
김성경 2026-05-11 14:01:26 +09:00
parent 97a6384a54
commit 2c8c16c288
5 changed files with 40 additions and 6 deletions

View File

@ -1,12 +1,13 @@
import time
import traceback
from typing import AsyncGenerator
from fastapi import HTTPException
from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine
from sqlalchemy.orm import DeclarativeBase
from app.utils.logger import get_logger
from config import db_settings
import traceback
logger = get_logger("database")
@ -134,15 +135,16 @@ async def get_session() -> AsyncGenerator[AsyncSession, None]:
# )
try:
yield session
except HTTPException:
raise
except Exception as e:
import traceback
await session.rollback()
logger.error(traceback.format_exc())
logger.error(
f"[get_session] ROLLBACK - error: {type(e).__name__}: {e}, "
f"duration: {(time.perf_counter() - start_time)*1000:.1f}ms"
)
raise e
raise
finally:
total_time = time.perf_counter() - start_time
# logger.debug(
@ -170,6 +172,8 @@ async def get_background_session() -> AsyncGenerator[AsyncSession, None]:
# )
try:
yield session
except HTTPException:
raise
except Exception as e:
await session.rollback()
logger.error(
@ -178,7 +182,7 @@ async def get_background_session() -> AsyncGenerator[AsyncSession, None]:
f"duration: {(time.perf_counter() - start_time)*1000:.1f}ms"
)
logger.debug(traceback.format_exc())
raise e
raise
finally:
total_time = time.perf_counter() - start_time
# logger.debug(

View File

@ -306,7 +306,7 @@ class SocialAccountService:
else:
# DB datetime은 naive, now()는 aware이므로 naive로 통일하여 비교
current_time = now().replace(tzinfo=None)
buffer_time = current_time + timedelta(hours=1)
buffer_time = current_time + timedelta(minutes=20)
if account.token_expires_at <= buffer_time:
should_refresh = True

View File

@ -18,10 +18,11 @@ from app.user.services.auth import (
AdminRequiredError,
InvalidTokenError,
MissingTokenError,
TokenExpiredError,
UserInactiveError,
UserNotFoundError,
)
from app.user.services.jwt import decode_token
from app.user.services.jwt import decode_token, is_token_expired
logger = logging.getLogger(__name__)
@ -58,6 +59,9 @@ async def get_current_user(
payload = decode_token(token)
if payload is None:
if is_token_expired(token):
logger.info(f"[AUTH-DEP] Access Token 만료 - token: ...{token[-20:]}")
raise TokenExpiredError()
logger.warning(f"[AUTH-DEP] Access Token 디코딩 실패 - token: ...{token[-20:]}")
raise InvalidTokenError()

View File

@ -92,6 +92,7 @@ from app.user.services.jwt import (
get_access_token_expire_seconds,
get_refresh_token_expires_at,
get_token_hash,
is_token_expired,
)
from app.user.services.kakao import kakao_client
@ -212,6 +213,9 @@ class AuthService:
# 1. 토큰 디코딩 및 검증
payload = decode_token(refresh_token)
if payload is None:
if is_token_expired(refresh_token):
logger.info(f"[AUTH] 토큰 갱신 실패 [1/8 만료] - token: ...{refresh_token[-20:]}")
raise TokenExpiredError()
logger.warning(f"[AUTH] 토큰 갱신 실패 [1/8 디코딩] - token: ...{refresh_token[-20:]}")
raise InvalidTokenError()

View File

@ -116,6 +116,28 @@ def decode_token(token: str) -> Optional[dict]:
return None
def is_token_expired(token: str) -> bool:
"""
토큰이 만료됐는지 확인 (서명/형식은 유효하지만 exp 초과인 경우)
Returns:
True: 서명은 유효하나 만료된 토큰, False: 형식/서명 자체가 잘못된 토큰
"""
try:
payload = jwt.decode(
token,
jwt_settings.JWT_SECRET,
algorithms=[jwt_settings.JWT_ALGORITHM],
options={"verify_exp": False},
)
exp = payload.get("exp")
if exp is None:
return False
return datetime.fromtimestamp(exp) < datetime.now()
except JWTError:
return False
def get_token_hash(token: str) -> str:
"""
토큰의 SHA-256 해시값 생성