#20 JWT
JWT (JSON Web Token)는 웹 애플리케이션에서 사용자 인증 및 정보 교환을 위해 널리 사용되는 표준이다. JWT는 특히 RESTful API와 같은 무상태(stateless) 환경에서 유용하다.
JWT의 구조
JWT는 세 부분으로 구성된 문자열로, 마침표(.)로 구분된다:
- 헤더 (Header)
- 페이로드 (Payload)
- 서명 (Signature)
1. 헤더 (Header)
헤더는 JWT의 타입과 해싱 알고리즘을 지정한다. 일반적으로 두 가지 정보를 포함한다: 타입 (typ)과 해싱 알고리즘 (alg)
{
"typ": "JWT",
"alg": "HS256"
}
위 JSON 객체는 Base64Url로 인코딩되어 JWT의 첫 번째 부분을 구성한다.
2. 페이로드 (Payload)
페이로드는 JWT의 본문으로, 다양한 클레임(claim)을 포함할 수 있다. 클레임은 엔터티(보통 사용자)에 대한 정보와 추가 메타데이터를 포함할 수 있다. 클레임은 세 가지로 분류된다:
- 등록된 클레임 (Registered Claims): 예약된 클레임으로, JWT 표준에 정의된 클레임이다. 예를 들어, iss (issuer), exp (expiration time), sub (subject), aud (audience) 등이 있다.
- 공개 클레임 (Public Claims): 충돌 방지를 위해 IANA JSON Web Token Registry에 등록된 클레임이다.
- 비공개 클레임 (Private Claims): 양 당사자 간에 동의된 클레임이다.
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
이 JSON 객체도 Base64Url로 인코딩되어 JWT의 두 번째 부분을 구성한다.
3. 서명 (Signature)
서명은 헤더와 페이로드를 합친 후, 비밀 키를 사용해 서명한 것이다. 서명은 JWT의 무결성과 진위성을 검증하는 데 사용된다. 서명 생성 과정은 다음과 같다
HMACSHA256(
base64UrlEncode(header) + "." + base64UrlEncode(payload),
secret
)
예를 들어, HS256 알고리즘을 사용하는 경우 비밀 키와 함께 HMAC SHA-256 해시를 생성한다.
최종 JWT는 다음과 같은 형태이다
xxxxx.yyyyy.zzzzz
여기서 xxxxx는 헤더, yyyyy는 페이로드, zzzzz는 서명을 의미한다.
JWT의 사용 사례
JWT는 다양한 시나리오에서 사용될 수 있다. 주로 다음과 같은 경우에 사용된다:
- 인증 (Authentication): 사용자 인증 후 서버는 JWT를 생성하여 클라이언트에게 전달한다. 클라이언트는 이후 요청 시 JWT를 포함하여 서버에 전송하며, 서버는 이 JWT를 검증하여 사용자를 인증한다.
- 정보 교환 (Information Exchange): JWT는 두 파티 간에 안전하게 정보를 교환하는 데 사용된다. 서명된 JWT는 발신자의 신원을 보장하며, 정보가 변경되지 않았음을 확인할 수 있다.
JWT의 보안
JWT의 보안은 서명과 사용된 알고리즘에 크게 의존한다. 다음은 JWT 사용 시 고려해야 할 보안 요소들이다:
- 비밀 키 보호: 비밀 키가 노출되면 누구나 JWT를 생성할 수 있으므로, 비밀 키를 안전하게 보호해야 한다.
- 알고리즘 선택: 안전한 알고리즘 (예: HS256, RS256)을 사용해야 한다. none 알고리즘을 허용해서는 안 된다.
- 만료 시간 설정: exp 클레임을 사용하여 JWT의 만료 시간을 설정함으로써, 만료된 JWT를 사용할 수 없게 해야 한다.
- HTTPS 사용: JWT는 민감한 정보를 포함할 수 있으므로, HTTPS를 통해 전송하여 도청을 방지해야 한다.
- 토큰 무효화: 사용자 로그아웃 또는 비밀번호 변경 시 토큰을 무효화할 방법을 마련해야 한다.