JWT란?

p-q·2023년 11월 14일
1
post-thumbnail

JWT를 사용하며 JWT에 대해 정리한 글입니다.

1. JWT란?

JWT(JSON WEB TOKEN)는 당사자 간에 정보를 JSON 객체로 안전하게 전송하기 위한 간결하고 독립적인 방법을 정의하는 개방형 표준입니다.

간단히 말해서 서로 다른 서비스 간에 발신자를 확인할 수 있는 민감한 정보가 포함된 json 형식의 암호화된 문자열입니다.

2. JWT의 구조

JWT는 헤더, 페이로드, 서명의 세 부분으로 구성됩니다. 각 부분은 토큰의 보안과 무결성을 보장하는 데 중요한 역할을 합니다.

따라서 JWT는 일반적으로 다음과 같은 모양을 취합니다.

xxxxx.yyyyy.zzzzz

1. Header

헤더는 일반적으로 두 부분으로 구성됩니다. 토큰 유형(JWT)과 사용 중인 서명 알고리즘(예: HMAC SHA256 또는 RSA)이 그것입니다.

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

그런 다음 이 JSON은 Base64Url로 인코딩되어 JWT의 첫 번째 부분이 됩니다.

2. Payload

토큰의 두 번째 부분은 페이로드이며, 여기에는 클레임이 포함됩니다. 클레임은 엔티티(일반적으로 사용자)와 추가 데이터에 대한 표현입니다. 클레임에는 등록 클레임, 공개 클레임, 비공개 클레임의 세 가지 유형이 있습니다.

  • 등록 클레임(Registered claims)
    토큰에 대한 정보들을 담고있는 필수는 아니지만 권장되는 사전 정의된 클레임 세트입니다.

    iss (Issuer) : JWT 발급자
    발행한 주체를 식별합니다.
    sub (Subject) : JWT의 주체(사용자)
    aud (Audience) : JWT가 대상인 수신자
    exp (Expiration Time) : JWT가 만료되는 시간
    NumericDate 형식으로 되어있어야 하며 언제나 현재 시간보다 이후로 설정되어 있어야 합니다.
    nbf (Not Before) : 처리를 위해 JWT를 수락해서는 안 되는 시간
    NumericDate 형식으로 되어있어야 하며 클레임을 처리하려면 현재 시간과 같거나 이전 이어야 합니다.
    iat (Issued At) : JWT가 발급된 시간으로, JWT의 연령을 결정하는 데 사용할 수 있습니다.
    jti (JWT ID) : 고유 식별자, JWT가 반복되는 것을 방지하는 데 사용할 수 있습니다(토큰을 한 번만 사용할 수 있음).

  • 공개 클레임(public claims)
    이름 및 이메일과 같은 일반 정보를 포함할 수 있는 공개용 사용자 지정 클레임을 만들 수 있습니다. 공개 클레임을 생성하는 경우 등록하거나 네임스페이스를 통해 충돌 방지 이름을 사용해야 하며, 사용하는 네임스페이스를 통제할 수 있도록 적절한 예방 조치를 취해야 합니다.

  • 비공개 클레임(Private claims)
    비공개 사용자 지정 클레임을 만들어 애플리케이션과 관련된 정보를 공유할 수 있습니다. 예를 들어 공개 클레임에는 이름, 이메일과 같은 일반적인 정보가 포함될 수 있지만 비공개 클레임에는 직원 ID, 부서 이름과 같은 보다 구체적인 정보가 포함될 수 있습니다.

3. signature

서명은 JWT 발신자가 실제 발신자인지 확인하고 메시지가 중간에 변경되지 않았는지 확인하는 데 사용됩니다.

서명을 생성하기 위해 Base64로 인코딩된 헤더와 페이로드를 비밀과 함께 가져와서 헤더에 지정된 알고리즘으로 서명합니다.

예를 들어 HMAC SHA256 알고리즘을 사용하여 토큰에 대한 서명을 만드는 경우 다음과 같이 하면 됩니다:

HMACSHA256(
      base64UrlEncode(header) + "." +
      base64UrlEncode(payload),
      secret)

3. JWT 작동 방식

1. 토큰 생성 과정

  • 헤더와 페이로드 설정: JWT는 먼저 헤더(header)와 페이로드(payload)로 구성됩니다. 헤더는 토큰의 유형(JWT)과 사용된 서명 알고리즘을 명시합니다. 페이로드는 클레임(claim)이라고 불리는 정보 조각을 포함하며, 이는 사용자 식별 정보나 토큰에 대한 다른 데이터를 담을 수 있습니다.

  • 서명 생성: 헤더와 페이로드는 각각 Base64로 인코딩되고, 이 둘을 합친 다음 서버의 비밀 키 또는 공개/개인 키 쌍을 사용하여 서명(sign)합니다. 이 서명 과정은 토큰이 중간에 변경되지 않았음을 보장하는 데 중요합니다.

