개발

JWT 개념 자세히 알아보자

brobro332 2024. 12. 15. 15:39
반응형

JWT란?

  • JWT(Json Web Token)은  간결하고도 독립된 방식으로 양단 사이의 정보를 전송할 수 있도록 정의된 RFC 7519 웹 표준이라고 한다.
  • 전송된 정보는 디지털 서명을 통해 검증되므로 신뢰할 수 있다.
  • 디지털 서명 방식은 두 가지 방식이 있다.

 

  1. RSA 또는 ECDSA 알고리즘을 통해 공개/비공개 키 쌍으로 서명할 수 있다.
    • 이렇게 서명된 토큰에 포함된 클레임의 무결성을 체크할 수도 있다.
    • 가령 비공개 키를 가진 사용자만 해당 토큰에 서명했음을 보장한다.
  2. HMAC 알고리즘을 통한 비밀 키 방식을 통해 서명하여 토큰을 암호화할 수도 있다.
    • 이렇게 암호화된 토큰은 다른 사람에게서 클레임을 보여주지 않고 숨긴다.

 

JWT 왜 사용할까?

  • HTTP의 중요한 특징 중 하나는 비상태성(stateless)을 지향한다는 점이다.
  • 비상태성이란 클라이언트가 보낸 정보를 서버에서 저장하지 않는다는 것이다.
     
  • 비상태성을 중요시하는 이유는 확장성으로 이어진다.
  • 세션의 경우 세션 ID를 메모리든 DB든 특정 방식으로 서버에 저장한다.
  • 가령 서비스가 흥해서 트래픽 부하를 관리하기 위해 서버의 수를 늘린다고 하자.
  • 이런 경우 서버 A와 서버 B에서 관리하는 세션 ID는 서로 공유되지 않기 때문에 사용자 요청에 대한 인가 기능이 적절하게 처리되지 못한다. 
    이 때 서버 클러스터링이나 세션 저장소를 외부에 둠으로써 서버 간 세션 ID를 공유할 수 있다고 한다.
  • 그런데 병목 현상 등으로 세션 스토리지 접근 속도 저하나 중앙 세션 스토리지에 부하가 집중된다는 문제가 발생한다.
  • 서버 클러스터링의 경우 노드 간 통신 문제로 세션 불일치 현상이 발생할 수 있다고 한다.
  • 그런데 본인도 챗 지피티와 검색을 통해 수집한 정보이니 참고만 하시는 걸 추천한다.
     
  • 반면 JWT는 사용자 정보를 서버에 저장하지 않는다. 서버가 늘어나도 문제가 없다는 뜻이다.

 

사실 나는 현재 확장성까지 신경 쓸 필요는 없다. 그런데 최근 개발은 항상 확장성을 생각하고 구현해야 한다는 점을 알게 되었다. 추후 내가 현업에서 JWT를 도입해야 될 수도 있으니 토이 프로젝트에 포함시켜보려고 한다. 

 

JWT의 구조를 알아보자

  • JWT는 점으로 분리된 헤더, 페이로드, 서명 세 부분으로 나뉜다.
  • 이때 헤더와 페이로드는 Base64Url로 인코딩 된 문자열이다.
     

헤더

  • 헤더는 보통 사용된 서명 알고리즘과 토큰의 타입을 포함한다.
  • 사용된 서명 알고리즘에는 HMAC SHA256 또는 RSA 등이 들어갈 수 있다.
  • 토큰의 타입에는 JWT가 값으로 들어간다.

 

페이로드

  • 페이로드는 주로 클레임을 포함하는 부분으로, 클레임은 사용자와 추가 데이터를 나타내는 정보다.
  • 클레임은 다음 세 가지 유형으로 나뉜다.
    1. 등록된 클레임
      • 권장되지만 필수는 아니다.
      • 상호운용성을 위해 사용되며 JWT의 간결성을 위해 클레임 이름은 세 글자로 제한된다고 한다.
      • 일반적으로 다음 사항이 포함된다. 
        • iss(발급자)
        • exp(만료 시간)
        • sub(주제)
        • aud(대상) 
        • nbf(토큰이 유효하기 시작하는 시간)
        • iat(토큰이 발급된 시간)
        • jti(토큰의 고유 식별자)
    2. 공개 클레임
      • 공개돼도 상관없는 정보로, 충돌 방지를 위해 URI로 정의해야 한다.
    3. 비공개 클레임
      • JWT를 사용하는 당사자 간의 합의에 따라 정의된 커스텀 클레임으로, 등록되거나 공개되지 않은 정보이다.

 
