JWT 저장 방식

Kyojun Jin·2024년 6월 18일

Spring

목록 보기
9/12

JWT를 클라이언트에 저장하는 것은 두 가지 방식이 있다.
1. Cookie에 저장해서 매 요청에 포함시키기
2. localStorage 에 저장한 다음 토큰이 필요한 요청의 헤더나 바디에 포함시키기

쿠키

  • 4KB까지만 담을 수 있다. (최소한의 정보 - 로그인 정보, 언어 등)
  • 보안 설정이 가능 (Javascript에서 접근 막거나, 특정 도메인에서만 사용 가능 등)
  • 항상 서버로의 요청에 포함됨
  • 유효 기간 설정 가능

localStorage

  • 5MB까지 담을 수 있다. (사이트 UI 설정 등)
  • 지우기 전까진 영구적으로 데이터 저장됨

쿠키라고 해서 당연히 공격에 완전히 강한 것은 아니다. HttpOnly 옵션을 사용하여 Javascript을 사용한 쿠키 조작이 불가능하게 하고, domain을 설정하여 특정 서버만 쿠키에 대한 접근을 허용할 수 있다. (XSS 공격 막기 위함)

또한 만료 기간을 설정하여 탈취 당하더라도 csrf 공격을 방지할 수 있고, path 를 통해 특정 요청에만 가능하도록 할 수 있다. 프론트와 백 서버가 HTTPS 를 사용한다면 secure를 통해 https에서만 쿠키를 보내도록 할 수 있다.

서버에서 응답을 전달할 때 ResponseCookieSet-Cookie 헤더를 사용하여 보안 설정된 쿠키 (HttpOnly, Secure, Domain 등)를 설정하는 것이 보안 상 낫다고 판단했다.

또한 localStorage 에는 사이트 UI 와 같은 (내가 봤던 페이지, 다크 모드 여부 등) 해커가 관심 없을만한 정보만 담는 것이 좋다.

보안 옵션과 함께 Set-Cookie로 클라이언트로 쿠키를 전송하기 위해선 헤더의 Access-Control-Allow-Credentials이 true여야 한다. 이는 cross-origin HTTP 요청에 보안 설정을 추가하는 것을 허용한다.

예를 들어 axios로 Post 요청을 한다면

axios.post(
  url,
  data,
  {
    withCredentials: true
  }
)

Spring에선

@Bean
    fun corsConfigurer(): WebMvcConfigurer? {
        return object : WebMvcConfigurer {
            override fun addCorsMappings(registry: CorsRegistry) {
                registr
                    .allowCredentials(true)
                    .exposedHeaders("Set-Cookie")
            }
        }
    }

방식으로 서로 쿠키 교환을 보안을 적용하여 주고받을 수 있다.

어쨌든 쿠키의 저장과 교환 방식에 보안 설정을 적용했더라도 언제든 공격 받을 수 있으니
공격 이후의 여파를 줄이기 위하여 유효기간이 짧은 access token과 refresh token, refresh token rotating 을 적용하고
token key 설정 시 secret key 하나 대신 public/private key 을 사용하는 것이 좋다.

0개의 댓글