2. 토큰 검증 과정

  • 토큰의 서명 검증 : 클라이언트로부터 받은 JWT는 서버에서 서명을 검증합니다. 이는 서버가 가지고 있는 비밀 키 또는 공개 키를 이용하여 이루어집니다. 서명이 유효하면 토큰이 안전하게 생성되었으며, 중간에 변경되지 않았음을 의미합니다.
  • 페이로드의 정보 사용: 서명이 유효하다고 확인되면, 페이로드에서 정보를 추출하여 사용합니다. 이 정보는 사용자 인증, 권한 부여 등에 활용될 수 있습니다.

이러한 과정을 통해 JWT는 웹 애플리케이션과 API에서 안전하고 효율적인 방법으로 사용자 인증 및 정보 교환을 가능하게 합니다. JWT의 구조와 이 두 가지 핵심 프로세스의 조합은 웹 보안에서 중요한 역할을 합니다.

4. JWT 사용의 장점

단순 웹 토큰(SWT) 및 SAML 토큰과 비교할 때 JWT를 사용하면 여러 가지 이점이 있습니다.

  • 더 컴팩트합니다: JSON은 XML보다 덜 장황하므로 인코딩할 때 JWT는 SAML 토큰보다 작습니다. 따라서 JWT는 HTML 및 HTTP 환경에서 전달하기에 좋은 선택입니다.

  • 더 안전하게: JWT는 서명을 위해 X.509 인증서 형식의 공개/개인 키 쌍을 사용할 수 있습니다. 또한 JWT는 HMAC 알고리즘을 사용하여 공유 비밀로 대칭적으로 서명할 수도 있습니다. SAML 토큰은 JWT와 같은 공개/개인 키 쌍을 사용할 수 있지만, 모호한 보안 허점을 도입하지 않고 XML 디지털 서명을 사용하여 XML에 서명하는 것은 JSON에 서명하는 단순성에 비해 매우 어렵습니다.

  • 더 일반적인: JSON 파서는 객체에 직접 매핑되기 때문에 대부분의 프로그래밍 언어에서 일반적입니다. 반대로 XML에는 자연스러운 문서와 객체 간 매핑이 없습니다. 따라서 SAML 어설션보다 JWT로 작업하기가 더 쉽습니다.

  • 처리하기 쉽습니다: JWT는 인터넷 규모에서 사용됩니다. 즉, 사용자의 디바이스, 특히 모바일에서 처리하기가 더 쉽습니다.

5. JWT 사용예시

JWT는 다양한 방법으로 사용할 수 있습니다:

  • 인증: 사용자가 자격 증명을 사용하여 로그인에 성공하면 ID 토큰이 반환됩니다. OIDC(OpenID Connect) 사양에 따르면 ID 토큰은 항상 JWT입니다.

  • 권한 부여: 사용자가 로그인에 성공하면 애플리케이션이 해당 사용자를 대신하여 경로, 서비스 또는 리소스(예: API)에 액세스하도록 요청할 수 있습니다. 이렇게 하려면 모든 요청에서 액세스 토큰을 전달해야 하며, 이 토큰은 JWT 형태일 수 있습니다. 싱글 사인온(SSO)은 형식의 오버헤드가 적고 여러 도메인에서 쉽게 사용할 수 있다는 점 때문에 JWT를 널리 사용합니다.

  • 정보 교환: JWT는 서명이 가능하므로 발신자가 본인이 맞는지 확인할 수 있으므로 당사자 간에 정보를 안전하게 전송하는 좋은 방법입니다. 또한 JWT의 구조를 통해 콘텐츠가 변조되지 않았는지 확인할 수 있습니다.

6. JWT의 보안 문제

JSON Web Token (JWT)은 웹 애플리케이션과 API에 널리 사용되고 있지만, 몇 가지 잠재적인 보안 취약점이 있습니다. 이러한 취약점을 이해하는 것은 JWT를 안전하게 사용하는 데 매우 중요합니다.

  1. 서명 알고리즘의 취약성: JWT는 서명을 통해 데이터의 무결성을 보장합니다. 그러나, 사용하는 알고리즘이 취약하거나 구현에 오류가 있을 경우, 공격자가 토큰을 위조하거나 변조할 수 있습니다. 예를 들어, 'None' 알고리즘을 사용하는 경우 서명 검증이 생략될 수 있으며, 이는 보안 위험을 증가시킵니다.
  2. 키 관리의 어려움: JWT는 비밀 키 또는 공개/개인 키 쌍을 사용해 서명합니다. 이 키들의 안전한 관리가 이루어지지 않을 경우, 토큰의 보안이 크게 저하될 수 있습니다. 키가 노출되거나 잘못 관리되면, 공격자가 유효한 토큰을 생성할 수 있게 됩니다.
  3. 교차 사이트 스크립팅(XSS) 공격: 웹 애플리케이션에서 JWT를 클라이언트 측에 저장할 경우 (예: 쿠키, 로컬 스토리지), XSS 공격에 취약해질 수 있습니다. 공격자가 악의적인 스크립트를 주입하여 사용자의 JWT를 탈취할 수 있으며, 이를 통해 사용자의 세션을 탈취하거나 악의적인 행동을 할 수 있습니다.
  4. 토큰 만료 관리: JWT는 만료 시간을 포함하고 있지만, 이를 적절히 관리하지 못하면 보안 문제가 발생할 수 있습니다. 오래된 토큰이 계속 사용되거나, 만료된 토큰이 재사용되는 경우 보안에 구멍이 생길 수 있습니다.
  5. 안전하지 않은 토큰 전송: JWT는 텍스트 형태로 전송되므로, 전송 과정에서 보안이 중요합니다. HTTPS와 같은 안전한 연결을 사용하지 않으면, 중간자 공격을 통해 토큰이 노출될 수 있습니다.

