토큰 로직 수정
parent
97a6384a54
commit
2c8c16c288
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
||||
|
|
|
|||
|
|
@ -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 해시값 생성
|
||||
|
|
|
|||
Loading…
Reference in New Issue