refresh token 수정 .
parent
e29e10eb29
commit
bc777ba66c
|
|
@ -291,15 +291,22 @@ def add_exception_handlers(app: FastAPI):
|
|||
# SocialException 핸들러 추가
|
||||
from app.social.exceptions import SocialException
|
||||
|
||||
from app.social.exceptions import TokenExpiredError
|
||||
|
||||
@app.exception_handler(SocialException)
|
||||
def social_exception_handler(request: Request, exc: SocialException) -> Response:
|
||||
logger.debug(f"Handled SocialException: {exc.__class__.__name__} - {exc.message}")
|
||||
return JSONResponse(
|
||||
status_code=exc.status_code,
|
||||
content={
|
||||
content = {
|
||||
"detail": exc.message,
|
||||
"code": exc.code,
|
||||
},
|
||||
}
|
||||
# TokenExpiredError인 경우 재연동 정보 추가
|
||||
if isinstance(exc, TokenExpiredError):
|
||||
content["platform"] = exc.platform
|
||||
content["reconnect_url"] = f"/social/oauth/{exc.platform}/connect"
|
||||
return JSONResponse(
|
||||
status_code=exc.status_code,
|
||||
content=content,
|
||||
)
|
||||
|
||||
@app.exception_handler(status.HTTP_500_INTERNAL_SERVER_ERROR)
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ class YouTubeOAuthClient(BaseOAuthClient):
|
|||
"response_type": "code",
|
||||
"scope": " ".join(YOUTUBE_SCOPES),
|
||||
"access_type": "offline", # refresh_token 받기 위해 필요
|
||||
"prompt": "select_account", # 계정 선택만 표시 (이전 동의 유지)
|
||||
"prompt": "select_account", # 계정 선택만 표시 (동의 화면은 최초 1회만)
|
||||
"state": state,
|
||||
}
|
||||
url = f"{self.AUTHORIZATION_URL}?{urlencode(params)}"
|
||||
|
|
|
|||
|
|
@ -498,35 +498,34 @@ class SocialAccountService:
|
|||
Raises:
|
||||
TokenExpiredError: 토큰 갱신 실패 시 (재연동 필요)
|
||||
"""
|
||||
# refresh_token이 없으면 갱신 불가 → 재연동 필요
|
||||
if not account.refresh_token:
|
||||
logger.warning(
|
||||
f"[SOCIAL] refresh_token 없음, 재연동 필요 - account_id: {account.id}"
|
||||
)
|
||||
raise TokenExpiredError(platform=account.platform)
|
||||
|
||||
# 만료 시간 확인 (만료 10분 전이면 갱신, 만료 시간 없어도 갱신 시도)
|
||||
should_refresh = False
|
||||
# 만료 시간 확인
|
||||
is_expired = False
|
||||
if account.token_expires_at is None:
|
||||
logger.info(
|
||||
f"[SOCIAL] token_expires_at 없음, 갱신 시도 - account_id: {account.id}"
|
||||
)
|
||||
should_refresh = True
|
||||
is_expired = True
|
||||
else:
|
||||
# DB datetime은 naive, now()는 aware이므로 naive로 통일하여 비교
|
||||
current_time = now().replace(tzinfo=None)
|
||||
buffer_time = current_time + timedelta(minutes=10)
|
||||
if account.token_expires_at <= buffer_time:
|
||||
is_expired = True
|
||||
|
||||
# 아직 유효하면 그대로 사용
|
||||
if not is_expired:
|
||||
return account.access_token
|
||||
|
||||
# 만료됐는데 refresh_token이 없으면 재연동 필요
|
||||
if not account.refresh_token:
|
||||
logger.warning(
|
||||
f"[SOCIAL] access_token 만료 + refresh_token 없음, 재연동 필요 - "
|
||||
f"account_id: {account.id}"
|
||||
)
|
||||
raise TokenExpiredError(platform=account.platform)
|
||||
|
||||
# refresh_token으로 갱신
|
||||
logger.info(
|
||||
f"[SOCIAL] 토큰 만료 임박, 갱신 시작 - account_id: {account.id}"
|
||||
)
|
||||
should_refresh = True
|
||||
|
||||
if should_refresh:
|
||||
return await self._refresh_account_token(account, session)
|
||||
|
||||
return account.access_token
|
||||
|
||||
async def _refresh_account_token(
|
||||
self,
|
||||
account: SocialAccount,
|
||||
|
|
|
|||
Loading…
Reference in New Issue