Table of Contents
refreshToken 을 안전하게 생성
refreshToken 은 서버에서 Set-Cookie: HttpOnly; Secure; SameSite=Strict 로 클라이언트 전송하는 방법을 설명합니다.
Cookie 생성 유틸리티 클래스
import jakarta.servlet.http.Cookie;
import org.springframework.http.ResponseCookie;
import org.springframework.stereotype.Component;
@Component
public class CookieUtil {
public ResponseCookie createRefreshTokenCookie(String refreshToken, long maxAgeInSeconds) {
return ResponseCookie.from("refreshToken", refreshToken)
.httpOnly(true) // JS 접근 방지
.secure(true) // HTTPS 환경에서만 전송
.path("/") // 모든 경로에서 쿠키 전송
.maxAge(maxAgeInSeconds)
.sameSite("Strict") // CSRF 공격 방어
.build();
}
}
컨트롤러에서 쿠키 전송하기
@RestController
@RequestMapping("/api/auth")
public class AuthController {
private final CookieUtil cookieUtil;
public AuthController(CookieUtil cookieUtil) {
this.cookieUtil = cookieUtil;
}
@PostMapping("/login")
public ResponseEntity<?> login(@RequestBody LoginRequest loginRequest) {
// 1. 사용자 인증 로직 (생략)
// 2. 토큰 생성
String accessToken = "access-token-string";
String refreshToken = "refresh-token-string";
// 3. Refresh Token을 담은 쿠키 생성
ResponseCookie cookie = cookieUtil.createRefreshTokenCookie(refreshToken, 7 * 24 * 60 * 60);
// 4. Access Token은 바디에, Refresh Token은 헤더(쿠키)에 설정
return ResponseEntity.ok()
.header(HttpHeaders.SET_COOKIE, cookie.toString())
.body(new LoginResponse(accessToken));
}
}
클라이언트로부터 쿠키 읽기
@PostMapping("/refresh")
public ResponseEntity<?> refresh(
@CookieValue(name = "refreshToken") String refreshToken) {
// 1. 유효성 검증 및 새로운 Access Token 생성 로직
if (isValid(refreshToken)) {
String newAccessToken = "new-access-token";
return ResponseEntity.ok(new LoginResponse(newAccessToken));
}
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
}
application-dev.yml, application-prd.yml 에서 Secure 처리
Secure(true) 설정 시, http://localhost 환경에서는 쿠키가 저장되지 않을 수 있습니다.
application-dev.yml
auth:
cookie:
secure: false
same-site: Laxs # 로컬 개발 시에는 Strict보다 Lax가 편리할 수 있습니다.
application-prd.yml
auth:
cookie:
secure: true
same-site: Strict
@Component
public class CookieUtil {
@Value("${auth.cookie.secure}")
private boolean isSecure;
@Value("${auth.cookie.same-site}")
private String sameSite;
public ResponseCookie createRefreshTokenCookie(String refreshToken, long maxAgeInSeconds) {
return ResponseCookie.from("refreshToken", refreshToken)
.httpOnly(true)
.secure(isSecure) // yml 설정값 적용
.path("/")
.maxAge(maxAgeInSeconds)
.sameSite(sameSite) // yml 설정값 적용
.build();
}
}
주의사항
-
CORS 설정: 프론트엔드와 백엔드 도메인이 다를 경우, 백엔드 CORS 설정에서 allowCredentials(true)를 반드시 활성화해야 쿠키가 주고받아집니다.
-
Local 테스트: Secure(true) 설정 시, http://localhost 환경에서는 쿠키가 저장되지 않을 수 있습니다. 개발 환경에서는 Secure(false)로 운영하거나 HTTPS 대행 프록시를 사용하세요.