개발공부/WEB 기본

[웹기본] JWT(JSON Web Token)

햄❤️ 2021. 6. 1. 18:34
728x90

JWT

JSON Web Token의 약자로 전자 서명 된 URL-safe (URL로 이용할 수있는 문자 만 구성된)의 JSON.

클라이언트와 서버, 서비스와 서비스 사이 통신 시 권한 인가를 위해 사용하는 토큰이다. 

JWT는 서버와 클라이언트 간 정보를 주고 받을 때 Http 리퀘스트 헤더에 JSON 토큰을 넣은 후 서버는 별도의 인증 과정없이 헤더에 포함되어 있는 JWT 정보를 통해 인증합니다.
이때 사용되는 JSON 데이터는 URL-Safe 하도록 URL에 포함할 수 있는 문자만으로 만듭니다.
JWT는 HMAC 알고리즘을 사용하여 비밀키 또는 RSA를 이용한 Public Key/ Private Key 쌍으로 서명할 수 있습니다.

JWT는 웹표준(RFC 7519)으로서 두 개체에서 JSON 객체를 사용하여 가볍고 자가수용적인 방식으로 정보를 안전성 있게 전달해줍니다.

‘인증(Authentication)‘이란, 등록된 사용자인지 확인하는 과정이고, ‘인가(Authorization)‘는 권한이 있는 사용자인지 확인하는 과정이다. http 특성 때문에 인증, 인가 과정은 꼭 필요하다. http는 요청(request)이 들어오면 응답(response)하는 구조인데, 응답 이후 상태가 저장되지 않기 때문에(stateless) 요청을 보낸 사용자가 등록된 사용자인지, 요청한 작업 권한을 가지고 있는지 검증해야한다.

 

 JWT의 등장 배경 

서버 기반 권한 인증를 대체하기 위해 JWT가 등장했다. 

기존 서버 기반 권한 인증의 문제점

사용자 수가 늘어날수록 세션에 담아야 할 정보가 함께 증가하기 때문에 메모리 과부하 문제가 발생한다.

많은 트래픽을 감당하기 위해 프로세스를 늘리거나 서버 장비를 추가하는 경우 확장이 쉽지 않다.

(세션을 서버에 저장하고 있고, 서버를 여러 대 사용하여 요청을 분산한 상황이라고 가정해보자. 어떤 사용자가 로그인 했을 때 그 사용자는 처음 로그인 했던 그 서버, 즉 그 사용자 정보가 담긴 서버에만 요청을 보내도록 설정을 해야한다)

쿠키는 단일 도메인 및 서브 도메인에서만 작동하기 때문에 여러 도메인에서 관리하는 것은 번거롭다.

즉, 서버 기반 인증인 세션과 쿠키는 MSA환경에 적합하지 않다.

why JSON 형태?

프로그래밍 언어를 통해 유연하게 다루기 편하고, 데이터 스키마 수정이 편해서  

구성요소

JWT는 . 을 구분자로 3가지의 문자열로 구성되어 있습니다.

aaaa.bbbbb.ccccc 의 구조로 앞부터 헤더(header), 내용(payload), 서명(signature)로 구성됩니다.

헤더 (Header)

헤더는 typ와 alg 두가지의 정보를 지니고 있습니다. typ는 토큰의 타입을 지정합니다. JWT이기에 "JWT"라는 값이 들어갑니다. alg : 해싱 알고리즘을 지정합니다. 기본적으로 HMAC, SHA256, RSA가 사용되면 토근을 검증 할 때 사용되는 signature부분에서 사용됩니다.

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

정보(payload)

Payload 부분에는 토큰을 담을 정보가 들어있습니다. 정보의 한 조각을 클레임(claim)이라고 부르고, 이는 name / value의 한 쌍으로 이뤄져있습니다. 토큰에는 여러개의 클레임들을 넣을 수 있지만 너무 많아질경우 토큰의 길이가 길어질 수 있습니다.

클레임의 종류는 크게 세분류로 나누어집니다.

  1. 등록된(registered) 클레임 등록된 클레임들은 서비스에서 필요한 정보들이 아닌, 토큰에 대한 정보들을 담기위하여 이름이 이미 정해진 클레임들입니다. 등록된 클레임의 사용은 모두 선택적(optional)이며, 이에 포함된 크레임 이름들은 다음과 같습니다.
  • iss : 토큰 발급자 (issuer)
  • sub : 토큰 제목 (subject)
  • aud : 토큰 대상자 (audience)
  • exp : 토큰의 만료시간(expiration), 시간은 NumericDate 형식으로 되어있어야 하며 언제나 현재 시간보다 이후로 설정되어 있어야 합니다.
  • nbf : Not before을 의미하며, 토큰의 활성 날짜와 비슷한 개념입니다. 여기에도 NumericDate형식으로 날짜를 지정하며, 이 날짜가 지정하며, 이 날짜가 지나기 전까지는 토큰이 처리되지 않습니다.
  • iat : 토큰이 발급된 시간(issued at), 이 값을 사용하여 토큰의 age가 얼마나 되었는지 판단 할 수 있습니다.
  • jti : JWT의 고유 식별자로서, 주로 중복적인 처리를 방지하기 위하여 사용됩니다. 일회용 토큰에 사용하면 유용합니다.

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

