로그인 인증 구조 개선

오형상·2025년 4월 9일
0

CoinToZ

목록 보기
8/9

처음에는 accessToken과 refreshToken을 응답 헤더로 내려주고, 클라이언트에서 JS로 직접 쿠키에 저장하는 방식으로 구현했습니다.
이 방식은 간단하지만 XSS에 취약했습니다.
이를 개선하기 위한 인증 구조 리팩토링을 진행하게 되었습니다.


기존 인증 구조 정리

전체 로그인 흐름

  • 자체 로그인

    • 서버에서 accessToken과 refreshToken을 응답 헤더에 담아 클라이언트로 전달
    • 클라이언트는 accessToken과 refreshToken을 document.cookie를 통해 JS에서 쿠키로 직접 저장
  • OAuth2 로그인

    • 로그인 성공 시 accessToken, refreshToken, email을 redirect URL의 쿼리 파라미터에 담아 전달
    • 클라이언트는 쿼리에서 accessToken과 refreshToken을 파싱해서 document.cookie를 통해 JS에서 쿠키로 직접 저장

RefreshToken 저장 및 검증 (Rtr 방식)

  • 서버는 refreshToken을 Redis에 "RT:{email}" 형식으로 저장
  • AccessToken 만료 시:
    1. 클라이언트는 refreshToken과 email을 요청 헤더에 함께 전송
    2. 서버는 헤더 값과 Redis의 저장값과 일치 여부를 비교
    3. 유효 시 → accessToken + refreshToken 재발급 및 Redis 갱신

로그아웃 처리

  • accessToken은 Redis 블랙리스트로 등록 (남은 만료 시간 기준)
  • Redis에서 해당 email의 refreshToken 삭제

개선 필요성을 느낀 이유

  • JS에서 접근 가능한 쿠키로 인해 XSS 공격에 매우 취약
  • OAuth2 로그인과 자체 로그인 간 인증 흐름이 일관되지 않음

개선된 인증 구조 설계

구조 개요

  • 자체 로그인 시:

    • accessToken → 응답 바디(JSON)
    • refreshToken → Secure + HttpOnly + SameSite=None 쿠키로 전달
  • OAuth2 로그인 시:

    • refreshToken만 Secure + HttpOnly + SameSite=None 쿠키로 전달
    • email을 redirect URL의 쿼리 파라미터에 담아 전달
    • accessToken은 전달하지 않고, 리다이렉트된 페이지에서 재발급 요청을 통해 별도로 발급

클라이언트 저장 방식

  • accessToken → Recoil에 저장 클라이언트 메모리에서만 유지 (브라우저 저장 없음)
  • refreshToken → HttpOnly 쿠키에 저장 (JS 접근 불가)
  • email → localStorage에 저장, refreshToken 재발급 시 Redis 키 식별자 역할

RefreshToken 저장 및 검증 (Rtr 방식 유지)

  • 서버는 refreshToken을 Redis에 "RT:{email}" 형식으로 저장

  • AccessToken 만료 시:
    1. 클라이언트는 email을 요청 헤더에 함께 전송
    2. 서버는 쿠키 값과 Redis의 저장값 일치 여부를 비교
    3. 유효 시 → accessToken + refreshToken 재발급 및 Redis 갱신

로그아웃 처리 방식

  • refreshToken 쿠키 제거 (maxAge = 0)
  • accessToken → Redis 블랙리스트 등록
  • Redis에서 refreshToken 삭제

개선 효과

  • XSS에 강한 구조로 보안성 향상
  • 클라이언트 토큰 저장 방식 통일 (쿠키 + 메모리 기반)
  • 자체 로그인 / OAuth2 흐름 구조 일관성 확보

구조 개선 전후 비교

항목기존 구조개선 구조
토큰 전달 방식헤더 / 쿼리 파라미터응답 바디 + HttpOnly 쿠키
RefreshToken 저장Redis "RT:{email}"동일
RefreshToken 전달 방식클라이언트가 헤더에 직접 포함클라이언트가 쿠키에 저장된 값을 자동 전송
email 전달 방식localStorage 저장 후 헤더로 전달동일
보안성JS 접근 가능 쿠키 → XSS 취약HttpOnly + Secure → XSS 방지
Silent RefreshRefreshToken 헤더 + localStorage 기반 자동 처리쿠키 + localStorage 기반 자동 처리
로그아웃 처리블랙리스트 등록 + Redis 삭제동일 + 쿠키 제거까지 포함

전체 코드 보기


0개의 댓글