Back to blog

February 22, 2023

JWT, 안전하게 사용하는 방법은?

적용하기엔 간단하지만 안전하게 사용하기 어려운 JWT에 대해 고려할 사항을 살펴봅니다.

시작하며

JWT(JSON Web Token)는 웹 애플리케이션에서 인증(Authentication) 및 인가(Authorization)를 처리하기 위한 엑세스 토큰(Access Token)으로 널리 사용되는 방법입니다. 사용자가 ID/PW 등으로 인증에 성공하면 서버는 사용자의 정보를 JWT에 담에 클라이언트에 전달하고, 클라이언트는 이후의 요청에 JWT를 함께 전달하여 별도의 인증 요청 없이도 사용자의 특정 권한이 필요한 요청을 처리할 수 있습니다. 하지만 JWT는 사용자 인증정보를 클라이언트에서 관리하는 방식이기 때문에 안전하게 사용하기 위해서는 신경써야 할 부분이 많습니다. 본 포스팅에서는 JWT를 안전하게 사용하는 방법에 대해 소개하겠습니다.

JWT 보안 고려사항

엑세스 토큰 도난 대응 : 토큰 갱신

JWT를 엑세스토큰으로 사용할 때 기본적으로 신경써야 하는 부분은 토큰의 갱신입니다. 혹시라도 엑세스 토큰이 탈취당할 경우 해당 토큰이 영구적으로 사용되는 것을 방지해야 하기 때문입니다. 토큰 갱신 방법으로 아래의 유형들을 고려해볼 수 있습니다.

  1. 수명이 짧은 엑세스 토큰을 사용
  2. 토큰의 수명이 짧을 수록 공격자는 탈취한 토큰을 사용할 수 있는 기간이 짧기 때문에 안전합니다. 하지만 이 경우 사용자는 ID/PW 입력과 같은 사용자 인증을 자주 해야 하기 때문에 사용자 경험 측면에서 좋은 방법은 아닙니다.
  3. 기존 액세스 토큰을 사용하여 새로운 액세스 토큰을 발급
  4. 만약 공격자가 액세스 토큰을 탈취하여 한 번 갱신에 성공하면 연속적으로 몇 번이고 토큰을 갱신할 수 있기 때문에 좋은 방법이 아닙니다.
  5. 수명이 짧은 엑세스 토큰과 수명이 긴 갱신 토큰(Refresh Token) 사용
  6. 사용자 인증을 통해 액세스 토큰과 갱신 토큰을 발급받고, 액세스 토큰이 만료될 경우 갱신 토큰을 사용하여 갱신하는 방법입니다. 액세스 토큰을 자주 갱신하면서도 사용자 인증은 자주 하지 않아도 되기 때문에 일반적으로 많이 사용됩니다. 위의 두 유형보다는 좋은 방법이라고 할 수 있으나 갱신 토큰을 탈취당할 경우 갱신 토큰의 수명만큼 위험에 노출된다는 점에서 여전히 보완할 점이 많습니다.
갱신 토큰 도난 대응 : 세션 사용

갱신 토큰 도난에 대한 대비책 중 세션을 함께 사용하고 갱신토큰을 세션 아이디처럼 사용하는 것입니다. 이 경우 만약 갱신 토큰이 탈취당한다면 세션에 저장된 사용자의 이전 접속 디바이스 정보, IP, Origin, 단위 시간당 접속 횟수 등을 검사할 수 있습니다. 비정상적인 접근이 감지되는 경우 세션 정보를 삭제하여 갱신토큰을 무효화할 수 있습니다. 갱신 토큰을 세션 아이디처럼 사용할 경우 JWT 방식보다는 불투명 토큰(임의의 문자열)을 사용하여 불필요한 정보 노출을 피하고 요청 크기도 줄일 수 있습니다.

토큰 도난의 사전 방지 : 토큰을 쿠키로 저장 & 쿠키 속성 활용

토큰은 다양한 방식으로 도난당할 수 있습니다. 도난에 대한 사후 처리만큼이나 사전에 방지하는 것 역시 중요한데, 토큰을 쿠키로 저장하고 쿠키의 특정 속성값들을 활용함으로써 이를 해결할 수 있습니다. 대표적인 토큰 공격 유형들과 각 유형에 대응되는 쿠키 속성 사용법에 대해 소개하겠습니다.

1. 중간자 공격(MITM Attack)

