BackEnd/WEB

[WEB] JWT (Json Web Token)이란?

샤아이인 2022. 5. 11.

JWT에 대한 공부를 하며 요약도 할겸 스스로 정리하는 글 입니다. 틀린 내용은 댓글 남겨주시면 감사하겠습니다!

 

1. 탄생 배경

 

기존의 Session 방식은 stateful 한 단점이 있었습니다. 이는 stateless한 HTTP의 특성에도 위배되는 특성이죠!

 

그럼 왜 stateful이 단점일까?

 

서버에 session 정보를 저장해두어야 하기 때문에, 사용자의 요청이 많아져 서버를 수평 확장(scale out) 하는 경우 세션 정보를 저장하고 있는 서버로부터 복사를 해와 따로 저장해야 하기 때문에 번거로움이 있습니다.

 

이러한 문제를 해결하는 방법중 하나로, 각 서버들의 공통된 session 저장소를 만들어서 이 한곳으로부터 session 정보를 확인하도록 하는 것 입니다. 보통 inMemory DB인 Redis 를 많이 사용하게 됩니다.

 

또한 Session은 Client의 매 요청마다 Header에 담겨 오는데, 이를 받는 Server는 매번 session 저장소로부터 저장되어있는 session인지 확인작업을 해야만 합니다.

즉, DB에 필수적으로 접근을 해야만 합니다.

 

이러한 문제 상황을 해결 하기 위해 나온 방법중 하나로 Token 인증 방식의 JWT가 탄생하게 되었습니다.

 

2. JWT의 등장

JWT(Json Web Token)은 Json 포맷을 이용하여 사용자에 대한 속성을 저장하는 Claim 기반의 Web Token이다.

 

JWT는 토큰 자체를 정보로 사용하는 Self-Contained 방식으로 정보를 안전하게 전달한다.

주로 회원 인증이나 정보 전달에 사용되게 됩니다.

 

데이터가 많아지면 토큰의 크기가 커진다는 단점이 있으며, 한번 발급되면 서버측에서 사용자의 데이터를 수정해도 토큰을 재발급하지 않으면 이전 토큰에는 반영되지 않게 됩니다.

 

인증 절차 과정은 기존의 Cookie/Session 방식의 과정과 크게 달라지지 않습니다.

1. Client가 자신의 id, pwd를 기반으로 인증 시도

2. Server에서 사용자 인증에 성공했다면, 서명된 Token을 생성하여 Client에게 반환해 줍니다.

3. 이 다음부터 client가 server에 request를 보내올때는 header에 JWT 토큰을 함께 전달하게 됩니다.

4. Server에서 전달받은 JWT 토큰이 정상적인 토큰인지 확인하게 됩니다.

 

기존의 session 방식에서는 sessionId를 주고 받았지만, 이번에는 JWT token을 주고 받게 됩니다.

 

핵심은 JWT는 서명된 Token 이라는 점 입니다!

 

JWT는 크게 2가지 알고리즘을 사용하게 됩니다.

 

1. HS256 방식

대표적인 JWT 암호화 알고리즘인 HS256 방식은, HMAC algorithm + SHA256 해싱 알고리즘으로 대칭키 전략을 사용합니다.

즉, 데이터를 암호화 할때 사용한 key 와 복호화 할때 사용하는 key 가 동일하다는 의미 입니다.

 

2. RS256 방식

이와 대조적으로 RS256 방식은, RSA + SHA256 해싱 알고리즘으로 비대칭키 전략으로 private key를 sign 용도(encryption)로, public key를 verify 용도로 사용하게 됩니다.

 

(알고리즘에 따른 인증 방식은 저 뒤에서 알아봅시다~~)

 

Token에 secret key를 기반으로 서명하게 될 경우, 다시 서버로 Token이 전달될때 secret key를 가지고있는 서버는 해당 토큰이 정상적인 토큰인지 검사를 할 수 있게 됩니다.

 

여기서 중요한 점은JWT 토큰에 포함되어 있는 내용물들은 누구나 확인할 수 있다는 점 입니다.

