JWT(Json Web Token)이란 공부/BE, DB

Date 2021. 7. 30. 14:52

JWT란 서비스와 서비스 간 통신 시 인증(Authentication)과 인가(Authorization)에 주로 사용하는 토큰이다.

 

요청을 하는 서비스는 JWT를 포함하여 요청을 전송하고, 요청을 받아들이는 서버는 이 JWT를 보고 해당 요청을 허가하거나 거부한다.(Authorization)

 

JWT RFC문서를 살펴보면(rfc7519) 'The JWT conform to either the JWS or JWE specification' 이라고 적혀있다.

즉 JWS 또는 JWE Spec을 구현한 것이 JWT라고 할 수 있다.

 

여기서 우리가 살펴볼 것은 대부분 JWT 구현에 사용하는 Header, Payload, Signature로 구성되는 JWS Specification이다.

 

JWS로 구현한 JWT의 정의를 살펴보자면,

1. URL-safe 하다. 즉 HTTP Request에 JWT를 포함할 시 요청의 URL(path) 부분에도 넣어도 상관이 없다는 뜻이다.

2. 총 3개의 부분 : Header, Payload, Signature로 구성되고, 각 세 부분을 '.'로 구분한다.

3. Header와 Payload는 JSON 객체를 BASE64url 인코딩한 문자열이다.

4. key:value 쌍을 claim이라 하고 a set of claims를 JSON 객체로 표현한다.

 

 

JWT 생성하기, JWT 검증하기, JWT 사용 사례 크게 세 부분으로 나누어 설명하겠다.

JWT 생성하기

Payload

일단 정보를 담을 Payload를 만들어야 한다. 이 Payload는 a set of claims을 JSON 형태로 나타낸 뒤 URL-safe 하게 BASE64url 인코딩 한 것이다.

claim의 key는 string이어야 하고 value는 JSON value여야 한다. 이 조건을 만족시키면 claim이 될 수 있다.

 

IANA(Internet Assigned Numbers Authority)에 가면 자주 사용하는 payload claim들이 나열되어 있다.

 

대표적으로 iss(issuer), sub(subject), exp(expiration) 등이 존재한다. 이외에도 필요한 정보를 Payload에 claim 형태로 담을 수 있다.

{
  "iss": "donghyeong",
  "sub": "intro"
}

 

위와 같은 JSON을 BASE64url 인코딩하면 Payload가 완성된다.

 

ewogICJpc3MiOiAiZG9uZ2h5ZW9uZyIsCgkic3ViIjogImludHJvIgp9

Header

 

헤더는 JOSE(JSON Object Signing and Encryption) 헤더라고 한다. 즉 이 JWT 토큰이 무결(integrity)한지 확인하기 위한 메타데이터들을 담고 있다. 자세한 정보는 마찬가지로 IANA 에서 확인할 수 있다.

 

가장 중요한 claim은 alg로, 나중에 Signature를 생성하고 검증할 때 사용한다. 자세한 내용은 뒷부분에서 설명하겠다.

 

{
  "alg": "HS256"
}

 

마찬가지로 위와 같은 JSON을 BASE64url 인코딩하면 Header가 완성된다.

 

eyJhbGciOiJIUzI1NiJ9

Signature

 

JWT의 Header와 Payload는 단순히 BASE64url 인코딩한 것이기 때문에 누구나 읽거나 수정할 수 있다. 이러한 정보들이 변조되지 않았음을 증명하기 위해 서명(Signature)를 이용한다.

 

Header와 Payload를 이어붙인 값에 헤더의 알고리즘을 이용해 서명(Signature) 한다.

 

SIGNATURE = BASE64url(ALGORITHM(Header + '.' + Payload, Private Key))

 

이러한 서명 알고리즘에는 대표적으로 SHA등 HMAC으로 대표되는 대칭키 알고리즘,

비대칭키를 사용하는 알고리즘 등이 존재한다.

 

"구글 계정으로 로그인" 등 OpenID Connect에서는 비대칭키를 사용하는 JWT를 사용한다고 한다.

구글같은 ID-Provider는 구글의 Private key로 토큰을 서명하고, "구글 계정으로 로그인" 등 기능을 사용하는 App은 구글의 Public key로 해당 토큰을 검증하여 Integrity를 확인한다.

 

본론으로 돌아와 이렇게 생성된 Signature를 Header와 Payload에 이어붙이면 JWT가 완성된다.

 

JWT = HEADER.PAYLOAD.SIGNATURE

JWT 검증하기

 

이렇게 생성된 JWT가 변조되지 않았음을 확인하기 위해서는 Signature를 이용해 검증하게 된다.

Key(비대칭 알고리즘의 경우 Public Key)를 알고 있다고 가정하고 Header와 Payload의 값을 헤더의 알고리즘으로 계산한 결과가 Signature와 같으면 Validate하다고 판단한다.

 

ALGORITHM(HEADER + '.' + PAYLOAD, Key) === BASE64urlDecode(SIGNATURE)

JWT 사용 사례

API Key

JWT를 API Key로 사용해 클라이언트는 JWT를 포함하여 요청하고, 서버는 해당 JWT를 보고 해당 요청을 받아들일지 거부할지 선택한다.

  1. 클라이언트는 서버에게 JWT를 제공받는다. ( 로그인 등 )
  2. API Call시 HTTP 요청에 JWT를 담아 ( 보통 Authorization Header ) 전송한다.
  3. 서버는 해당 JWT를 검증하고 Payload에 담은 값을 바탕으로 API요청을 처리하거나 거부한다.

OAuth

인증/인가 관련 표준인 OAuth2.0에서도 토큰으로 JWT를 사용할 수 있다.

 

 

 

Recent Posts

Popular posts

Recent Comments

Tag List

인가 인증 네트워크 GCP ORM 테라폼 AWS API 네임스페이스 클라우드 TypeScript JWT IAC 백준 DNS DB 컨테이너 운영체제 k8s JavaScript 도커 알고리즘 파이썬 리눅스
Total : Today : Yesterday :
Blog powered by Tistory, Designed by hanarotg