부스트캠프 활동 중 한번 정리한 적이 있었는데, 요즘 공부를 안했더니 개념을 까먹어서 다시 정리해본다!
공식문서를 직접 해석하고 여러 블로그들을 참고해서 정리했습니다 😉
보통 서버가 클라이언트의 인증을 확인하는 방법으로 쿠키, 세션, 토큰 3가지가 있다. JWT는 토큰 인증 방식 중 하나다. JWT와 무엇인지, 어떻게 동작하는지, 왜 사용하는지 제대로 알아보자.
JWT는 JSON Web Token의 줄임말로 인증에 필요한 정보들을 암호화시킨 JSON 토큰이다. JWT 기반 인증은 JWT 토큰(Access Token)을 HTTP 헤더에 실어 서버가 클라이언트를 식별하는 방식이다.
JWT는 .을 구분자로 나누어지는 세가지 문자열의 조합으로 구성되어 있다.
Header.Payload.Signature
JWT에서 사용할 타입과 해시 알고리즘 종류가 담겨있다. 일반적으로 토큰 유형(typ)과 서명 알고리즘(alg) 두 부분으로 구성된다.
{
"typ":"JWT",
"alg":"HSA256",
}
위 코드를 Base64Url로 인코딩하여 JWT의 첫번째 부분인 Header를 형성하게 된다.
서버에서 첨부한 사용자 권한 정보와 데이터가 담겨있다. 즉, 서버와 클라이언트가 주고받는 시스템에서 실제로 사용될 정보에 대한 내용을 담고 있는 섹션이다.
{
"id": 123456789,
"name": "JuYeong-s",
"age": 24
}
페이로드는 대표적으로 Registered claims, Public claims, Private claims 이렇게 세 가지 데이터 타입으로 나뉜다.
Registered claims: 미리 정의된 클레임
iss(issuer)
: 발행자sub(subject)
: 토큰 제목aud(audience)
: 토큰 대상 - 수신인을 식별함exp(expireation time)
: 토큰 만료 시간nbf(not before)
: JWT가 토큰이 처리되지 않아야 할 시점 - 이 시점이 지나기 전까지는 토큰이 처리되지 않는다.iat(issued At)
: 발행한 시간jti(JWI ID)
: 토큰 고유 식별자Public claims: 공개 클레임
Private claims: 비공개 클레임
Header, Payload를 Base64 URL-safe Encode를 한 이후 Header에 명시된 해시함수를 적용하고, 개인 키(Private Key)로 서명한 전자서명이 담겨있다.
Signature를 생성하기 위해서는 인코딩된 Header, 인코딩된 Payload, 비밀 키, Header에 명시된 알고리즘이 필요하다.
HMACSHA356(
base64UrlEncode(header) + "." + base64UrlEncode(payload),
secret key
)
시그니처는 (헤더 + 페이로드)
와 서버가 갖고 있는 secret key
값을 합친 것을 헤더에서 정의한 알고리즘으로 암호화를 한다.
Header와 Payload는 단순히 인코딩된 값이기 때문에 제 3자가 복호화나 조작을 할 수 있지만, Signature는 서버의 secret key가 유출되지 않는 이상 복호화할 수 없다.
따라서, Signature는 토큰의 위조 여부를 판단하는데 사용된다.
사용자가 성공적으로 로그인하면 JWT가 반환된다. 사용자가 로그인이 필요한 경로나 리소스에 엑세스하려고 할 때마다 Baerer 스키마를 사용하여 Authorization 헤더에 JWT를 실어 보내야 한다.
Authorization: Bearer <token>
이때 HTTP 헤더를 통해 JWT 토큰을 보낼 경우 토큰이 너무 커지지 않도록 해야 한다. 또한, 보안 문제때문에 민감한 세션 데이터를 브라우저 저장소에 저장하지 않도록 해야 한다.
브라우저 저장소에 저장하지 않을 경우, 헤더의 Authorization에 토큰을 실어보내면 쿠키를 사용하지 않기 때문에 CORS는 문제가 되지 않는다.
(저장하지 않고 JWT을 실어보내는 방법으로는 클라이언트 상태를 사용하는 방법이 있음.)
API 또는 리소스에 엑세스하기 위해 JWT를 얻고 사용하는 흐름
SWT(Simple Web Tokens)
및 SAML(Security Assertion Markup Language Tokens)
과 비교할 때 JWT의 이점에 대해 알아보자.
JSON은 XML보다 단순하기 때문에 인코딩될 때 크기도 더 작기 때문에 XML 기반의 SAML 방식보다 크기가 작다. 따라서, HTML 및 HTTP 환경에서 전달하기에 좋은 선택이다.
보안 측면에서, SWT 방식은 대칭 키 방식인 HMAC 알고리즘을 사용하는 비밀 키에 의해서만 서명되지만, JWT와 SAML 토큰은 공개키/개인키 쌍 방식을 쓸 수 있다.
인증 과정에서 대칭 키 방식은 속도는 빠르지만 키를 교환해야 한다는 문제와 키 배송 문제가 있다.
JSON 파서는 객체 형식이기 때문에 대부분 프로그래밍 언어에 일반적이다. 반면, XML은 객체에 바로 매핑되기 어렵기 때문에 SAML보다 JWT가 더 사용하기 쉽다.
- JSON과 XML