Projects/[Final] Shopping Mall Project

[트러블슈팅] 로그아웃 API에서 인증, 무효화 구현하기

montmer27 2026. 4. 27. 09:12

[Github Repository]

https://github.com/all-in-market/mvp-api-server/commit/22f8f094a5edd45f399487be55c40573861ff50d

 

Merge pull request #142 from all-in-market/fix/logout · all-in-market/mvp-api-server@22f8f09

Fix/logout

github.com

 

[AS-IS]

  • 로그인 시 액세스 토큰(1시간 유효) + 리프레쉬 토큰(1주일 유효) 발급
  • 리프레쉬 토큰은 UUID로 생성한 뒤, "refresh:{id}" 키로 Redis에 TTL 1주일 설정하여 저장
  • [테스트] 구매자 인증 컨트롤러, 서비스 테스트 통과
  • 액세스 토큰 만료 시 호출하는 "/auth/refresh" 엔드포인트에 연결된 컨트롤러 메서드 없음
  • 로그아웃 시 액세스 토큰 블랙리스트 등록 + 리프레쉬 토큰 Redis에서 키 삭제 기능 없음

리프레쉬 토큰을 Redis에 저장

[TO-BE]

  • 액세스 토큰 만료 시 리프레쉬 토큰으로 갱신하는 "/auth/refresh" api 구현
    • buyer [x] 
    • seller [ ] 
    • admin [ ]
  • 로그아웃 시 액세스 토큰 블랙리스트 등록 + 리프레쉬 토큰 Redis에서 삭제

[STEPS]

  • 현행 리프레쉬 토큰 Redis 저장 방식으로는 리프레쉬 토큰으로 키에 담긴 사용자 id를 추출할 수 없음
    • 키에 UUID를 포함시켜 저장하거나, 리프레쉬 토큰 저장 방식을 UUID에서 JWT로 바꿔야 함.
    • 선택지: 키에 UUID를 포함시켜 저장 "refresh:{UUID}: {userId}"
    • 근거: 토큰에 정보가 없어 보안성 우수, UUID 그대로 키 사용하여 간편함

키 구조를 "refresh:{UUID}:{userId}" 구조로 변경

  • "/auth/refresh" 엔드포인트에 액세스 토큰 갱신 메서드 구현 및 테스트 코드 작성 완료

  • 현재 코드에서 로그아웃 시 액세스 토큰 블랙리스트 등록하는 코드 있는지 확인
    • JwtAuthenticationFilter : 요청마다 "blacklist:" + token 키로 Redis를 조회해 블랙리스트 여부를 검사하는 키는 있음
    • BuyerAuthController: 없음
    • SellerAuthController: 있으나 200 OK만 반환

  • 로그아웃 시 액세스 토큰 블랙리스트 등록하도록 구현

BuyerAuthService.java
BuyerAuthController.java

  • 문제 발견
    • 1. 쿠키 경로 문제: 리프레시 토큰 쿠키가 path = /auth/refresh로 제한 -> /auth/logout 요청 시 브라우저가 쿠키를 포함하지 않음. refreshToken 파라미터가 null이 되어 리프레시 토큰이 삭제되지 않음. 
    • 2. 리프레시 토큰 로테이션 없음: /auth/refresh 호출 시 새 액세스 토큰만 발급하고 사용한 리프레시 토큰을 교체하지 않음. 토큰 탈취 시 7일간 무제한 재발급 가능
    • 3. 리프레시 비즈니스 로직이 컨트롤러에 직접 작성돼 있어, 서비스로 이동 필요
  • 수정
    • BuyerAuthService.refresh 메서드 추가: Redis에서 userId 조회, 기존 토큰 삭제, 새 토큰 발급 및 저장, LoginResult 반환
    • BuyerAuthController
      • 쿠키 path("/auth/refresh) -> path("/auth" 3곳 수정 (login 응답, refresh 응답, logout 만료 쿠키)
      • /auth/refresh 엔드포인트를 buyerAuthService.refresh()에 위임하도록 전면 교체
      • 불필요한 RedisTemplate, JwtProvider 필드 주입 제거
    • BuyerAuthServiceTest, BuyerAuthControllerTest 수정
  • Seller에도 동일한 기능 적용
  • 테스트 코드 작성 및 성공 확인