서명

  • 서명을 생성하려면 아래 항목들을 결합하여 서명해야 한다.
  1. 인코딩 된 헤더
  2. 인코딩 된 페이로드
  3. 비밀 키
  4. 헤더에 지정된 알고리즘

 

  • 예를 들어, HMAC SHA256 알고리즘을 사용하는 경우 서명은 다음과 같이 생성된다.
HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret
)
  • 서명을 통해 메시지가 전송 중 변경되지 않았다는 사실과 비공개 키로 서명된 경우 JWT의 발신자가 올바른지 확인할 수 있다.

 

JWT의 작동 원리

  • 인증에서 사용자가 로그인하면 JWT가 반환된다.
  • 토큰은 자격 증명이므로 보안 문제를 방지하기 위해 필요한 기간 이상 보관하지 않아야 한다.
  • 또한, 보안이 부족한 브라우저 저장소에 민감한 세션 데이터를 저장하지 않는 것이 좋다고 한다.
  • 이 부분은 더 알아봐야겠지만 로컬 스토리지보다는 HTTP Only 쿠키에 세션 데이터를 저장하는 것이 보안성을 높일 수 있다는 의미인 것 같다.
     
  • 사용자가 보호된 경로나 리소스에 접근하려 할 때, 클라이언트는 JWT를 전송해야 한다.
  • 일반적으로 Authorization 헤더에 Bearer 스키마를 사용하여 JWT를 보내는데, 헤더의 내용은 다음과 같다.
Authorization: Bearer <token>

 

  •  서버에서는 Authorization 헤더에서 유효한 JWT를 확인하고, 유효하면 사용자가 보호된 리소스에 접근할 수 있도록 허용한다.
  • JWT가 필요한 데이터를 포함하고 있으면, 특정 작업을 위해 데이터베이스를 쿼리 할 필요가 줄어들 수 있다.
  • 참고로 JWT 토큰을 Authorization 헤더로 전송하면, 쿠키를 사용하지 않기 때문에 CORS 문제는 발생하지 않는다고 한다.

 

나는 아마 HTTP Only 쿠키 방식으로 토큰을 전달하도록 구현하게 될 것 같다. 

 

JWT의 작동 과정

  1. 클라이언트에서 로그인을 한다.
  2. 서버에서 액세스 토큰과 리프레시 토큰을 반환한다.
  3. 클라이언트에서 리소스를 요청할 때마다 액세스 토큰을 포함한다.
  4. 서버에서 해당 토큰이 유효한지 확인한다.
  5. 만약 유효기간이 만료되는 등 유효하지 않을 경우 리프레시 토큰을 확인하여 액세스 토큰과 리프레시 토큰을 재발급해준다.

 

마치며

이번 포스팅에서는 jwt.io 사이트의 introduction 메뉴 위주로 개인적으로 궁금한 부분을 추가로 검색하여 정리해 보았다.

사실 작년에 JWT 인증을 구현해 본 적은 있는데 당시 구글링해서 코드를 대부분 가져다 썼던 기억이 난다. 또한 그때는 리프레시 토큰을 DB에 저장해서 비상태성도 지켜지지 않았다.
 
이번에는 JWT 인증 과정을 이해하고 최대한 외부 도움 없이 구현해보고자 한다. 물론 검색은 하겠지만. 😅

 

참고 사이트

 

JWT.IO

JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties.

jwt.io

 

JWT(Json Web Token) 를 알아보자

JWT란? JWT는 JSON 객체를 사용해서 유저를 인증하고 식별하기 위한 토큰기반 인증이다. 토큰 자체에 정보를 포함하고 있으며 세션처럼 서버에 저장할 필요가 없고 요청시 HTTP 헤더에 토큰을 첨부

devcheon.tistory.com

 

이미지 출처

 

JWT.IO

JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties.

jwt.io