{ "https://chup.tistory.com/jwt_claims/is_admin" : true }

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

서명(signature) 🎈🎈

payload의 데이터가 조작 되었는지 여부를 서명에서 서버가 체크* 

서명은 헤더의 인코딩값과 정보의 인코딩값을 합친후 주어진 비밀키로 해쉬를 하여 생성. 이렇게 만든 해쉬를 base64형태로 나타내게 된다.

 

 JWT 사용과정 

1.브라우저의 로그인과정에서 회원정보를 입력(ID,PASSWORD)
2.서버는 JWT를 생성
3.서버는 브라우저에게 JWT를 전송
4.브라우저는 JWT를 가지고 서버에게 데이터를 요청
5.서버는 서명을 확인하고 유저 정보를 클라이언트에게 제공

 JWT의 사용 목적 

  • 회원인증: JWT를 이용해서 회원정보를 주고 받게 되면 유저의 정보를 세션에 유지할 필요가 없게 된다.
    즉 stateless 한 서버를 만들 수 있게 함. 이전 방식은 브라우저와 서버의 세션영역에 로그인 정보가 저장되어있는 Statefull한 서버
  • 정보교류: 데이터를 주고받을때 안정성있게 정보 교환할 수 있게 도와준다

로그인 인증시 JWT 사용(Refresh Token)

만약 유효기간이 짧은 Token을 발급하게되면 사용자 입장에서 자주 로그인을 해야하기 때문에 번거롭고 반대로 유효기간이 긴 Token을 발급하게되면 제 3자에게 토큰을 탈취당할 경우 보안에 취약하다는 약점이 있습니다. 그 점들을 보완하기 위해 Refresh Token 을 사용하게 되었습니다. Refresh Token은 Access Token과 똑같은 JWT입니다. Access Token의 유효기간이 만료되었을 때, Refresh Token이 새로 발급해주는 열쇠가 됩니다. 예를 들어, Refresh Token의 유효기간은 1주, Access Token의 유효기간은 1시간이라고 한다면, 사용자는 Access Token으로 1시간동안 API요청을 하다가 시간이 만료되면 Refresh Token을 이용하여 새롭게 발급해줍니다. 이 방법또한 Access Token이 탈취당한다해도 정보가 유출이 되는걸 막을 수 없지만, 더 짧은 유효기간때문에 탈취되는 가능성이 적다는 점을 이용한 것입니다. Refresh Token또한 유효기간이 만료됐다면, 사용자는 새로 로그인해야 합니다. Refresh Token도 탈취 될 가능성이 있기 때문에 적절한 유효기간 설정이 필요합니다.

 

Access Token + Refresh Token 인증 과정

 

 

 장점 

- 서버가 JWT를 받으면 서명이 맞는지 확인하고, 디코드하고, 만료되지 않은 것을 확인하고, 요청받은 기능을 허가해줄 지 JWT에 담긴 데이터를 보고 판단(검증을 위해 데이터베이스나 세션에 접근하지 않아도 됨)

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

- 데이터에 누가 손댔는지 여부를 확인하기 위해 서명을 확인하는 것 외에는 서버에서 인증 작업을 하지 않아도 됨

 

 

 단점 

  • 사용자 계정을 차단하거나 비활성화해야하는 경우 응용 프로그램은 잠금이 완전히 적용되도록 토큰이 만료 될 때까지 기다려야 함(한번 발급된 토큰은 값을 수정하거나 폐기가 불가)
  • 사용자가 비밀번호를 변경해야하는 경우 (예 : 계정 도용의 경우) 사전에 인증을 수행 한 경우 이전 비밀번호로 생성 된 토큰은 만료 될 때까지 유효합니다. (서버에서는 한번 발급된 토큰의 정보를 바꾸는것 불가능)
  • 표준 구현에서는 "새로 고침"토큰을 지정하지 않습니다. 따라서 만료 시 사용자는 다시 인증해야합니다.
  • JWT 토큰의 "상태 비 저장"측면을 위반하지 않고는 토큰을 파기 할 수 없습니다. 토큰이 브라우저에서 삭제 되더라도 만료 될 때까지 유효하므로 실제 로그 아웃이 불가능합니다.
  • 만약 유출되었다면? 못 쓰게 만들어야 하는데 만료시킬 방법이 없다.
  • 저장할 필드 수에 따라서 토큰이 커질 수 있다.
  • 토큰이 모든 요청에 대해 선송되면 데이터 트래픽 크기에 영향을 미칠 수 있다.

 

 

 

출처: https://github.com/gyoogle/tech-interview-for-developer/blob/master/Web/JWT(JSON%20Web%20Token).md 

출처: https://velog.io/@geunwoobaek/JWT%EB%9E%80

출처: https://naon.me/posts/til63

728x90

'개발공부 > WEB 기본' 카테고리의 다른 글

[웹기본] 쿠키(Cookie) & 세션(Session)  (0) 2021.06.01