JWT
-
컴팩트하고 독립적임: 토큰은 자체적으로 포함된 정보 덩어리로, URL에 포함시키기 쉽고 빠르게 전송 및 처리할 수 있습니다.
-
디지털 서명: JWT는 디지털로 서명되어 정보의 무결성과 진위를 보장합니다. 서명 방식은 비밀 키(HMAC 알고리즘) 또는 공개/개인 키 쌍(RSA 또는 ECDSA)을 사용합니다.
-
검증 가능: 수신자는 JWT의 서명을 확인하여 토큰의 무결성과 발신자의 신원을 검증할 수 있습니다.
-
암호화 가능: 정보의 기밀성을 위해 JWT를 암호화할 수도 있지만, 일반적으로 서명된 토큰으로서 무결성 검증에 중점을 둡니다.
-
정보의 무결성과 진위 증명: 공개/개인 키 쌍을 사용할 경우, 개인 키를 가진 발신자가 서명했음을 증명할 수 있습니다.
JSON 웹 토큰을 언제 사용해야 하나요?
권한 부여(Authorization)
- 사용자가 로그인하면 JWT가 발급됩니다.
- 이후 요청마다 JWT를 포함하여 사용자는 자신이 접근할 수 있는 경로, 서비스, 리소스에 액세스할 수 있습니다.
- JWT는 오버헤드가 적고 여러 도메인에서 쉽게 사용 가능하여 Single Sign-On(SSO) 기능에 널리 활용됩니다.
정보 교환(Information Exchange)
- JWT는 서명이 가능하므로 발신자가 자신의 신원을 증명할 수 있습니다.
- 서명은 JWT의 헤더와 페이로드를 기반으로 하며, 이를 통해 내용의 변조 여부를 확인할 수 있습니다.
JWT 구조
Header
Base64Url로 인코딩되어 JWT의 첫 번째 부분을 형성하며 다음과 같은 내용을 포함합니다.
{
"alg": "RSA",
"typ": "JWT"
}
- 토큰 유형(typ): 보통 “JWT”로 지정됩니다.
- 서명 알고리즘(alg): 예를 들어 HMAC SHA256(HS256) 또는 RSA를 사용합니다.
Payload
Base64Url로 인코딩되어 JWT의 두 번째 부분을 형성하며 다음과 같은 내용을 포함합니다.
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
클레임 유형:
-
등록된 클레임(Registered Claims)
- 권장되는 사전 정의된 클레임 세트입니다.
- 상호 운용성을 높이기 위해 사용되며 필수는 아니지만 유용합니다.
- 예시: iss(발급자), exp(만료 시간), sub(주제), aud(청중).
-
공개 클레임(Public Claims)
- JWT 사용자들이 자유롭게 정의할 수 있는 클레임입니다.
- 충돌을 방지하기 위해 IANA JSON 웹 토큰 레지스트리에서 정의하거나 충돌 방지 네임스페이스를 포함하는 URI 형식으로 정의해야 합니다.
-
개인 클레임(Private Claims)
- 당사자 간의 정보를 공유하기 위해 작성된 맞춤형 클레임입니다.
- 이를 사용하는 당사자들 간에만 의미가 있으며, 등록되거나 공개된 클레임이 아닙니다.
Signature
인코딩된 헤더와 인코딩된 페이로드, 비밀 키, 그리고 헤더에 지정된 알고리즘을 사용하여 서명을 생성합니다.
HMACSHA256(base64UrlEncode(header) + '.' + base64UrlEncode(payload), secret)
- 메시지가 전송 도중 변경되지 않았는지 확인하는 데 사용
- 개인 키로 서명된 토큰의 경우, JWT를 발송한 사람이 주장하는 실제 발송자인지 확인
Putting all together
JWT의 최종 출력은 HTML 및 HTTP 환경에서 쉽게 전달할 수 있는 점(.)으로 구분된 세 개의 Base64-URL 문자열입니다.
xxxxx.yyyyy.zzzzz
JWT는 어떻게 작동하나요?
-
토큰 발급:
- 사용자가 자격 증명을 사용하여 성공적으로 로그인하면 JWT가 발급됩니다.
- 이 토큰은 인증 정보를 포함하고 있어 보안에 주의가 필요합니다.
- JWT는 자격 증명 정보를 포함하지만, 보안상의 이유로 너무 오랫동안 저장해서는 안 됩니다.
-
토큰 전송:
Authorization: Bearer <token>
- 사용자가 보호된 리소스나 경로에 접근할 때마다, 사용자는 Authorization 헤더에 JWT를 포함하여 서버에 요청을 보냅니다.
- 일반적으로 Bearer 스키마를 사용하여 전송합니다.
-
서버 검증:
- 서버는 Authorization 헤더에서 JWT를 검증하여 사용자의 권한을 확인합니다.
- JWT가 유효하다면, 서버는 보호된 리소스에 대한 접근을 허용합니다.
- JWT에 필요한 정보가 포함되어 있을 경우, 데이터베이스 쿼리의 필요성이 줄어들 수 있습니다.
-
주의사항:
- 토큰 크기 제한: HTTP 헤더를 통해 JWT를 전송할 때는 토큰이 너무 커지지 않도록 해야 합니다. 일부 서버는 8KB 이상의 헤더를 허용하지 않을 수 있습니다.
- CORS 문제 없음: JWT는 쿠키를 사용하지 않고 Authorization 헤더를 통해 전송되므로, CORS(Cross-Origin Resource Sharing) 문제가 발생하지 않습니다.
JWT 사용 흐름
- 권한 요청: 클라이언트가 서버에 권한을 요청합니다.
- 토큰 반환: 권한 부여가 완료되면, 서버는 클라이언트에 액세스 토큰을 반환합니다.
- 리소스 접근: 클라이언트는 액세스 토큰을 사용하여 보호된 리소스(예: API)에 접근합니다.
- 비밀 정보 주의: 서명된 토큰은 포함된 정보가 노출될 수 있지만, 변경되지는 않습니다. 따라서 JWT에 비밀 정보를 포함해서는 안 됩니다.
JWT 장점
-
간결성
- JSON은 XML보다 덜 장황하고, 인코딩 시 크기가 작아 JWT는 SAML보다 더 컴팩트합니다.
- 이로 인해 HTML 및 HTTP 환경에서 전달하기 용이합니다.
-
서명 방식
- JWT와 SAML은 공개/비공개 키 쌍을 사용하여 서명할 수 있으며, XML 서명보다 JSON 서명이 더 단순합니다.
- SWT는 HMAC 알고리즘을 사용하여 대칭적으로 서명할 수 있지만, JWT는 더 강력한 보안을 제공합니다.
-
다루기 쉬움
- JSON은 대부분의 프로그래밍 언어에서 객체로 쉽게 매핑할 수 있습니다.
- XML은 자연스러운 문서-객체 매핑이 없어 JWT가 SAML보다 사용하기 더 쉽습니다.