토큰의 내용물인 header, payload 는 암호화가 된것이 아니라 단순하게 Base64Url를 통해  인코딩한 문자열이기 때문에, 같은 문자열에 대해 항상 같은 인코딩 문자열을 반환한다.

역으로 누구든 JWT 토큰을 Base64Url로 디코딩 하게되면 내용물을 확인할 수 있게 됩니다.

 

그럼 JWT를 왜 사용하고 있는것 일까요?

 

JWT의 핵심은 내용물을 암호화 하여 다른사람이 못보게 하는 전략이 아니라, 위변조 된 내용인지 아닌지 무결성(Integrity)을 검증하는것이 핵심이다.

 

3. JWT 구조

JWT는 Header, Payload, Signature의 3 부분으로 이루어지며, Json 형태인 각 부분은 Base64Url로 인코딩 되어 표현됩니다.

또한 각각의 부분을 이어 주기 위해 .(dot) 구분자를 사용하게 됩니다.

 

추가로 Base64Url는 암호화된 문자열이 아니고, 그냥 인코딩한 문자열이다. Base64Url로 다시 디코딩 하면 내용을 누구나 확인할수 있다.

 

3-1. Header

토큰의 헤더 부분은 typ과 alg 두 가지 정보로 구성되게 됩니다.

alg는 Signature를 만들때 상용되는 알고리즘을 명시한 것 입니다. 

  • typ: 토큰의 타입을 지정 ex) JWT
  • alg: 알고리즘 방식을 지정하며, 서명(Signature) 및 토큰 검증에 사용 ex) HS256(SHA256) 또는 RSA
{ 
   "alg": "HS256",
   "typ": JWT
 }

 

3-2. PayLoad

토큰의 payload, 즉 내용물에는 토큰에서 사용할 정보의 조각들인 클레임(Claim)이 담겨 있게 됩니다. 

총 3가지 종류가 있으며, Key : Value 형태로 데이터를 추가하게 됩니다.

 

어떤 claim을 추가할지는 개발자 마음지만, 우선 표준에 대해서 알아봅시다!

참고로 clain의 표준 key 이름 길이는 3글자 입니다.

 

3.2.1 등록된 클레임(Registered Claim)

등록된 클레임은 토큰 정보를 표현하기 위해 이미 정해진 표준 종류의 데이터들로, 필수로 사용해야 된다는 것이 아닙니다!

  • iss: 토큰 발급자(issuer)
  • sub: 토큰 제목(subject) - 토큰에 대한 식별값이 됨
  • aud: 토큰 대상자(audience)
  • exp: 토큰 만료 시간(expiration), NumericDate 형식으로 되어 있어야 함 ex) 1480849147370
  • nbf: 토큰 활성 날짜(not before), 이 날이 지나기 전의 토큰은 활성화되지 않음
  • iat: 토큰 발급 시간(issued at), 토큰 발급 이후의 경과 시간을 알 수 있음
  • jti: JWT 토큰 식별자(JWT ID), 중복 방지를 위해 사용하며, 일회용 토큰(Access Token) 등에 사용

 

3.2.2 공개 클레임(Public Claim)

공개 클레임은 사용자 정의 클레임으로, 공개용 정보를 위해 사용된다. 충돌 방지를 위해 URI 포맷을 이용하며, 예시는 아래와 같다.

{ 
    "https://blogshine.tistory.com": true
}

 

3.2.3 비공개 클레임(Private Claim)

비공개 클레임은 사용자 정의 클레임으로, 서버와 클라이언트 사이에 임의로 지정한 정보를 저장한다. 아래의 예시와 같다.

{ 
    "token_type": access 
}

 

3-3. Signature(서명)

서명(Signature)은 토큰 유효성 검증을 할 때 사용하는 고유한 암호화 코드 부분 입니다.

 

예를 들어 HS256 방식으로 서명을 한다고 해봅시다.

서명(Signature)은 위에서 만든 헤더(Header)와 페이로드(Payload)의 값을 각각 BASE64Url로 인코딩하고, 인코딩한 값에 비밀 키를 추가하여 헤더(Header)에서 정의한 HS256 알고리즘으로 해싱을 하고, 이 값을 다시 BASE64Url로 인코딩하여 생성한다.

