JWT

yuKeon·2023년 11월 26일
0

개요

"JWT를 설명해 주세요"

면접에서 자주 나오는 질문이지만 정확히 답변하기는 어렵다. 
개발에 자주 사용했지만 정확히 알고 사용했는가는 회의적이다. 
이번 포스팅은 JWT가 무엇이고 왜 사용하는지 이유를 알아본다.

1. JWT

1.1. JWT란?

JWT(JSON Web Token)은 JSON 객체로 정보를 안전하게 전송하기 위한 개방형 표준 인증 방식이다. 일반적으로 클라이언트와 서버, 서비스와 서비스의 통신 시 권한 인가(Authorization)를 위해 사용한다.
JWT는 디지털 서명으로 검증되고 신뢰할 수 있다. JWT는 비밀키(HMAC 알고리즘) 또는 공개/개인 키 쌍(RSA 또는 ECDSA)으로 서명할 수 있다. 서명된 토큰은 내부 클레임의 무결성을 검증할 수 있으며, 암호화된 토큰은 이러한 클레임을 외부로부터 숨긴다.

1.2. JWT 구조

JWT는 세 부분으로 구분된다.

헤더
JWT를 어떻게 검증하는가를 담는다. 토큰의 유형과 서명에 사용되는 알고리즘 두 가지로 구성된다. 예를 들어, 헤더는 {"alg": "HS256", "typ": "JWT"}와 같은 JSON 형태로, 이후 Base64Url 인코딩되어 JWT의 첫 번째 부분을 구성한다.

페이로드
JWT의 본문이다. 페이로드에 있는 데이터를 클레임 셋이라고 부른다. 클레임 셋은 JWT의 내용(토큰 생성자 정보, 생성 일시)를 저장한다.중요한 점은 페이로드는 디코딩 되어 있을 뿐이므로 중요한 정보를 저장하면 안 된다는 점이다.

시그니처
헤더와 페이로드를 합친 문자열을 서명한 값이다. 서명은 헤더의 정의된 알고리즘과 비밀 키를 이용해 성성하고 Base64 URL-Safe로 인코딩한다.
시그니처는 서버에서 관리하는 비밀 키로만 복호화할 수 있으므로 다른 클라이언트가 임의로 복호화할 수 없다.

1.3. JWT 특징

self-contained
JWT 자체에 필요한 모든 정보를 담을 수 있다. 헤더는 토큰을 복호화하는 방법을, 페이로드는 토큰 정보와 인가에 필요한 내용을 자유롭게 담을 수 있으며, 시그니처로 헤더와 페이로드가 위 변조 여부를 검증할 수 있다.

stateless
서버는 JWT 생성 시 JWT 검증이나 권한 인가 시 필요한 값을 넣으면 되기 때문에 JWT에 대한 상태를 따로 관리하지 않는다. 단지 클라이언트가 전달한 토큰을 검사할 뿐이다.

2. 사용 이유 (VS 세션)

토큰 방식은 세션과 비교했을 때 두 가지 관점에서 사용 이유를 찾을 수 있다.

확장성
세션 방식보다 확장이 자유롭다. 세션 기반 인증 방식은 사용자의 인증 정보를 서버에서 관리한다. 이는 확장성에 제한을 줄 수 있다. 서버의 Scale-out을 진행할 때 세션의 정합성 문제가 발생할 수 있기 때문이다.

JWT는 클라이언트 측에서 인증 정보를 보관한다. 이는 서버 측에서 상태를 유지할 필요가 없으며, 서버 확장성에 영향을 주지 않는다.

세션 방식도 다양한 방법(ex. Sticky Session, Session Clustering)으로 서버를 확장할 수 있다. 하지만 JWT는 이러한 구현 없이 토큰 자체로 인증이 가능하기 때문에 확장 측면에서 장점을 가진다.

간편함
세션 방식의 인증 절차를 살펴보자. 클라이언트가 쿠키에 담아 세션 ID를 전달한다. 서버는 세션 ID로 세션 저장소에 있는 사용자 정보를 조회한다. 즉, 모든 인증 과정에서 I/O 작업이 발생한다.

JWT는 self-contained 특징이 있다. 이는 토큰 자체로 모든 인증 정보를 갖고 있다는 의미다. 따라서 해당 토큰의 유효성만 검사하면 되므로 인증이 간편하다.

3. 한계

완벽한 기술은 없다. 토큰도 다음과 같은 단점이 있다.

네트워크 부하
세션의 경우 쿠키에 세션 ID만 담아 요청을 전송하여 트래픽을 적게 사용한다.
반면 JWT는 인증에 필요한 모든 정보를 담아 전송하므로 세션 방식보다 많은 네트워크 트래픽을 사용한다.

보안
세션 방식은 상태 정보를 서버에서 관리한다. 때문에 세션의 탈취가 의심되거나 정황이 발견되면 서버에서 세션을 무효화(삭제)할 수 있다.

하지만 JWT는 인증 정보를 클라이언트에서 관리한다. 이는 누군가 토큰을 탈취해서 서버에 요청을 보내도 서버는 이를 탐지할 수 없다는 의미다.

이를 보안하는 방법이 무엇일까? 토큰의 유효 시간을 짧게 가져갈 수 있다. 하지만 사용자는 더 많은 로그인 요청을 받게 된다. 이는 Refresh Token을 사용해서 해결할 수 있다. 하지만 Refresh Token을 사용한다는 것은 상태를 저장한다는 뜻이 아닐까?

4. 마치며

지금까지 JWT가 무엇이며 세션과 비교했을 때 장점을 알아봤다.
JWT는 claim 기반의 토큰으로 헤더, 페이로드, 시그니처로 구성된다.
헤더에는 토큰을 암호화하는 데 사용한 알고리즘 정보를 저장하고 페이로드에는 인가에 필요한 정보, 시그니처는 헤더와 페이로드를 합친 문자열을 비밀 키로 암호화한 값이 들어간다. 세션과 비교해서 확장성과 간편함이 장점이지만 보안과 네트워크 부하 단점이 존재한다.

Ref.

https://jwt.io/introduction
https://brunch.co.kr/@jinyoungchoi95/1
https://hudi.blog/session-based-auth-vs-token-based-auth/
https://meetup.nhncloud.com/posts/239

0개의 댓글