- 웹표준(RFC 7519)으로서 두 개체에서 JSON 객체를 사용하여 가볍고 자가수용적인(self-contained)방식으로
정보를 안전성 있게 전달합니다. - 대부분의 주류 프로그래밍 언어에서 지원됩니다.
- 자가 수용적입니다.
- JWT는 필요한 모든 정보를 자체적으로 지니고 있습니다.
- 토큰이 검증되었다는 것을 증명해주는 signature를 포함하고 있습니다.
- 쉽게 전달될 수 있습니다.
- 웹 서버의 경우 HTTP의 Header에 넣어서 전달할 수 있고, URL의 파라미터로 전달할 수도 있습니다.
- 회원인증
- 유저가 로그인하면, 서버는 유저의 정보에 기반한 토큰을 발급합니다.
- 그 후, 유저가 서버에 요청할 때마다 JWT를 포함하여 전달합니다.
- 서버가 클라이언트에게서 요청을 받을 때마다 해당 토큰이 유효하고 인증됐는지 검증하고,
유저가 요청한 작업에 권한이 있는지 확인하여 작업을 처리합니다.
- 정보교류
- 정보가 sign이 되어있기 때문에 정보를 보낸이가 바뀌진 않았는지,
또 정보가 도중에 조작되지는 않았는지 검증할 수 있습니다.
- 정보가 sign이 되어있기 때문에 정보를 보낸이가 바뀌진 않았는지,
- typ : 토큰의 타입을 지정합니다.
- alg : 해싱 알고리즘을 지정합니다. 해싱 알고리즘은 보통 HMAC SHA256 또는 RSA가 사용되며,
이 알고리즘은 토큰을 검증할 때 사용되는 signature부분에서 사용됩니다.
{
"typ" : "JWT",
"alg" : "HS256"
}
- 여기에 담는 정보의 한 '조각'을
클레임(claim)
이라고 부르고, 이는name/value
의 한 쌍으로 이루어져 있습니다. - 토큰에는 여러 개의 클레임(정보의 조각)들을 넣을 수 있습니다.
- 클레임의 종류는 다음과 같이 크게 세 분류로 나뉘어 있습니다.
-
등록된(registered) 클레임
등록된 클레임들은 서비스에서 필요한 정보들이 아닌 토큰에 대한 정보들을 담기 위하여
이름이 이미 정해진 클레임들입니다.
등록된 클레임의 사용은 모두 선택적이며, 이에 포함된 클레임 이름들은 다음과 같습니다.- iss : 토큰 발급자 (issuer)
- sub : 토큰 제목 (subject)
- aud : 토큰 대상자 (audience)
- exp : 토큰의 만료시간(expiration), 시간은 NumericDate형식으로 되어있어야 하며(예: 1480849147370)
언제나 현재 시간보다 이후로 설정되어 있어야 합니다. - nbf : Not Before를 의미하며, 토큰의 활성 날짜와 비슷한 개념입니다.
여기에도 NumericDate형식으로 날짜를 지정하며, 이 날짜가 지나기 전까지는 토큰이 처리되지 않습니다. - iat : 토큰이 발급된 시간(issued at), 이 값을 사용하여 토큰의 age가 얼마나 되었는지 판단할 수 있습니다.
- jti : JWT의 고유 식별자로서, 주로 중복적인 처리를 방지하기 위하여 사용됩니다.
일회용 토큰에 유용하게 사용할 수 있습니다.
-
공개(public) 클레임
공개 클레임들은 충돌이 방지된(collison-resistant) 이름을 갖고 있어야 합니다.
충돌을 방지하기 위해서는 클레임 이름을 URI 형식으로 짓습니다. -
비공개(private) 클레임
등록된 클레임도 아니고 공개된 클레임들도 아닙니다.
양측 간에 (보통 클라이언트 <-> 서버) 협의 하에 사용되는 클레임 이름들입니다.
공개 클레임과는 달리 이름이 중복되어 충돌이 일어날 수 있으니 사용할 때 유의해야 합니다.
-
- JWT의 마지막 부분은 바로 서명입니다.
이 서명은 헤더의 인코딩 값과 정보의 인코딩 값을 합친 후, 주어진 SecretKey로 해시를 하여 생성합니다.
토큰을 안전하게 사용하기 위해서는 다음과 같은 모범 사례를 따르도록 권장합니다.
-
JWT는 안전한 HttpOnly Cookie에 저장해야 합니다.
이렇게 해야 XSS 공격을 방지할 수 있습니다.
-
Cookie를 사용해 JWT를 전송한다면, CSRF 방어가 무엇보다도 중요합니다.
악의적인 다른 도메인에 의해
사용자가 인식하지 못하는 사이에 우리가 구축한 웹 서버로의 요청이 발생할 수 있기 때문입니다.
토큰의 전송 방식으로 Cookie를 사용한다면 CSRF에 대한 대비책을 반드시 준비해야 합니다. -
강력한 Key로 토큰을 서명해야 하며, Key는 인증 서비스에서만 접근해야 합니다.
토큰을 사용해서 사용자를 인증할 때마다 항상 보안 키로 서명되어 있는지 검사해야 합니다. -
서명을 위한 보안 키는 토큰의 발행자(issuer)와 소비자(consumer)만 접근할 수 있어야 하며,
외부 접근을 허용해서는 안 됩니다. -
민감한 데이터는 JWT로 저장하면 안 됩니다.
토큰은 일반적으로 조작을 방지하기 위한 목적으로 서명되므로 권한 claim 데이터는 쉽게 decode해서 볼 수 있습니다.
그렇기 때문에, 민감한 정보를 토큰으로 저장하면 유출될 가능성이 있습니다. -
Replay 공격에 대비하려면 jti claim과 유효기간(exp claim), 생성시간(creation time)을 권한 claims에 포함해야 합니다.