본문 바로가기

ETC

JWT(Json Web Token)에 대해

[JWT(Json Web Token)이란]

Json Web Token (JWT)는 정보를 JSON 객체로 안정하게 전송하기 위한 간결한 토큰입니다.(RFC 7519)

HMAC와 같이 암호화 해시 함수와 기밀 암호화 키를 갖는 메시지 인증 코드 또는 RSA 또는 ECDSA를 사용하는 public/private key을 사용하여 서명을 합니다.

이처럼 서명되어 있기 때문에 확인하고 신뢰할 수 있습니다.

토큰 안에 포함된 클레임(Claim)의 무결성을 확인 할 수 있으며 암호화된 토큰은 이러한 클레임(Claim)을 다른 참조로부터 숨길 수 있습니다.

public/private key를 이용하여 토큰에 서명할 때 서명은 개인키를 보유하고 있는 참조만 서명했다는 것을 증명할 수 있습니다.

 

[JWT는 언제 사용할까?]

Authorization

사용자가 로그인한 뒤, 이후 요청에는 JWT가 포함되어 사용자가 해당 토큰으로 허용되는 경로, 서비스 및 리소스에 액세스할 수 있습니다.

SSO(Single Sign-On)은 오버헤드가 적고 여러 도메인에서 쉽게 사용할 수 있기 때문에 JWT를 널리 사용하는 기능입니다.

Information Exchange

JWT는 정보를 안전하게 전송하는 좋은 방법입니다.

예를 들어 public/private key를 이용해서 JWT에 서명할 수 있기 때문에 발신자가 누구인지 확인할 수 있습니다.

또한 Header와 Payload를 사용하여 서명을 계산하므로 데이터가 변조되지 않았는지 확인할 수도 있습니다.

 

[JWT의 구조]

JWT는 점(.)으로 구분된 세 부분으로 구성되어 있습니다.

그리고 각 JSON으로 이루어진 부분들은 Base64Url로 인코딩되어 표현됩니다.

xxxxx.yyyyy.zzzzz

  • Header
  • Payload
  • Signature

Header

Header는 일반적으로 JWT인 토큰 유형과 HMAC SHA256 또는 RSA와 같은 사용 중인 서명 알고리즘으로 typ과 alg 두부분으로 구성됩니다.

  • typ: 토큰 타입 지정
  • alg: 알고리즘 방식을 지정

Payload

Payload에는 클레임(Claim)이 포함되어 있는데 클레임은 엔터티(일반적으로 사용자) 및 추가 데이터에 대한 설명입니다.

클레임에는 등록된 클레임, 공개 클레임 및 비공개 클레임의 세 가지 유형이 있습니다.

(등록된 클레임(Registered claims))

필수는 아니지만 유용하고 상호 운용 가능한 클레임 집합을 제공하기 위해 권장되는 미리 정의된 클레임 집합입니다.

  • iss(토큰 발급자)
  • exp(토큰 만료 시간) 👉 NumericDate 형식이어야 하며, 현재 시간보다 이후로 설정되어있어야합니다.
  • sub(토큰 제목)
  • aud(토큰 대상자)
  • nbf(토큰의 활성 날짜) 👉 NumericDate 형식으로 날짜를 지정하며, 이 날짜가 지나기 전까지는 토큰이 처리되지 않습니다.
  • iat(토큰 발급 시간)
  • jti(JWT의 고유 식별자) 👉 중복처리 방지를 위해 사용하며 일회용 토큰에 사용하면 유용합니다.

(공개 클레임(Public claims))

JWT를 사용하는 사람들이 마음대로 정의할 수 있습니다.

그러나 충돌을 방지하려면 IANA JSON Web Token Registry에 정의되어있고 또는 충돌 방지 네임스페이스를 포함하는 URI로 정의해야 합니다.

 

(비공개 클레임(Private claims))

사용에 동의하고 등록된 클레임이나 공개 클레임이 아닌 정보를 공유하기 위해 생성된 맞춤 클레임입니다.

 

Signature

서명 부분을 생성하려면 인코딩된 헤더, 인코딩된 페이로드, 암호, 헤더에 지정된 알고리즘을 가져와서 서명해야 합니다.

Signature은 메시지가 도중에 변경되지 않았는지 확인하는데 사용되며 private key로 서명된 토큰의 경우 JWT의 보낸 사람이 누구인지 확인할 수도 있습니다.

 

[JWT 동작원리]

인증에서 사용자가 자격 증명을 사용하여 성공적으로 로그인하면 JWT(Json Web Token)이 반환됩니다.

토큰은 자격 증명이므로 보안 문제를 방지하기 위해 주의해야하며 토큰을 필요 이상으로 오래 보관해서는 안 됩니다.

또한 보안이 취약하므로 민감한 세션 데이터를 브라우저 저장소에 저장해서는 안 됩니다.

사용자가 액세스하려고 할 때마다 사용자 에이전트는 일반적으로 Bearer 스키마를 사용하여 Authorization 헤더에서 JWT를 보내야 합니다.

Authorization: Bearer <token>

서버의 보호 경로는 Authorization 헤더에 유효한 JWT가 있는지 확인하고 JWT가 있는 경우 사용자는 보호된 리소스에 접근할 수 있습니다.

일부 서버는 8KB 이사으이 헤더를 허용하지 않기 때문에 HTTP 헤더를 통해 JWT 토큰을 보내는 경우 토큰이 너무 커지지 않도록 해야 합니다.

모든 사용자 권한을 포함하는 것과 같이 JWT 토큰에 너무 많은 정보를 포함하려는 경우 Auth0와 같은 대체 솔류션이 필요할 수 도 있습니다.

  1. 애플리케이션 또는 클리이언트가 authorizaton server에 권한을 요청합니다.
  2. 권한이 부여되면 authorizaton server는 애플리케이션에 액세스 토큰(access token)을 반환합니다.
  3. 애플리케이션은 액세스 토큰을 사용하여 보호된 리소스(e.g. API)에 액세스합니다.

서명된 토큰을 사용하면 토큰에 포함된 모든 정보가 변경할 수 없더라도 사용자 또는 다른 사용자에게 노출되므로 토큰 안에 private 정보를 넣으면 안 됩니다.

 

[JWT의 장단점]

장점

  • JWT 의 주요한 이점은 사용자 인증에 필요한 모든 정보는 토큰 자체에 포함하기 때문에 별도의 인증 저장소가 필요 없습니다.
  • 쿠키를 전달하지 않아도 되므로 쿠키를 사용함으로써 발생하는 취약점이 사라집니다.
  • URL 파라미터와 헤더로 사용
  • 트래픽 대한 부담이 낮음
  • REST 서비스로 제공 가능
  • 내장된 만료
  • 독립적인 JWT

단점

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

 

 

Reference.
https://jwt.io/introduction
https://velopert.com/2389
https://gorokke.tistory.com/181

 

'ETC' 카테고리의 다른 글

[JPA] JPA N+1 문제 및 해결방안  (0) 2022.09.11
www.google.com을 입력했을 때 웹 동작방식  (0) 2022.09.03
GET, POST, PUT  (0) 2022.06.21
Git 연습하기  (0) 2022.01.09
회고를 작성하기 위한 KPT, 5F  (0) 2021.12.31