개발자_H 2023. 4. 21. 14:04
반응형

2023.04.19 - [개발을 파헤치다/쉽게 풀어쓴 개념] - JWT(JSON Web Token)은 왜 쓸까? 등장하게 된 배경

 

JWT(JSON Web Token)은 왜 쓸까? 등장하게 된 배경

JWT는 무엇인가 JWT(JSON Web Token)는 웹상에서 사용되는 토큰에 대한 표준 규격(RFC 7519)을 얘기합니다. 특정 기술 이름이 아니라 HTTP처럼 표준을 정의한 것입니다. 의미를 한번 파헤쳐서 살펴보면 JSON

show-me-the-money.tistory.com

이전 글에서는 JWT(JSON Web Token)이 등장하게 된 배경과 개념에 대해서 알아봤습니다. 

이번에는 JWT의 구조와 장단점에 대해서 좀 더 명확하게 살펴보도록 하겠습니다.

JWT 구조

JWT로 인증을 하는 방식 자체는 Cookie&Session을 사용했을 때와 완전히 다르지는 않습니다. 하지만 JWT가 기존의 문제를 해결할 수 있는 이유는 서명된 토큰이라는 점. 그래서 사용자 식별 정보를 Token 자체에 담을 수 있다는 점입니다. 서명이 되어있기 때문에 서버에서 이 Token이 정상인지 아닌지 검증할 수 있습니다. 

JWT는 아래와 같은 구조를 가지는데요.


  • Header : 토큰의 유형과 서명 알고리즘이 명시됩니다.
  • Payload : 사용자의 인증/인가 정보가 포함됩니다.
  • Signature : Header와 Payload가 개인키로 서명되어 저장됩니다.

 

Header

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

Header에는 위와 같이 토큰의 유형(typ)과 어떤 알고리즘(alg)을 사용했는지 명시됩니다.

Payload

{
    "sub": "1",
    "iss": "ori",
    "exp": 1636989717,
    "iat": 1636987917
}

Payload에는 보통 Claim이라고 하는 사용자의 인증에 대한 정보를 담고 있습니다.
JWT의 장점은 인증을 위해 매번 DB 테이블을 조회할 필요가 없다는 점인데요. 
바로 Payload에 정보가 들어있기 때문에 가능합니다. Claim에 어떤 값을 넣을지는 개발자가 정할 수 있지만 JWT의 표준 스펙을 알아보는 게 먼저겠죠. 

표준 스펙상 Key값은 3글자로 되어있습니다.

  • iss (Issuer) : 토큰 발급자
  • sub (subject) : 인증 주체. 사용자에 대한 식별 값
  • aud (audience) : 토큰 대상자. 클라이언트를 의미합니다
  • exp (expiration time) : 토큰 만료 시간
  • iat (issued at) : 토큰 발급 시간
  • nbf ( not before) : 토큰 활성 날짜. 이 날짜 이전의 토큰은 활성화 되지 않음을 의미
  • jti (JWT Id) : JWT 토큰 식별자. issur가 여러 명일 때 이를 구분하기 위한 값

표준 스펙으로 이렇게 정의가 되어있고 이것이 모두 들어갈 필요는 없습니다.
서비스 특성이나 서버 아키텍처를 고려해서 정의하면 됩니다.

중요한 원칙은 Payload에 민감한 정보를 담지 않는 것입니다. Header나 Payload는 json이 인코딩 되어있을 뿐이지 특별한 암호화가 걸려있는 것이 아니기 때문에 누구나 이 값을 가지고 디코딩을 한다면 Header나 Payload값을 알 수 있습니다.
다시 말해서, JWT에는 단순히 식별을 하기 위한 정보만을 담아야합니다. 민감한 개인정보는 절대 넣어서는 안 됩니다.

Signature

위의 Signature 구조를 확인해 보면 JWT를 생성할 때 Base64로 인코딩 된 Header와 Payload를 개인키를 가지고 암호화합니다. 그 결과값이 Signature인 것이죠. 이 값은 서버에있는 개인키로만 암호화를 풀 수 있기때문에 클라이언트가 풀 수 있는 방법이 없습니다.

JWT 인증과정을 살펴보면,

  • JWT를 헤더에 담아 클라이언트가 서버로 HTTP 요청을 보낸다
  • 서버가 개인키를 가지고 Signature를 복호화 한 다음, base64로 인코딩된 header와 payload를 디코딩하고 그 값이 일치하는지 확인한다.
  • 값이 일치하면 인증을 허용한다.

만약 클라이언트가 payload에 조작된 값을 넣어 요청을 보내면 서버가 애초에 발급했던 정보와 다르므로 인증이 거부되겠죠.

 

 

 

JWT 장단점

장점

  • 이미 JWT 자체가 인증된 정보이기 때문에 세션 저장소와 같이 별도의 인증 관련 저장소가 필수적으로 필요하지 않습니다.
  • 클라이언트의 상태를 저장하지 않기 때문에 사용자가 많이 늘어나도 Session에 비해 크게 메모리를 차지하지 않습니다.
  • 사용자를 식별할 수 있는 정보가 토큰에 포함되어 있기 때문에 Session을 사용할 때와 달리 인증 관련 조회가 필요 없습니다.
  • Cookie를 사용하지 않으므로 CORS(Cross-Origin Resource Sharing) 문제에서 자유롭습니다.

단점

  • 인증관련 특정한 기능을 구현할 때 한계가 있을 수 있습니다. 예를 들어, 현재 로그인된 사용자의 모든 장비들을 나열해 주는 것처럼 사용자의 상태값을 서버에서 알아야 하는 기능구현에는 제한사항이 있습니다.
  • Cookie&Session과는 다르게 base64 인코딩을 통해 정보를 전달하므로 데이터의 크기가 큽니다. 네트워크 전달 시 부하가 더 생길 수 있습니다.
  • Token을 탈취당하면 만료될 때까지 대처가 불가능하다.

 

마지막 단점으로 쓴 Token 탈취에 대해서 부가적으로 설명을 드리겠습니다.
Session의 경우 Cookie만 쓸 때에 비해 좋았던 점이 바로 보안적인 부분이었는데요.
Session ID를 탈취당하더라도 저장소의 값을 지워서 인증이 안되도록 할 수 있었죠.
하지만 JWT 같은 경우 한번 서버에서 발급을 하게 되면 클라이언트가 관리하는 형태이기 때문에 서버 쪽에서 조치할 수 있는 게 없습니다. 

이런 경우 JWT 스펙에 나와있던 토큰 만료 시간(exp)을 짧게 가져가는 것으로 보완할 수 있는데요. 만료시간을 짧게 가져가면 토큰이 탈취된다고 해도 짧은 시간만 유효하기 때문에 피해를 최소화할 수 있겠죠.

반응형