JWT

  • JWT(Json Web Token) 이란 JSON 객체로서, 당사자간에 정보를 안전하게 전송하기위한 개방형 표준(RFC 7519)이다.

    개방형 표준은 기술 표준의 문서가 공개되어 있고, 누구나 자유롭게 사용할 수 있는 표준을 의미한다. 대표적인 예로 HTML, IP(인터넷 프로토콜), JSON 등이 있다.

  • 정보는 서명되어 있기에 신뢰할 수 있다. JWT는 비밀 키(HMAC 알고리즘 사용) 또는 공개/개인 키 쌍(RSA 또는 ECDSA 사용)을 사용하여 서명할 수 있다.

사용되는 곳

  • 인증 : 사용자에게 JWT 가 생성되어 인증되면, 인증된 사용자의 요청마다 JWT가 포함되어 해당 토큰으로 허용된 경로, 서비스 및 리소스에 액세스할 수 있다. 이러한 Single Sign-On은 오버헤드가 적고 다양한 도메인에서 쉽게 사용할 수 있기 때문에 오늘날 JWT를 널리 사용하는 기능이다.

    Single Sign-On(SSO) 은 사용자가 한 번만 로그인하면, 동일한 세션 내에서 여러 애플리케이션이나 웹사이트에 추가 로그인 없이 접근할 수 있게 해주는 인증 체계이다.

  • 정보 교환 : JWT는 공개/개인 키 쌍을 사용하여 서명할 수 있으므로 보낸 사람이 누구인지 확인할 수 있다. 또한 서명은 헤더와 페이로드를 사용하여 계산되므로 콘텐츠가 손상되지 않았는지 확인할 수도 있다.

구조

JWT 는 base64url 로 인코딩된 JSON 데이터 로 구성되어있으며, 총 세가지 요소가 점(.) 으로 구분되어 있다. JWT 는 간결해야하기 때문에, 각 JSON 데이터의 키는 세자리로 축약한다.

헤더

헤더는 일반적으로 토큰 유형과 HMAC SHA256 또는 RSA와 같이 해당 JWT 에 사용되는 서명 알고리즘의 두 부분으로 구성된다.

{
  "alg": "HS256",
  "typ": "JWT"
}

페이로드

페이로드는 클레임을 포함한다. 클레임은 엔터티(일반적으로 사용자) 및 추가 데이터에 대한 설명이다.

클레임

클레임에는 등록된 클레임, 공개 클레임 및 개인 클레임의 세 가지 유형이 있다.

  • 등록된 클레임 : JWT 에서 미리 정의해둔 클레임이다. 필수는 아니지만, 유용한 상호 운용 가능한 클레임 세트를 제공하기 위해 권장된다.
    • iss : 토큰 발급자를 나타낸다.
    • sub : 토큰 제목을 나타낸다.
    • aud : 토큰 대상자를 나타낸다.
    • exp : 토큰 만료 시각을 나타낸다. Numeric Date 형식으로 나타낸다.
    • nbf : Not Before. 토큰의 활성 시각을 나타낸다. 쉽게 말해, 이 시각 전에는 토큰이 유효하지 않다는 의미이다.
    • iat : Issued At. 토큰이 발급된 시각을 나타낸다. Numeric Date 형식으로 나타낸다. 이 값으로 토큰이 발급된지 얼마나 오래됐는지 확인할 수 있다.
    • jti : JWT ID. JWT 의 식별자를 나타낸다.
  • 공개 클레임 : 공개용 정보(e.g. 이메일 주소, 프로필 이미지 등) 를 위해 사용된다. 충돌 방지를 위해 IANA JSON Web Token Claims Registry 에 등록하여 사용하거나, 정보가 URI 포맷으로 정의될 때 사용한다.
         "email": "user@example.com",
         "profile": "http://domain.com/img.png",
         "http://domain.com/xxx/yyy/is_admin" : true
    
  • 개인 클레임 : 당사자 간에만 협의된 클레임이다. 공개 클레임과 충돌이 일어나지 않도록 해야한다.
          "user_id": "123456790",
    

    서명

서명 부분을 만들려면 인코딩된 헤더, 인코딩된 페이로드, 비밀 키 및 헤더에서 지정한 알고리즘을 가져와서 해당 비밀 키로 서명해야 한다. 서명은 JWT의 발행자가 자신이 누구인지 확인하고 메시지가 도중에 변경되지 않았는지 확인하는 데 사용한다.

직접 확인해보기

jwt.io

작동 방식

  1. 사용자가 로그인 하여, 인증에 성공했다면 서버는 JWT 를 생성하여 반환.
  2. 클라이언트는 서버의 반환 방식에 따라 로컬 스토리지 또는 쿠키에 JWT 를 보관.
  3. 서비스를 이용하는 동안 인가가 필요한 모든 요청마다 HTTP 헤더에 JWT 를 담음.
    • 일반적으로 유저 에이전트를 인증하기 위한 자격 증명을 포함하는 Authorization 요청 헤더에 Bearer 스키마를 사용하여 담는다.
            Authorization: Bearer <token>
      
  4. 서버는 서명을 확인하고 페이로드를 디코딩하여 토큰의 유효성을 검사.

유효성 검사 와 확인

JWT 의 보안 검사를 위해 유효성 검사 와 확인이라는 절차가 진행된다.

유효성 검사

JWT의 구조, 형식 및 내용을 확인하여, 토큰이 말이 되는지, 예상되는 표준을 준수하는지, 올바른 데이터를 포함하는지 확인한다.

  • 구조: 토큰에 점으로 구분된 표준 세 부분(헤더, 페이로드, 서명)이 있는지 확인한다.
  • 형식: 각 부분이 올바르게 인코딩(base64url) 되었는지, 페이로드에 예상되는 클레임이 포함되어 있는지 확인한다.
  • 내용: 페이로드 내의 클레임이 올바른지 확인하여 토큰이 만료되지 않았는지, 시간이 되기 전에 사용되지 않았는지 등을 확인한다.

확인

토큰의 진위성과 무결성을 확인하는 것을 포함하며, 토큰이 악의적으로 변경되지 않았고 신뢰할 수 있는 소스에서 온 것인지 확인한다.

  • 서명 확인: 비밀 키 또는 공개 키를 사용하여 헤더에 지정된 알고리즘으로 수행되며, 서명이 예상과 일치하는지 확인하여, 토큰이 무결한지 혹은 신뢰할 수 있는 소스에서 온것인지 확인한다.
  • 발행자 확인: iss 클레임이 예상되는 토큰 발행자와 일치하는지 확인한다.
  • 대상 확인: aud 클레임이 예상되는 토큰 대상자와 일치하는지 확인한다.

출처