JWT를 사용한 로그인 api 에서 나타난 현상이다.
Refresh Token
은 쿠키에 넣고
Access Token
은 header에 Authorization 이름으로 클라이언트에 보내줘야한다.
Access Token
은 잘 전달 받았지만 Refresh Token 이 오지 않았다.
...
String accessToken = JwtUtils.generateAccessToken(userClaimsDto);
String refreshToken = JwtUtils.generateRefreshToken(userClaimsDto);
Optional<UserAuthentication> userAuth = getUserAuthentication(userDetails, type);
upsertRefreshTokenToDatabase(userDetails, userAuth, refreshToken);
response.addHeader(AUTH_HEADER, TOKEN_TYPE + accessToken);
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
response.addCookie(getRefreshTokenCookie(refreshToken)); // 쿠키
response.setCharacterEncoding("UTF-8");
...
private Cookie getRefreshTokenCookie(String refreshToken) {
Cookie cookie = new Cookie(REFRESH_TOKEN, refreshToken);
cookie.setHttpOnly(true);
cookie.setMaxAge(EXPIRATION);
return cookie;
}
도메인과 경로를 지정해주지 않아서 생긴 문제이다.
찾아보니 지정해주지 않으면 디폴트 값이 지정된다고 하는데 잘 적용이 되지 않았던 것 같다.
private Cookie getRefreshTokenCookie(String refreshToken) {
Cookie cookie = new Cookie(REFRESH_TOKEN, refreshToken);
cookie.setHttpOnly(true);
cookie.setMaxAge(EXPIRATION);
// 추가
cookie.setDomain("localhost"); // 도메인 설정
cookie.setPath("/"); // 도메인의 모든 페이지 경로에 쿠키를 전송하도록 지정
//
return cookie;
}
클라이언트와 서버 모두 로컬 환경일때는 제대로 동작하였다.
그러나 클라이언트를 로컬로 실행하고 서버를 배포 서버를 사용해서 테스트 해봤을 때
이전처럼 Refresh Token이 클라이언트로 전달되지 않았다.물론 도메인을 배포한 클라이언트의 도메인으로 설정해줬다.
클라이언트와 서버의 도메인이 달라서 생긴 문제이다.
쿠키의
SameSite
정책을 잘 몰랐다.자바의
Cookie
클래스에는SameSite
설정하는 메서드가 따로 없어서
ResponseCookie
클래스를 사용했다.
SameSite를 None 으로 설정했다.
SameSite의 관한 설명은 포스팅을 하고 따로 참조하겠다.
private ResponseCookie getRefreshTokenCookie(String refreshToken) {
ResponseCookie cookie = ResponseCookie.from(REFRESH_TOKEN, refreshToken)
.maxAge(EXPIRATION)
.path("/")
.httpOnly(true)
.secure(true)
.sameSite("None") // sameSite 정책을 None 으로 설정
.build();
return cookie;
}
[Web] 쿠키의 SameSite 과 CSRF 공격 의 일부이다.
개발 시 사용했던 브라우저는 크롬이다.
크롬 역시SameSite
정책이 적용되어있고 기본값은Lax
라고 한다.토큰 재발급 요청 메서드는
Post
이다.
그래서 안됐던 것 같다.이 정책을 잘 몰라서 문제를 해결하기 위해 급히
SameSite
를None
으로 설정했다.보안을 위해서 백엔드 팀에게 get으로 바꾸자고 요청해볼 생각이다.
아 저는 이 프로젝트에서 프론트앤드 팀인데 이쪽 담당하신 분이 코로나에 걸리셔서
제가 오류를 해결하려고 시도해봤습니다..ㅎ