중간자 공격은 네트워크 통식을 조작하여 통신 내용을 훔쳐 보거나 조작하는 공격 유형으로, 서버의 IP, Domain 이름, 서버의 증명서 등을 확인하여 방지할 수 있으며, 일반적으로는 TLS/SSL 인증서 (HTTPS 사용)를 통해 방지한다.

해결 방법 : Secure 속성 사용

  • Secure 속성은 웹브라우저가 HTTPS(TLS/SSL) 연결을 통해서만 쿠키를 보내도록 합니다.HTTPS를 사용하면 모든 통신 내용은 암호화되기 때문에 공격자의 중간자 공격을 통한 토큰을 탈취를 방지할 수 있습니다.
2. XSS(Cross-Site Scripting)

XSS는 대상 웹사이트에 악성 스크립트를 주입하여 비정상적인 동작을 실행시키는 공격 유형이다. 공격자는 다른 사용자의 브라우저에서 스크립트가 실행되게 하여 사용자의 쿠키, 세션 등 중요한 정보에 접근할 수 있다.

해결 방법 : HttpOnly 속성 사용

  • HttpOnly 속성은 웹브라우저가 스크립트를 통한 Dom document.cookie 객체 접근을 허용하지 않도록 합니다. 즉 공격자의 XSS를 통한 토큰 탈취를 방지할 수 있습니다.
3. CSRF ( Cross Site Request Forgery)

사용자가 자신의 의지와는 무관하게 공격자가 의도한 행위를 특정 웹사이트에 요청하도록 만드는 공격 유형이다. 공격자는 사용자의 엑세스 토큰을 탈취하지 않고도 사용자로 하여금 엑세스 토큰을 사용하여

해결 방법 : SameSite 속성 사용

  • SameSite 속성은 웹브라우저가 쿠키를 받은 서버가 아닌 다른 서버로 요청을 하는 경우 그 쿠키는 전송하지 못하도록 합니다.

결론

JWT를 안전하게 사용하기 위한 고려사항에 대해서 살펴봤습니다. 이를 토대로 Furo에서 권장하는 JWT 사용법은 다음과 같습니다.

  1. JWT 방식의 액세스 토큰과 불투명 토큰 방식의 갱신 토큰을 사용합니다.
  2. 액세스 토큰과 갱신 토큰을 Secure, HttpOnly, SameSite 쿠키에 저장하여 중간자 공격, XSS, CSRF 등을 방지합니다.
  3. 인증서버에서는 사용자 세션을 관리하고 토큰 갱신시에만 세션에 접근하도록 합니다. 이 때 세션에는 사용자의 디바이스 정보, 소스 IP, Origin 등을 저장하여 비정상적인 접근을 감지할 수 있도록 하고, 세션 만료시 다시 인증하도록 합니다.
  4. 액세스 토큰이 만료되면 갱신 토큰과 함께 서버에 요청을 보내 새 액세스 토큰을 얻습니다. 이 요청은 갱신 토큰이 탈취되는 것을 방지하기 위해 HTTPS를 통해 이루어져야 합니다.
  5. 새 액세스 토큰을 받으면 클라이언트 측의 Secure, HttpOnly, SameSite 쿠키에 저장된 액세스 토큰을 업데이트합니다.
  6. 액세스 토큰이 갱신되면, 같은 갱신 토큰으로는 더 이상 새 액세스 토큰을 얻는 데 사용할 수 없도록 이전 갱신 토큰을 서버 측에서 무효화합니다.
  7. 매번 사용하기 전에 서버 측에서 JWT 토큰을 확인하여 변조되지 않았는지 확인합니다.

마치며

서버와 클라이언트 간 통신에 JWT를 적용하는 것은 어렵지 않지만 JWT를 안전하게 사용하는 것은 생각보다 어려운 일입니다. 본 포스팅에서 소개한 내용을 포함하여 다양한 보안 위협에 대해 고려하고 대비해야 하기 때문입니다. 10분 만에 안전한 인증 기능을 구현할 수 있는 SaaS Furo는 복잡한 보안 문제를 대신 해결해드립니다. 간단한 핸즈온으로 빠르고 안전하게 사용자 인증을 구현해보실 수 있습니다. 자세한 문의는 support@furo.one으로 언제든지 편하게 해주시면 됩니다.

Related posts

Continue reading

Newsletter

최신 소식이 궁금하신가요?
뉴스레터를 구독해보세요.

Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.