JWT 토큰의 구조
JWT(Jason Web Token)은 인증(Authentication)과 권한 부여(Authorization)를 안전하고 효율적으로 처리하기 위해 사용된다.
백엔드 개발자가 사용자 인증을 구현해야 할 때 요청을 보내는 유저가 "누구인지" 확인하고, "할 수 있는 일"을 판단 해야한다.
이 때 JWT 토큰을 이용하여 유저의 필요한 정보를 저장하여 인증/권한을 확인할 수 있다.
먼저 JWT 토큰의 구조는 다음과 같다. 마침표, 즉 '.' 문자를 기준으로 Header, Payload, Signature를 구분하여 가진다.
<Header>.<Payload>.<Signature>
Header는 JWT의 메타데이터를 포함한다.
일반적으로 토큰의 타입, 서명 알고리즘의 종류를 포함한다.
{
"alg": "HS256",
"typ": "JWT"
}
Payload는 토큰에 담을 실제 데이터(Claims)를 포함한다.
Claims에는 사용자 식별 정보, 권한 정보, 만료 시간 등 원하는 데이터를 넣을 수 있다.
Claims의 종류는 다음과 같다.
- Registered Claims(표준 클레임): 권장되는 표준 키들.
- iss (Issuer): 토큰 발급자.
- sub (Subject): 토큰의 주제(주로 사용자 ID).
- aud (Audience): 토큰 대상.
- exp (Expiration): 토큰 만료 시간(Unix 타임스탬프).
- iat (Issued At): 토큰 발급 시간.
- nbf (Not Before): 토큰 유효 시작 시간.
- Public Claims(커스텀 클레임): 공개적으로 사용되는 클레임.
- 예: 사용자 역할, 클랜 정보 등.
- Private Claims: 양측(클라이언트-서버) 간에만 사용되는 클레임
{
"sub": "kangth97",
"name": "Taeho Kang",
"roles": "USER",
"exp": 1673875200
}
Signature는 토큰의 무결성을 보장하는 부분이다.
Header와 Payload의 내용을 연결해 HS256 같은 알고리즘으로 서명한다.
이 서명을 통해 토큰이 위조되었는지 검증할 수 있다.
Session 기반 인증과 비교
JWT 토큰을 이용하는 stateless 인증은 기존 세션 기반 인증과 비교하여 몇 가지 장점이 있다.
먼저 세션 기반 인증의 기본적인 인증 과정을 살펴보자.
1. 사용자가 로그인을 하면 서버는 사용자를 확인한 뒤 세션을 생성. 세션 ID를 클라이언트에 쿠키로 전달한다.
2. 사용자가 요청을 보낼 때마다 해당 쿠키를 함께 전송한다.
3. 서버는 세션 저장소(메모리, Redis 등)에서 세션 ID를 조회하여 사용자를 인증한다.
위 세션 기반 인증은 다음과 같은 문제점이 존재한다.
1. 서버 상태 저장: 세션 데이터를 서버에서 관리해야 하므로 사용자가 많아질수록 저장소와 서버 자원이 많이 필요하다.
2. 확장성 문제: 여러 대의 분산 서버를 사용하는 경우, 세션 데이터를 모든 서버에서 공유해야 해서 관리가 복잡하다. 또한 같은 유저라도 모바일 환경, 웹 환경에 따라 세션이 달라지게 된다.
이러한 문제를 해소할 수 있는 JWT 기반 인증 과정을 살펴보자
1. 사용자가 로그인을 하면 서버는 사용자를 확인 후 JWT 토큰을 생성하여 클라이언트에 전달한다.
2. 사용자가 요청을 보낼 때마다 헤더에 JWT를 포함해 서버로 전송한다.
3. 서버는 토큰을 Decoding하여 사용자 정보를 확인 후 인증(authenticate) 및 권한을 확인(authorization) 한다.
JWT는 클라이언트가 모든 인증 정보를 포함하므로 서버는 상태를 저장할 필요가 없다.
또한 서버는 토큰의 무결성을 확인하기만 하면 되므로 분산 시스템에서도 쉽게 동작한다.
JWT 사용 시 주의사항
1. Payload는 암호화 되지 않는다: JWT의 payload는 Base64Url로 인코딩 되므로 누구나 내용을 디코딩할 수 있다. 따라서 민감한 정보(비밀번호, 주민등록번호)는 토큰에 포함되지 않아야 한다.
2. 토큰 크기 증가: 토큰이 클수록 네트워크 성능에 영향을 줄 수 있으므로 필요한 최소 데이터만 포함해야 한다.
3. 권한 변경 시 반영이 어려움: JWT는 발급 시점의 정보를 포함하므로, 권한이 변경되면 토큰을 재발급해야한다.
4. 토큰 탈취 시 위험: JWT는 클라이언트가 저장하므로 탈취당하면 만료되기 전까지 악용될 수 있다. 따라서 HTTPS를 사용하고, 짧은 만료시간을 두고 Refresh Token을 활용하여 보안을 강화해야 한다.