이러한 잠재적 취약점을 고려하여, JWT를 사용할 때는 안전한 알고리즘 선택, 키의 안전한 관리, XSS 공격 방지를 위한 적절한 저장 방법 선택, 토큰의 만료 및 재사용 관리, 그리고 데이터 전송의 보안을 강화하는 것이 중요합니다.

7. JWT 관리 모범 사례

JWT (JSON Web Token) 관리의 모범 사례를 알고 있으면, 웹 애플리케이션과 API의 보안을 크게 향상시킬 수 있습니다. 여기에 안전한 JWT 사용을 위한 중요한 팁과 요령을 소개합니다.

  1. 강력한 서명 알고리즘 사용: JWT의 보안은 대부분 서명에 의존합니다. HS256(최소한의 표준) 이상의 강력한 서명 알고리즘을 사용하세요. 가능하다면, RSA나 ECDSA 같은 비대칭 서명 알고리즘을 고려하는 것이 좋습니다.
  2. 키 관리 강화: 비밀 키와 공개/개인 키 쌍은 안전하게 보관하고 정기적으로 갱신해야 합니다. 키가 유출되는 것을 방지하기 위해, 안전한 환경에 키를 저장하고 접근 권한을 엄격히 제한해야 합니다.
  3. 최소한의 클레임 사용: JWT는 필요한 최소한의 정보만을 포함해야 합니다. 민감한 개인 정보는 토큰에 포함하지 않는 것이 좋습니다. 클레임은 명확하고, 간결해야 하며, 해석이 모호하지 않아야 합니다.
  4. 토큰 만료 시간 설정: JWT는 만료 시간을 명시적으로 설정해야 합니다. 짧은 만료 시간은 보안을 강화하지만, 사용자 경험에 영향을 줄 수 있으므로 적절한 균형을 찾아야 합니다.
  5. 토큰 취급 주의: 클라이언트 측에서 JWT를 저장할 때는 XSS 공격을 방지하기 위해 쿠키보다는 HTTPOnly와 Secure 플래그가 설정된 쿠키를 사용하거나, 가능한 한 서버 측에서 관리하는 것이 좋습니다.
  6. 안전한 토큰 전송: JWT는 항상 HTTPS와 같은 안전한 채널을 통해 전송되어야 합니다. 이렇게 하면 중간자 공격에 대한 위험을 줄일 수 있습니다.

8. 최신 웹 보안에서 JWT의 역할

JWT는 웹 기반의 인증과 권한 부여 과정에서 핵심적인 요소로 자리 잡았습니다. 이 토큰은 안전하고 효율적인 방법으로 사용자 신원을 확인하고, 서버와 클라이언트 간의 정보 교환을 쉽게 만듭니다. 특히, 단일 페이지 애플리케이션(SPA), 모바일 애플리케이션, 그리고 마이크로서비스 아키텍처에서 JWT의 중요성은 더욱 부각됩니다.

보안 측면에서, JWT는 사용자 인증 정보를 안전하게 전송할 수 있게 해주며, 이를 통해 사용자와 시스템 간의 신뢰를 구축합니다. 또한, JWT는 확장성이 뛰어나고 다양한 플랫폼과 언어에서 쉽게 구현할 수 있어, 현대의 다양한 웹 애플리케이션 개발 요구사항을 충족시킵니다.

하지만, 모든 기술과 마찬가지로, JWT도 적절히 관리되고 보안이 유지되어야 합니다. 잘못된 관리나 구현은 보안 취약점을 초래할 수 있으므로, JWT를 사용할 때는 모범 사례를 따르는 것이 중요합니다.

요약하자면, JWT는 웹 보안의 현재와 미래에서 중요한 역할을 하고 있습니다. 그것은 간편하고, 유연하며, 강력한 인증 수단으로서 웹 애플리케이션의 보안을 강화하는 데 필수적인 요소입니다

참고 자료

JWT-introduce
JWT-doc
auth0-Tokens

profile
ppppqqqq

0개의 댓글