본문 바로가기

Backend/Spring | SpringBoot

[Spring Security] JWT Cookie 저장 작업

반응형

JWT를 담는 방법은 3가지가 있는데 HTTP Header, Cookie, Session/Local Storage에 담는 방법이다. 각각에 대한 특징은 아래와 같다.

- HTTP Header (Authorization header): 이 방법은 특히 API 사용 시에 자주 사용되며 클라이언트는 각 요청의 Authorization 헤더에 JWT를 포함시켜 서버로 보낸다.
이 방식은 CSRF (Cross-Site Request Forgery) 공격에 취약하지 않으며, 토큰이 로컬 스토리지나 세션 스토리지에 저장되지 않기 때문에 XSS (Cross-Site Scripting) 공격에 대한 노출을 줄일 수 있다.

- Cookie: JWT를 쿠키에 저장한다.
이 방법은 서버와 클라이언트 간에 자동으로 JWT를 전송할 수 있는 장점이 있지만, CSRF 공격에 취약할 수 있다. 쿠키에 JWT를 저장할 경우, 쿠키에 HttpOnly 및 Secure 플래그를 설정하여 XSS 공격으로부터 토큰을 보호해야 한다.

- Session Storage / Local Storage: 웹 스토리지에 JWT를 저장한다.
이 방법은 XSS 공격에 노출될 위험이 있다. 공격자가 스크립팅 공격을 통해 웹 스토리지에 접근할 수 있다면, 저장된 토큰을 탈취할 수 있다.


결론적으로, 가장 안전하고 권장되는 방법은 HTTP 헤더를 사용하는 것이다. 하지만 HTTP 헤더를 이용하면 redirect가 자동으로 처리되면서 인증정보가 손실되기 때문에 redirect를 사용할 수 없다.

따라서 Cookie에 저장하는 것으로 구조를 바꿨다.

 

+ ) 추가 고민했던 것들
Cookie나 Session에 저장하게 되면 Client단에서 JWT를 관리 하는 것이므로 탈취에 대한 보안 이슈가 발생하지 않을까?
- 보안 측면에서 보면 서버가 해킹당한다면 모든 서버가 탈취 될 수 있다. 또한 아키텍쳐 관점에서 보면 토큰이 중앙관리 되기 때문에 MSA에는 맞지 않다.

 

CustomLoginSuccessHandler 수정

import ...;

@Component(value = "customAuthenticationSuccessHandler")
@Slf4j
@RequiredArgsConstructor
public class CustomLoginSuccessHandler implements AuthenticationSuccessHandler {

  ...

  @Override
  public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
      Authentication authentication) throws IOException {

    ...

    // 쿠키에 JWT 추가
    Cookie accessTokenCookie = new Cookie("access_token", accessToken);
    accessTokenCookie.setHttpOnly(true);
    accessTokenCookie.setSecure(true);
    accessTokenCookie.setPath("/");
    response.addCookie(accessTokenCookie);

    ...
}

 

또한 추가적인 보안을 위해 CSRF방지를 위한 토큰을 생성해서 비교하는 방식도 추가해야했다.

 

반응형