Skip to content

Latest commit

 

History

History
90 lines (74 loc) · 5.79 KB

2. JWT.md

File metadata and controls

90 lines (74 loc) · 5.79 KB

JWT (JSON Web Token)

  • 웹표준(RFC 7519)으로서 두 개체에서 JSON 객체를 사용하여 가볍고 자가수용적인(self-contained)방식으로
    정보를 안전성 있게 전달합니다.
  • 대부분의 주류 프로그래밍 언어에서 지원됩니다.
  • 자가 수용적입니다.
    • JWT는 필요한 모든 정보를 자체적으로 지니고 있습니다.
    • 토큰이 검증되었다는 것을 증명해주는 signature를 포함하고 있습니다.
  • 쉽게 전달될 수 있습니다.
    • 웹 서버의 경우 HTTP의 Header에 넣어서 전달할 수 있고, URL의 파라미터로 전달할 수도 있습니다.

JWT는 어떤 상황에서 사용되는가

  • 회원인증
    • 유저가 로그인하면, 서버는 유저의 정보에 기반한 토큰을 발급합니다.
    • 그 후, 유저가 서버에 요청할 때마다 JWT를 포함하여 전달합니다.
    • 서버가 클라이언트에게서 요청을 받을 때마다 해당 토큰이 유효하고 인증됐는지 검증하고,
      유저가 요청한 작업에 권한이 있는지 확인하여 작업을 처리합니다.
  • 정보교류
    • 정보가 sign이 되어있기 때문에 정보를 보낸이가 바뀌진 않았는지,
      또 정보가 도중에 조작되지는 않았는지 검증할 수 있습니다.

JWT의 생김새

JWT

헤더(Header)는 2가지의 정보를 가지고 있습니다.

  • typ : 토큰의 타입을 지정합니다.
  • alg : 해싱 알고리즘을 지정합니다. 해싱 알고리즘은 보통 HMAC SHA256 또는 RSA가 사용되며,
    이 알고리즘은 토큰을 검증할 때 사용되는 signature부분에서 사용됩니다.
{
   "typ" : "JWT",
   "alg" : "HS256"
}

정보(Payload)부분에는 토큰에 담을 정보가 들어있습니다.

  • 여기에 담는 정보의 한 '조각'을 클레임(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) 클레임

      등록된 클레임도 아니고 공개된 클레임들도 아닙니다.
      양측 간에 (보통 클라이언트 <-> 서버) 협의 하에 사용되는 클레임 이름들입니다.
      공개 클레임과는 달리 이름이 중복되어 충돌이 일어날 수 있으니 사용할 때 유의해야 합니다.

서명 (signature)

  • 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에 포함해야 합니다.