Skip to content

fix: 서버가 세션을 무효화한 기기가 죽은 토큰으로 무한 리다이렉트 루프에 빠짐 #467

Description

@iOdiO89

재현

  1. 웹+앱 등 2기기에 동일 계정 로그인
  2. 기기 A에서 회원 탈퇴
  3. 기기 B에서 아무 화면 사용 → /home/login 무한 리다이렉트 + refresh 재시도 루프

서버 로그: 모든 API가 401(COMMON-UNAUTHORIZED), refresh도 401(AUTH-001, "탈퇴 유저" 사유)이 초 단위로 반복.

원인 — 죽은 쿠키를 아무도 안 지움 + 로그인 페이지가 로컬 exp만 믿음

탈퇴 직후 access 토큰은 exp상 유효(최대 15분)하지만 서버에서는 무효인 상태가 된다. 이 상태에서:

  1. /home 쿼리 401 → 인터셉터가 refresh 시도 → 401 → /login?redirect=/home&action=session-expired 리다이렉트. 이때 쿠키를 지우지 않음 (apis/client.ts 갱신 실패 catch)
  2. 로그인 페이지: action이 있어 홈 포워딩은 스킵하지만, LoginButtons가 토스트 후 router.replaceaction 파라미터를 벗겨냄
  3. /login?redirect=/home(action 없음) 재진입: login/page.tsx:26-33죽은 access 쿠키의 role=MEMBER만 보고 redirect(ROUTES.HOME) → 홈 복귀
  4. 1번으로 → 무한

proxy(#451의 쿠키 폐기)도 개입 못 한다 — isTokenValid가 로컬 exp만 검사해 "access 유효 → 통과"로 판단하므로 갱신 자체를 시도하지 않는다.

같은 이유로 Apple 동의철회, (이론상) 세션 재사용 감지 등 "서버가 세션을 죽였는데 클라는 모르는" 모든 경로에서 동일 루프가 발생할 수 있다. 배포 직후 레거시 토큰 401은 access가 이미 만료된 뒤라 proxy 경로(#451)로 정리되므로 이 루프에 해당하지 않는다.

수정

(a) proxy.tssession-expired/withdrawn-account action으로 /login에 도착하면 인증 쿠키 폐기 (Set-Cookie Max-Age=0). 브라우저 httpOnly 쿠키는 JS로 지울 수 없어 이 지점이 유일한 정리 위치. 루프의 3번 고리(멤버 오인 → 홈 포워딩)를 끊는다.

(b) apis/client.ts — 갱신 실패(catch) 시 deleteCookie + 웹뷰면 WEB_REQ_LOGOUT 브릿지로 네이티브 TokenStorage까지 정리. 웹뷰(JS 쿠키)는 즉시 정리되고, 앱 재시작 시 죽은 토큰이 재주입되는 것도 방지.

서버 협의 (별도)

refresh 거부 code가 탈퇴 유저여도 AUTH-001(일반 만료)로 내려와 클라가 "탈퇴한 계정" 안내를 할 수 없음 → 탈퇴 사유일 때 USER-003으로 내려줄 수 있는지 협의. 루프 자체는 위 (a)+(b)로 해결되며 이건 안내 문구 정확성 문제.

연관 이슈

Metadata

Metadata

Assignees

Labels

fixSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions