본문 바로가기
Springboot Study/Springboot Security

JWT (JSON Web Token)

by xogns93 2024. 11. 1.

1. Token의 역할과 특징

토큰은 HTTP의 상태 비저장성을 보완하고, 사용자 인증, 세션 관리, 권한 부여를 보다 안전하게 관리하기 위해 웹 애플리케이션에서 사용됩니다. 주로 클라이언트와 서버 간 인증 및 통신 과정에서 사용됩니다.

  • 주요 기능
    • 인증 (Authentication): 사용자가 누구인지 확인하고, 그 사용자가 시스템에 접근할 수 있는 권한을 서버에 알림.
    • 세션 관리 (Session Management): 각 요청에 토큰을 포함해 사용자 세션을 관리. 이 방식은 서버 확장성과 무관하게 작동하여 서버 부담을 줄임.
    • 권한 부여 (Authorization): 토큰에 사용자의 권한 정보가 담겨 있어, 서버는 해당 사용자의 접근 권한을 쉽게 판단할 수 있음.
    • 보안 (Security): 토큰은 서명(Signature)을 포함하여 변조 방지 및 무결성을 보장하고, CSRF(Cross-Site Request Forgery)와 같은 공격으로부터 보호 가능.

2. JWT의 구성 요소와 구조

JWT (JSON Web Token)는 세 가지 주요 요소 (Header, Payload, Signature) 로 이루어져 있으며, 점(.)으로 구분되어 header.payload.signature 형식으로 구성됩니다.

  1. Header

    • 토큰 유형과 서명에 사용되는 암호화 알고리즘 정보를 포함.
    • 보통 typ (토큰 타입, JWT)와 alg (암호화 알고리즘, HS256) 두 가지 정보로 구성됨.
    { "alg": "HS256", "typ": "JWT" }
  2. Payload

    • 클레임(Claims)이라고 불리는 인증, 권한 부여와 관련된 사용자 정보가 담김.
    • 주요 클레임:
      • 등록된 클레임 (Registered Claims): JWT 표준에 정의된 클레임, 예를 들어 iss(발급자), exp(만료 시간), sub(주제, 사용자 ID).
      • 공개 클레임 (Public Claims): 서비스 간 상호 운영을 위해 IANA에 등록되거나 URL 형태로 정의됨. 예를 들어 role, email.
      • 비공개 클레임 (Private Claims): 두 시스템 간에 협의된 클레임으로, 보통 사용자별 세부 정보를 담음.
    {
      "sub": "1234567890",
      "name": "John Doe",
      "admin": true
    }
  3. Signature

    • 헤더페이로드를 각각 Base64URL로 인코딩하여 서버의 비밀 키로 서명해 JWT의 무결성을 보장.
    • 서버는 이 서명을 통해 클라이언트가 전송한 JWT가 변조되지 않았음을 확인할 수 있음.
    HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)

3. JWT 사용 과정

JWT는 보통 클라이언트와 서버 간의 인증정보 교환 과정에서 사용됩니다. 인증 과정에서 사용자는 ID와 비밀번호를 통해 인증을 시도하고, 서버는 이를 검증한 후 JWT를 발급해 클라이언트에 반환합니다.

  1. JWT 발급: 사용자가 로그인하면 서버가 사용자의 인증 정보를 확인하고 JWT를 생성하여 클라이언트에 전달.
  2. 토큰 저장: 클라이언트는 이 토큰을 로컬 스토리지나 세션에 저장하고, 추후 요청에 사용할 수 있도록 관리.
  3. 요청 시 토큰 전송: 클라이언트는 요청마다 Authorization: Bearer <토큰> 형식으로 서버에 전송하여 인증을 대신함.
  4. 서명 검증 및 만료 확인: 서버는 클라이언트가 전송한 JWT의 서명과 만료 시간을 검증하여, 유효한 토큰인지 확인.
  5. 리프레시 토큰 갱신: 만료된 토큰의 경우, 리프레시 토큰을 통해 새로운 액세스 토큰을 발급받아 계속 사용할 수 있음.

4. JWT의 장점

  • 자가 포함된 구조 (Self-contained): JWT는 필요한 정보를 자체적으로 포함하므로, 서버가 상태 비저장(stateless) 상태를 유지 가능.
  • 간결함 (Compactness): JSON 형식을 Base64URL로 인코딩하여 크기가 작아 네트워크 오버헤드가 적음.
  • 모바일 친화성: 모바일 환경에서 클라이언트가 저장하고 네트워크 연결이 가능할 때만 서버에 전송하면 되어, 세션 유지 부담을 줄일 수 있음.
  • 크로스 도메인 인증: JWT는 특정 도메인에 의존하지 않고, CORS 정책을 지원해 크로스 도메인 요청에서도 사용 가능.
  • 확장성: 서버가 사용자 세션을 직접 관리하지 않아 서버 확장이 용이함.

5. JWT의 단점과 보완 방법

  • 보안 문제: Base64로 인코딩된 정보는 누구나 읽을 수 있어 민감 정보를 담아서는 안 됨. 민감 정보는 별도의 안전한 저장소에서 관리.
  • 토큰 길이 문제: Self-contained 구조로 인해 많은 데이터가 포함될수록 토큰이 길어질 수 있음. 필요한 최소한의 정보만 포함하도록 설계.
  • 상태 관리의 어려움: 토큰을 강제로 만료시키기 어려워 보안이 복잡. 주기적인 토큰 갱신과 짧은 만료 시간 설정이 필요.
  • 재사용 공격 위험: HTTPS를 통해 안전하게 전송하고, 클라이언트 측에서도 안전한 위치에 저장 필요.

6. 보안 고려 사항

  • 서명 검증: 클라이언트가 보낸 JWT는 서버가 서명을 검증하여 변조되지 않았음을 확인해야 함.
  • 만료 시간 설정: JWT의 exp 클레임을 통해 만료 시간을 설정하고, 만료된 토큰은 서버에서 거부함으로써 보안을 강화.
  • HTTPS 사용: 탈취 위험을 방지하기 위해 HTTPS 프로토콜로 전송하여 암호화 필요.
  • 저장 위치: 클라이언트가 토큰을 안전하게 저장하도록 HttpOnly 및 Secure 설정을 권장.

7. JWT 활용 사례

  • 인증 (Authentication): 클라이언트가 JWT를 통해 본인의 신원을 인증하여 요청을 전송할 수 있음.
  • 권한 부여 (Authorization): 서버는 토큰의 권한 정보로 사용자가 특정 리소스에 접근할 수 있는지를 판단.
  • 정보 교환 (Data Exchange): 서버 간, 또는 클라이언트와 서버 간 안전한 데이터 전송 가능.

JWT는 웹 애플리케이션에서 인증, 권한 부여, 세션 관리 등 다양한 보안 요구사항을 만족하는 효과적인 방법으로, 특히 상태 비저장 방식으로 확장성과 보안성을 동시에 높여줍니다.