Java

[Java] 서버에서 Set-Cookie에 담은 RefreshToken이 브라우저로 전송이 안되는 문제 해결

joheamin 2025. 5. 28. 10:00

오늘 토큰만료 시 로그인할때 Cookie에 저장해둔 RefreshToken을 통해 토큰을 재발급을 받으려고 했는데 

문제가 발생했다 .

 

우선 로그인 하였을때 쿠키를 집어넣는 코드를 보았을때 

◾ AuthService
//로그인 함수{
	
	Cookie refreshTokenCookie = new Cookie("refreshToken",tokenDTO.getRefreshToken());

         refreshTokenCookie.setHttpOnly(true);    //JS 접근 불가
         refreshTokenCookie.setSecure(false);      // HTTPS 연결에서만 전송
         refreshTokenCookie.setPath("/");        //모든 경로에서 전송
         refreshTokenCookie.setMaxAge(7 * 24 * 60 * 60); // 7일 유지
         
         response.addCookie(refreshTokenCookie);
}​

 

 

이렇게 하였을 때 브라우저에서 쿠키의 값을 조회하는 요청을 보내었을때

서버에서는 MissingCookieValueException 가 생긴다.

 

 

 

컨트롤러에서 쿠키의 값을 받는 파라미터는 이렇게 정의하였다.

◾ AuthController
//리프레쉬 토큰
    @GetMapping("/getrefresh")
    public ResponseEntity<?> getRefresh(@CookieValue("refreshToken") String refreshToken) {
        return authService.getRefresh(refreshToken);
    }​

 


👉 @CookieValue("refreshToken") : 로그인할때 넣어준 key값으로 쿠키에서 가져온다. 

 

그런데 이 구간에서 가져오지 못하고 MissingCookieValueException 가 발생한것이다..

 


시도해본 방안들 

 

1. withCredentials: true 설정

우선 axios는 크로스 도메인 요청을 보낼때 쿠키를 자동으로 포함하지 않는다.

따라서 요청 시 쿠키를 포함한다는 설정을 해주어야한다.

getRefresh: async () => {
    const result = await axios.get(`${KH_DOMAIN}/auth/getrefresh`, {
      withCredentials: true,   //쿠키 포함 허용 설정
    });
    return result.data;
  },

 

그러나 이 방법은 이미 하였던 방법이였기때문에 체크만 하고 넘어갔다.

 

 

2. 쿠키 저장 시 Secure , Samesite 설정

Cookie refreshTokenCookie = new Cookie("refreshToken",tokenDTO.getRefreshToken());

            refreshTokenCookie.setHttpOnly(true);    //JS 접근 불가
            refreshTokenCookie.setSecure(false);      // HTTPS 연결에서만 전송
            refreshTokenCookie.setPath("/");        //모든 경로에서 전송
            refreshTokenCookie.setMaxAge(7 * 24 * 60 * 60); // 7일 유지

 

브라우저에 저장할 쿠키를 담을때 몇가지 설정해두는 것들이 있다.

이중 setSecure 와 Samesite 설정이 있다.

 

이때 Cookie 객체는 samesite설정을 지원하지 않기때문에 수동 설정을 해줄 경우 직접 setHeader로 넣어주어야한다.

 

response.setHeader("Set-Cookie",
                    "refreshToken=" + tokenDTO.getRefreshToken() +
                            "; Path=/; Max-Age=604800; HttpOnly; SameSite=Lax");

 

❓ Secure

Secure 속성이 true일 경우 HTTPS 연결에서만 쿠키가 전송된다.

그러나 나는 HTTP 연결을 하고있으므로 false를 해야했다.

 

 

❓SameSite

쿠키가 다른 사이트로부터 즉 크로스 도메인으로부터의 요청에도 포함 될 수 있는지를 설정

기본값은 Lax이며 GET요청 등 안전한 도메인에서만 가능하고 none일 경우 모든 요청을 허용한다.

 

단 none일 경우 secure가 반드시 true여야한다.

 

 

따라서 

 

HTTPS 일 경우 

👉 Secure : true  

👉 SameSite : none

 

HTTP 일 경우 

👉 Secure : false

👉 SameSite : Lax

 

이렇게 해야한다.

 

그러나 이 방법도 적용해보았을때 여전히 쿠키가 전송 되지 않았다.

 

 

 

CORS 설정 

CORS 설정에서 쿠키를 포함한 요청을 허용하는 설정을 또 할수가있었다.

◾ WebMvcConfig
@Override
    public void addCorsMappings(CorsRegistry registry) {

        registry.addMapping("/**")
                .allowedOrigins("http://localhost:3000")
                .allowedMethods("GET","POST","PUT","PATCH","DELETE","OPTIONS")
                .allowedHeaders("*")
                .allowCredentials(true)   //쿠키 포함 허용 
                .maxAge(MAX_AGE_SECS);
        ;
    }​

 

 👉.allowCredentials(true) 를 true로 해준다. 

◾ AuthController

@CrossOrigin(origins = "http://localhost:3000", allowCredentials = "true")
public class AuthController {​
👉 컨트롤러에도 true로 명시해준다.

 

 

그래도 다 안된다 .. 😭

 

 

원인을 찾던 중 결국 해결했다.

 

해결❗

로그인 요청에 쿠키 전송을 허용하는 설정을 하지않은것 

 

 

위에서 쿠키의 값을 가져오기 위해 프론트에서 요청을 보낼때  

withCredentials: true 을 설정했었다.

 

나는 이것을 쿠키의 값만 가져올때만 허용을 해주면 되는 줄 알았는데

쿠키에 값을 저장하고 브라우저로 전송하기 위해서도 허용을 해야한다는것을 몰랐었다.

 

//로그인
  login: async (email, password) => {
    const login = {
      email: email,
      password: password,
    };
    const result = await axios.post(`${KH_DOMAIN}/auth/login`, login, {
      withCredentials: true,
    });
    return result.data;
  },

👉 로그인할때도 쿠키 포함 전송을 허용하는 설정 

 

 

이 설정을 해주니 쿠키가 브라우저로 들어오는것이 확인되었다 ... 👏👏👏👏👏