HMACSHA256(B64Url(header) + "." + B64Url(payload), secret) => Signature

 

3-4. JWT Token 예시

이를 JWT 토큰으로 만들려면, 

header, payload, signature 각각을 모두 Base64Url 로 encode한 후, 각각을 . dot로 연결하면 JWT가 된다.

JWT = B64Url(header).B64Url(payload).B64Url(signature)

 

서명에는 대칭키를 사용하는 HS256 알고리즘을 적용했으니 향후, 검증을 할때도 같은 key가 사용되게 될 것 이다.

 

생성된 토큰은 HTTP 통신을 할 때 Authorization이라는 key의 value로 사용된다. 일반적으로 value에는 Bearer이 앞에 붙여진다.

{ 
    "Authorization": "Bearer {생성된 토큰 값}",
}

 

4. 장단점

JWT의 장점

  • JWT는 사용자 인증에 필요한 모든 정보는 token 자체에 포함하기 때문에 별도의 인증 저장소가 필요없다. (ex Session 저장소)
  • 쿠키를 전달하지 않아도 되므로 쿠키를 사용함으로써 발생하는 취약점이 사라집니다.
  • 트래픽 대한 부담이 낮음 (session 저장소에서 검증하지 않아도 되니까)
  • REST 서비스로 제공 가능
  • 독립적인 JWT

JWT의 단점

  • Self-contained: 토큰 자체에 정보를 인증에 필요한 정보를 담고 있으므로 단점이 될수도 있습니다.
  • 토큰 길이: 정보가 많아질수록 토큰의 길이가 늘어나 네트워크에 부하를 줄 수 있습니다.
  • Payload 인코딩: 페이로드(Payload) 자체는 암호화 된 것이 아니라, BASE64로 인코딩 된 것입니다. 중간에 Payload를 탈취하여 디코딩하면 데이터를 볼 수 있으므로, JWE로 암호화하거나 Payload에 중요 데이터를 넣지 않아야 합니다.
  • Stateless: JWT는 상태를 저장하지 않기 때문에 한번 만들어지면 제어가 불가능합니다. 즉, 토큰을 임의로 삭제하는 것이 불가능하므로 토큰 만료 시간을 꼭 넣어주어야 합니다.
  • Tore Token: 토큰은 클라이언트 측에서 관리해야 하기 때문에, 보통 브라우저에서 토큰을 저장해야 합니다.

 

5. 출처

https://m.blog.naver.com/sehyunfa/221723355441

 

해싱(Hashing)을 활용한 HMAC(Hash based Message Authentication Code)

이 글을 읽기 전에 해싱에 대한 기본 지식은 아래 포스트를 통해 습득하시기 바랍니다. 송수신자 간의 메시...

blog.naver.com

https://brunch.co.kr/@jinyoungchoi95/1

 

JWT(Json Web Token) 알아가기

jwt가 생겨난 이유부터 jwt의 실제 구조까지 | 사실 꾸준히 작성하고 싶었던 글이지만 JWT를 제대로 개념을 정리하고 구현을 진행해본 적이 없었는데 리얼월드 프로젝트를 진행하면서 JWT에 대한

brunch.co.kr

https://mangkyu.tistory.com/56

 

[Server] JWT(Json Web Token)란?

현대 웹서비스에서는 토큰을 사용하여 사용자들의 인증 작업을 처리하는 것이 가장 좋은 방법이다. 이번에는 토큰 기반의 인증 시스템에서 주로 사용하는 JWT(Json Web Token)에 대해 알아보도록 하

mangkyu.tistory.com

 

'BackEnd > WEB' 카테고리의 다른 글

[HTTP] HTTP 헤더 - 캐시와 조건부 요청  (0) 2022.02.03
[HTTP] HTTP 헤더 - 일반헤더  (0) 2022.02.02
[HTTP] HTTP 상태 코드  (0) 2022.02.01
[HTTP] HTTP 메서드 활용  (0) 2022.01.31
[HTTP] HTTP 메서드  (0) 2022.01.28

댓글