Skip to content

JWT란?!

김민준 edited this page Dec 26, 2019 · 1 revision

JWT 란?

JSON Web Token은 웹표준으로 두 개체에서 JSON 객체를 사용하여 가볍고 자가 수용적인(self-contained) 방식으로 정보를 안정성 있게 전달해준다.

자가 수용적 (self-contained) 이다.

JWT 는 필요한 모든 정보를 자체적으로 지니고 있습니다.

JWT 시스템에서 발급된 토근은, 토큰에 대한 기본 정보, 전달 할 정보 ( 로그인 시스템에서는 유저 정보) 그리고 토큰이 검증되었다는 것을 증명해주는 signature를 포함하고 있다.

  • 토큰의 기본 정보
  • 전달 할 정보
  • 토큰의 서명

쉽게 전달 될 수 있다.

JWT 는 자가 수용적이므로, 두 개체 사이에서 손쉽게 전달 될 수 있다. 웹 서버의 경우 HTTP의 헤더에 넣어서 전달 할 수도 있고, URL의 파라미터로 전달 할 수도 있다.

JWT 는 언제 사용될까?

다음과 같은 상황에서 JWT가 유용하게 사용 될 수 있다.

  • 회원 인증
  • 정보 교류

회원 인증

JWT를 사용하여 가장 흔한 시나리오이다.

유저가 로그인을 하면, 서버는 유저의 정보에 기반한 토큰을 발급하여 유저에게 전달해준다. 그 후, 유저가 서버에 요청을 할 때 마다 JWT 토큰을 포함하여 전달한다.

서버가 클라이언트에게서 요청을 받을때 마다, 해당 토큰이 유효하고 인증됐는지 검증을 하고, 유저가 요청한 작업에 권한이 있는지 확인하여 작업을 처리한다.

서버측에서는 유저의 세션을 유지 할 필요가 없다. 즉 유저가 로그인 되어 있는지 안 되어 있는지 신경 쓸 필요가 없고, 유저가 요청을 했을때 토큰만 확인하면 되니, 세션 관리가 필요 없어서 서버 자원을 많이 아낄 수 있다.

정보 교류

JWT는 두 개체 사이에서 안정성있게 정보를 교환하기에 좋은 방법이다. 그 이유는, 정보가 sign이 되어있기 때문에 정보를 보낸이가 바뀌진 않았는지, 또 정보가 도중에 조작되지 않았는지 검증할 수 있다.

JWT의 생김새

JWT는 . 을 기준으로 3가지의 문자열로 되어있다. 구조는 다음과 같이 이루어져있다. image

JWT 토큰을 만들때는 JWT를 담당하는 라이브러리가 자동으로 인코딩 및 해싱 작업을 해준다.

헤더 (Header)

Header 는 두 가지의 정보를 지니고 있다.

  • typ : 토큰의 타입을 지정한다. JWT 이다.

  • alg : 해싱 알고리즘을 지정한다. 해싱 알고리즘은 보통 HMAC SHA256 혹은 RSA가 사용되며, 이 알고리즘은 토큰을 검증 할 때 사용되는 signature 부분에서 사용된다.

    { "typ" : "JWT" "alg" : "HS256" //해싱 알고리즘으로 HMAC SHA256을 사용한다. }

참고로 JSON 형태의 객체가 base64로 인코딩 되는 과정에서 공백 / 엔터들이 사라진다. 따라서 다음과 같은 문자열을 인코딩 하게 된다.

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

정보 (Payload)

Payload 부분에는 토큰에 담을 정보가 들어있다. 여기에 담는 정보의 한 조각 을 클레임(Claim) 이라고 부르고, 이는 name / value 의 한 쌍으로 이루어져있다. 토큰에는 여러개의 클레임 들을 넣을 수 있다. 클레임의 종류는 다음과 같이 크게 세 분류로 나위어져 있다.

  • 등록된(Registered) 클레임,
  • 공개(Public) 클레임,
  • 비공개(Private) 클레임

등록된(Registered) 클레임

등록된 클레임들은 서비스에서 필요한 정보들이 아닌, 토큰에 대한 정보를 담기 위하여 이름이 이미 정해진 클레임 들이다. 등록된 클레임의 사용은 모두 선택적 (Optional) 이며, 이에 포함된 클레임 이름들은 다음과 같다.

  • iss : 토큰 발급자
  • sub : 토큰 제목
  • aud : 토큰 대상자
  • exp : 토큰의 만료시각, 시간은 항상 NumericDate 형식으로 되어 있어야 하며 언제나 현재 시간보다 이후로 설정되어 있어야 한다.
  • nbf : Not Before를 의미하며, 토큰의 활성 날짜와 비슷한 개념이다. 여기에도 NumericDate형식으로 되어야 하며 이 날짜가 지나기 전까지는 토큰이 처리되지 않는다.
  • iat : 토큰이 발급된 시간, 이값을 사용하여 토큰의 age 를 판단 할 수 있다.
  • jti : JWT의 고유 식별자로, 주로 중복적인 처리를 방지하기 위하여 사용된다. 일회용 토큰에 사용하면 유용하다.

공개(public) 클레임

공개 클레임들은 충돌이 방지된 (Collision-resistant) 이름을 가지고 있어야 된다. 충돌을 방지하기 위해서는 클레임 이름을 URI 형식으로 짓는다.

{
	"https:www.naver.com/alswns" : true
}

비공개(private) 클레임

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

{
	"username" : "alswns"
}

예제 Payload

{
	"iss" : "alswns.com",
	"exp" : "1485270000000",
	"https://naver.com/alswns" : true,
	"userId" : "1128373727102",
	"username" : "alswns"
};

서명 (signature)

JSON Web Token 의 마지막 부분은 바로 서명(signature) 이다.

이 서명은 헤더의 인코딩값과 정보의 인코딩값을 합친 후 주어진 비밀키로 해쉬를 하여 생성한다.

헤더 + 정보 + 비밀키 → 해쉬 → 서명

해싱은 같은 인풋에 대해서 항상 같은 아웃풋이 나와야 된다.

따라서 헤더, 정보에서 임의의 변조가 일어났으면 변조된 값을 해싱하면 서명이 나오지 않아서 변조됨을 알 수 있다.

서명 검증

HS256 알고리즘이라고 하였는데 여기서 HS256은 HMAC SHA256의 합친말이다.

HMAC?

HMAC는 해싱기법을 이용해서 메시지의 위변조가 있었는지 체크하는 기법이다.

앞의 헤더, 페이로드 부분을 다시 해싱하였을 때 뒤에 서명이 나오는지 확인하는 방법이다.

해싱을 할 때 헤더 + 페이로드 + secret key 이렇게 세 개의 부분을 합쳐서 해싱을 하게 된다.

참고

Clone this wiki locally