ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • JWT(JSON Web Token)
    Programing 2024. 10. 2. 09:00

    1. JWT란 무엇인가?

    JSON Web Token(JWT)은 당사자 간에 정보를 안전하게 전송하기 위한 개방형 표준(RFC 7519)입니다. 이 정보는 디지털 서명되어 있어 신뢰할 수 있습니다. JWTs는 HMAC 알고리즘을 사용하거나 RSA 또는 ECDSA를 사용하는 공개/개인 키 쌍을 사용하여 서명할 수 있습니다.

    JWT의 구조

    JWT는 세 부분으로 구성됩니다:

    1. 헤더 (Header)
    2. 페이로드 (Payload)
    3. 서명 (Signature)

    각 부분은 점(.)으로 구분되며, Base64Url로 인코딩됩니다.

    xxxxx.yyyyy.zzzzz
    
    

    예를 들어, 실제 JWT는 다음과 같이 보일 수 있습니다:

    eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
    
    

    헤더(Header)

    헤더는 두 가지 정보를 포함합니다

    • typ: 토큰의 타입을 지정 (JWT)
    • alg: 해싱 알고리즘을 지정 (보통 HMAC SHA256 또는 RSA)

    예시:

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

    페이로드(Payload)

    페이로드는 토큰에 담을 클레임(claim) 정보를 포함합니다. 클레임은 엔티티(일반적으로 사용자)와 추가 데이터에 대한 설명입니다. 클레임의 종류는 다음과 같습니다:

    • 등록된 클레임
    • 공개 클레임
    • 비공개 클레임

    예시:

    {
      "sub": "1234567890",
      "name": "John Doe",
      "iat": 1516239022
    }
    
    

    서명(Signature)

    서명은 헤더의 인코딩값과 페이로드의 인코딩값을 합친 후 비밀키로 해싱하여 생성됩니다. 서명은 토큰이 변조되지 않았음을 확인하는 데 사용됩니다.

     

    2. JWT의 작동 방식

    1. 사용자가 자격 증명으로 로그인합니다.
    2. 서버가 사용자 정보로 JWT를 생성합니다.
    3. 서버가 JWT를 클라이언트에 반환합니다.
    4. 클라이언트는 이후의 요청에 이 JWT를 포함시킵니다.
    5. 서버는 JWT를 검증하고 요청을 처리합니다.

    3. JWT의 장점

    1. 무상태성(Stateless): 서버 측에서 세션을 저장할 필요가 없어 서버 부하를 줄일 수 있습니다.
    2. 확장성: 다중 서버 환경에서도 쉽게 사용할 수 있습니다.
    3. 유연성: 다양한 프로그래밍 언어에서 지원됩니다.
    4. 자가 수용적(Self-contained): 토큰 자체에 필요한 모든 정보가 포함되어 있습니다.

    4. JWT의 단점 및 보안 고려사항

    4.1 크기 문제

    JWT는 일반 세션 ID에 비해 크기가 큽니다. 예를 들어:

    import jwt
    
    # JWT 생성
    jwt_token = jwt.encode({"user_id": "xiaou"}, "secret", algorithm="HS256")
    print(f"JWT 크기: {len(jwt_token)} bytes")
    
    # 일반 세션 ID
    session_id = "xiaou"
    print(f"세션 ID 크기: {len(session_id)} bytes")
    
    

    이 코드를 실행하면 JWT가 일반 세션 ID보다 훨씬 크다는 것을 알 수 있습니다.

    4.2 중복 서명

    많은 웹 프레임워크에서 이미 쿠키에 서명을 제공하고 있어, JWT를 사용하면 중복 서명이 발생할 수 있습니다.

    4.3 토큰 취소 문제

    JWT는 발급 후 만료 시간까지 유효하므로, 즉시 취소가 어렵습니다. 이는 보안 위험을 초래할 수 있습니다.

    import jwt
    from datetime import datetime, timedelta
    
    # JWT 생성 (만료 시간 30분)
    expiration_time = datetime.utcnow() + timedelta(minutes=30)
    jwt_token = jwt.encode({"user_id": "xiaou", "exp": expiration_time}, "secret", algorithm="HS256")
    
    # 로그아웃 시도
    # 주의: 이 방식으로는 토큰을 즉시 무효화할 수 없음
    print("로그아웃 시도 - 하지만 토큰은 여전히 유효함")
    
    # 토큰 검증 (여전히 유효)
    try:
        decoded = jwt.decode(jwt_token, "secret", algorithms=["HS256"])
        print("토큰이 여전히 유효함:", decoded)
    except jwt.ExpiredSignatureError:
        print("토큰이 만료됨")
    
    

    4.4 데이터 최신성 문제

    사용자의 권한이 변경되어도, 기존 토큰은 만료 전까지 이전 권한을 유지합니다.

    4.5 암호화 부재

    기본적으로 JWT는 서명만 되고 암호화되지 않아, 중간자 공격에 취약할 수 있습니다.

    import jwt
    
    # JWT 생성 (암호화되지 않음)
    jwt_token = jwt.encode({"user_id": "xiaou", "role": "admin"}, "secret", algorithm="HS256")
    
    # JWT 내용 확인 (누구나 디코딩 가능)
    decoded = jwt.decode(jwt_token, options={"verify_signature": False})
    print("JWT 내용 (암호화되지 않음):", decoded)
    
    

    5. 결론 및 권장 사항

    JWT는 일회성 인증 토큰으로는 적합하지만, 장기적인 세션 관리에는 적합하지 않을 수 있습니다. 운영 환경에서는 다음을 고려해야 합니다:

    1. 세션 관리: 전통적인 서버 측 세션을 고려하세요.
    2. 토큰 수명: JWT를 사용한다면, 짧은 만료 시간을 설정하세요.
    3. 암호화: 필요한 경우 JWE(JSON Web Encryption)를 사용하여 토큰을 암호화하세요.
    4. 토큰 저장: 클라이언트 측에서 토큰을 안전하게 저장하세요 (예: HttpOnly 쿠키).
    5. 갱신 전략: 리프레시 토큰을 사용하여 보안을 강화하세요.

    JWT는 강력한 도구이지만, 적절한 사용 사례와 보안 고려사항을 신중히 검토해야 합니다. 개발 목적으로는 학습에 유용할 수 있지만, 운영 환경에서는 보안 전문가와 상의하여 최적의 인증 전략을 선택하는 것이 좋습니다.

Designed by Tistory.