Notice
Recent Posts
Recent Comments
Link
«   2025/04   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30
Tags
more
Archives
Today
Total
관리 메뉴

DS's TechBlog

[Cookie] 쿠키에 담은 리프레시 토큰이 서버로 넘어오지 않는 문제 본문

Web

[Cookie] 쿠키에 담은 리프레시 토큰이 서버로 넘어오지 않는 문제

dsjo 2025. 1. 7. 23:41

JWT를 사용해 인증 및 인가를 구현한 프로젝트에서, 리프레시 토큰쿠키에 저장하여 클라이언트 요청 시 자동으로 포함되도록 설정했습니다. 하지만 서버로 리프레시 토큰이 전달되지 않는 문제가 발생했습니다. 이번 글에서는 이 이슈의 원인과 해결 방법을 탐구해 보겠습니다.

 

리프레시 토큰 쿠키 설정

 스프링부트에서는 HttpServletResponse를 사용하여 쿠키를 설정할 수 있습니다. 다음과 같이 리프레시 토큰을 쿠키에 저장하였습니다.

    // 토큰을 발급하는 메서드
    @Override
    @Transactional
    public void issueToken(HttpServletResponse response, String userId, String role) {
        String accessToken = jwtUtil.createJwt(LoginConstants.ACCESS_TOKEN, userId, role, LoginConstants.ACCESS_TOKEN_EXPIRATION_TIME_MS);
        String refreshToken = jwtUtil.createJwt(LoginConstants.REFRESH_TOKEN, userId, role, LoginConstants.REFRESH_TOKEN_EXPIRATION_TIME_MS);

        refreshTokenService.registerRefreshToken(refreshToken, userId);

        response.setHeader(LoginConstants.ACCESS_TOKEN, "Bearer " + accessToken);
        response.addCookie(CookieUtil.createCookie(LoginConstants.REFRESH_TOKEN, refreshToken, (int) LoginConstants.REFRESH_TOKEN_EXPIRATION_TIME_S));
    }
    
    // 쿠키를 생성하는 메서드
    public static Cookie createCookie(String key, String value, int maxAge) {
        Cookie cookie = new Cookie(key, value);
        cookie.setMaxAge(maxAge);
        cookie.setPath("/");
        cookie.setHttpOnly(true);

        return cookie;
    }

이때, 브라우저에 저장된 쿠키는 개발자 도구에서 확인할 수 있습니다.

문제 상황

브라우저에 저장된 쿠키가 요청에 자동적으로 포함되기를 기대했습니다. 하지만, 서버에서 리프레시 토큰 쿠키를 읽을 수 없었습니다. 네트워크 탭을 확인하니 토큰이 요청에 포함되지 않았습니다.

 

문제 원인

리프레시 토큰 쿠키가 서버로 전달되지 않는 문제의 주요 원인은 Cookie의 SameSite 속성 설정에 있었습니다.

 

SameSite 속성이란?

SameSite 속성은 웹 애플리케이션의 쿠키가 크로스사이트 요청(Cross-Site Request)에서 어떻게 동작할지를 지정하는 보안 메커니즘입니다. 이 속성은 주로 CSRF(Cross-Site Request Forgery) 공격을 방지하기 위해 도입되었습니다. SameSite 속성에는 다음과 같은 값들이 있습니다:

 

  • Strict: 동일한 사이트에서 발생한 요청에 대해서만 쿠키가 전송됩니다. 크로스사이트 요청에는 절대 쿠키가 포함되지 않습니다.
  • Lax: 일부 크로스사이트 요청(예: 링크를 통한 GET 요청)에는 쿠키가 전송될 수 있지만, POST 요청 등 중요한 변경을 일으키는 요청에는 쿠키가 포함되지 않습니다. (Chrome 브라우저의 기본 속성)
  • None: 모든 요청에 대해 쿠키가 전송됩니다. 단, 이 경우 반드시 Secure 속성을 함께 설정하여 HTTPS 연결에서만 쿠키가 전송되도록 해야 합니다.
출처: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie

 

제 프로젝트의 경우에, 프론트엔드 서버와 백엔드 서버가 따로 존재하고, 백엔드에는 도메인이 없고 프론트엔드에는 도메인이 설정되어 있습니다. 이때, Chrome 브라우저의 기본 SameSite 속성인 `Lax` 설정에 따라서 크로스사이트 요청 시 쿠키의 자동 전송을 제한하므로, 프론트엔드에서 서버로의 요청에 리프레시 토큰 쿠키가 포함되지 않았습니다.

 

해결 방법

  1. SameSite 속성을 `None`으로 설정하고 `Secure` 속성 추가: SameSite 속성을 `None`으로 설정하면 크로스사이트 요청에서 쿠키가 전송되도록 할 수 있습니다.
  2. 서브 도메인 or 동일 도메인 사용: 서브 도메인이나 동일 도메인을 사용한다면, `Lax` 설정에도 쿠키가 전송됩니다.

위의 두 가지 방법 중 저는 2번 방법을 선택하였습니다.

프론트엔드와 백엔드를 최종적으로 같은 서버에서 돌릴 계획이었기에, 구매한 domain을 활용하여 'www.example.com', 'www.example.com/api'로 프론트엔드와 백엔드의 엔드포인트를 나누었고, 동일 사이트 요청에 따라 정상적으로 쿠키가 전송될 수 있도록 했습니다.

또한, 첫 번째 방법은 HTTPS를 통해서만 쿠키가 전송되도록 보장할 수는 있지만, CSRF 공격을 완전히 방지할 수 없어 보안에 취약하다는 단점이 있다고 판단했습니다.

 

 

이번 글에서는 JWT 기반 인증 시스템에서 리프레시 토큰 쿠키가 서버로 전송되지 않는 문제를 쿠키의 SameSite 속성을 위주로 원인을 분석하고, 이를 해결하기 위한 방법을 알아보았습니다. 프로젝트마다 환경이 다를 수 있는 만큼, 쿠키 설정 시에는 보안과 요구 사항을 균형 있게 고려해야 한다고 생각합니다. 읽어주셔서 감사합니다.

'Web' 카테고리의 다른 글

[Layered Architecture] 대체 DTO는 어디에 두어야 하는가?  (0) 2024.12.15