컴퓨터공학

JWT (JSON Web Token)

도우 2024. 11. 19. 10:43
반응형

일반적인 사용자 인증 방법

 

세션 기반 인증 (Session-Based Authentication)

세션 기반 인증은 웹 어플리에이션에서 가장 일반적으로 사용되는 사용자 인증 방식이다.

주요 동작과정은 다음과 같다.

로그인 과정

  1. 사용자가 ID/비밀번호를 서버에 전송
  2. 서버는 credentials(자격증명)을 검증
  3. 검증 성공 시 고유한 세션 ID 생성
  4. 세션 ID를 서버의 세션 저장소에 저장
  5. 세션 ID를 쿠키를 통해 클라이언트에 전송

인증 확인 과정

  1. 클라이언트는 매 요청마다 쿠키에 저장된 세션 ID를 전송
  2. 서버는 세션 저장소에 해당 세션 ID 유효성 검증
  3. 유효한 경우 요청 처리, 아닌 경우 에러 응답

세션 기반 인증에서 사용자가 서버로 로그인 요청을 보내면 서버는 해당 사용자의 인증 정보를 검증한 후 세션 ID를 발급한다.

이 세션 ID는 서버의 메모리나 데이터베이스와 같은 세션 저장소에 저장되며 동시에 클라이언트의 쿠키에도 저장된다.

이후 사용자가 요청을 보낼 때마다 쿠키에 저장된 세션 ID를 함께 전송하고 서버는 이 세션 ID의 유효성을 검증하여 인증된 사용자인지 확인한다.

이러한 세션 기반 인증의 가장 큰 장점은 중요한 인증 정보와 사용자 데이터가 서버에만 안전하게 저장된다는 점이다.

만약 세션 ID를 탈취당했다 하더라도 서버측에서 즉시 세션 ID를 수정하여 세션을 무효화할 수 있어 보안 통제가 용이하다.

 

세션 기반의 단점

위와 같은 장점에도 불구하고 세션 기반 인증에는 여러 단점이 존재한다.

우선 서버에 저장된 세션 정보를 바탕으로 세션 ID의 유효셩을 일일이 확인해야 하기 때문에 동시 접속자가 많을 경우 서버 메모리에 부담이 될 수 있다.

또한 서버를 확장할 때 세션 정보의 동기화 문제가 발생하여 이를 위해 별도의 클러스터링이나 Redis와 같은 중앙화된 세션 저장소가 필요하다.

이러한 서버 의존적인 인증 구조는 최근 마이크로서비스 아키텍처(MSA)와 같은 분산 환경에서 더욱 큰 문제가 된다.

각각의 서비스마다 세션 정보를 공유하고 동기화해야 하는 부담이 생기며, 이는 시스템의 복잡도를 높이고 확장성을 저해하는 요인이 된다.

또한 모바일 애플리케이션의 증가로 다양한 클라이언트 환경을 지원해야 하는 현대의 웹 서비스에서 쿠키 기반의 세션 관리는 플랫폼 간 호환성 문제를 야기할 수 있다.

이러한 세션 기반 인증의 한계를 극복하기 위해 등장한 대안이 바로 JWT(JSON Web Token)이다.

JWT는 필요한 모든 정보를 토큰 자체에 포함시키기 때문에 서버에 별도의 저장소가 필요하지 않으며, 이는 서버의 부하를 줄이고 분산 환경에서도 효과적으로 작동할 수 있게 한다. 각 서비스는 토큰 자체만으로 사용자를 인증할 수 있어 세션 동기화 문제에서도 자유롭다.

 

JWT - 토큰 기반 인증 (JSON Web Token)

JWT(JSON Web Token)는 당사자간 정보를 JSON 객체로 안전하게 전송하기 위한 온전성을 보장하는 토큰이다. JWT는 필요한 모든 정보를 토큰 자체에 포함하기 때문에 별도의 저장소가 필요하지 않다.

클레임(Claim)이라 불리는 사용자 정보들을 JSON 형태로 저장하는데, 이는 서버의 메모리에 저장되는 세션 방식과 달리 클라이언트 측에서 저장하고 관리한다.

JWT는 Header, Payload, Signature 세 부분으로 구성되며 각 부분은 점(.)으로 구분된다.

  • JWT의 구성요소
    Header : 토큰의 타입, 알고리즘의 종류
    Payload : 토큰에 담을 정보
    Signature : Header와 Payload를 기반으로 한 암호화 정보

세 부분 모두 Base64로 인코딩 되어 URL에서 안전하게 전송 가능한 문자열로 구성된다.

Payload에는 토큰에 담을 정보인 클레임(Claim)이 들어가는데, 이는 등록된 클레임(Registered Claim), 공개 클레임(Public Claim), 비공개 클레임(Private Claim)으로 구분된다.

등록된 클레임은 토큰 정보를 표현하기 위해 이미 정해진 종류의 데이터 조각들로, 선택이 가능하다.

{
  // Registered claims (등록된 클레임)
  "iss": "example.com",  // 발급자
  "exp": 1622444800,     // 만료시간
  "sub": "user@123",     // 주제
  "iat": 1622441200,     // 발급시간
  
  // Public claims (공개 클레임)
  "name": "John Doe",
  "role": "admin",

  // Private claims (비공개 클레임)
  "user_id": 123,
  "company": "Example Corp"
}

※ 클레임 : 토큰의 본문(Payload)에 포함된 정보 조각들을 의미

JWT의 클레임 타입 분류는 공개/비공개의 개념이 아닌, 클레임의 사용 목적과 표준화 정도에 따른 구분이다. JWT의 모든 정보는 Base64로 인코딩되어 있기 떄문에, 기본적으로 누구나 디코딩하여 열람이 가능하다.

이 말인 즉슨, JWT에 포함된 정보는 비밀로 유지되지 않는다. 따라서 클레임의 공개와 비공개의 구분은 보안적 요소가 아닌 정보의 범용성과 목적을 기준으로 한 의미적 구분이다.

  • 등록된 클레임: JWT 표준 스펙에 정의된 클레임
  • 공개 클레임: 공개된 표준 스펙에 정의된 클레임 (URI 형식)
  • 비공개 클레임: 당사자 간에 협의된 커스텀 클레임

 

JWT 프로세스

JWT인증 프로세스는 크게 로그인을 통한 토큰 발급 과정과 토큰을 사용하여 API에 접근하는 인증 과정으로 나눌 수 있다. 먼저 로그인 과정에서 클라이언트는 사용자의 ID와 비밀번호를 서버에 전송하고, 서버는 이 credentials(자격 증명 : 사용자가 제출한 인증 정보, 여기선 ID/비밀번호를 의미한다)를 검증한다.

검증이 성공하면 서버는 사용자 정보를 담은 JWT를 생성하여 클라이언트에게 반환한다. 이때 생성되는 JWT는 헤더, 페이로드, 서명으로 구성되어 각각의 JSON 객체는 Base64로 인코딩된다.

발급된 토큰으로 인증이 필요한 API를 호출할 때, 클라이언트는 Authorization 헤더에 ‘Bearer’ 스키마와 함께 토큰을 포함하여 요청을 보낸다.

서버는 요청을 받을 때마다 토큰의 유효성을 검증하고, 검증이 성공하면 요청을 처리한다. 이때 토큰의 검증은 서명 확인과 만료 시간 확인 등을 포함한다.

하지만 이러한 기본적인 JWT 인증 방식은 토큰 탈취 위험과 토큰의 유효기간 관리라는 두 가지 문제에 직면한다. 이를 해결하기 위한 방식으로 Access TokenRefresh Token을 함께 사용하는 것이다.

 

Access Token과 Refresh Token

AccessToken과 Refresh Token은 이중 토큰 인증 방식은 JWT의 보안적 한계를 보완하기 위해 도입되었다. Access Token은 실제 리소스에 접근하기 위한 인증 토큰으로 사용되며, 비교적 짧은 유효기간을 가진다. 보통 15분에서 1시간 정도로 설정되며 API 요청 시 Authorization 헤더에 ‘Bearer’ 스키마와 함께 포함되어 전송된다. 이는 Access Token이 탈취되더라도 짧은 유효기간으로 인해 피해를 최소화 하기 위함이다.

Refresh Token은 Access Token의 재발급을 위한 용도로 사용되며 보통 1~2주 정도의 긴 유효기간을 가진다. Access Token과 달리 데이터베이스에 저장되어 관리되며, 사용될 때마다 유효성을 검증한다.

초기 로그인 시 서버는 사용자 인증 후 Access Token과 Refresh Token을 모두 발급한다. 이떄 Refresh Token은 데이터베이스에 저장되고, 두 토큰은 모두 클라이언트에게 전송된다. 클라이언트는 발급받은 Access Token으로 API를 호출하며, 이 토큰이 만료되면 Refresh Token을 사용하여 새로운 Access Token을 발급받는다.

토큰 갱신 프로세스에서 서버는 전달받은 Refresh Token의 유효성을 검증하고, 데이터베이스에 저장된 토큰과 비교한다. 검증이 성공하면 새로운 Access Token을 발급하여 클라이언트에게 전달한다.

이때 추가적인 보안을 위해 Refresh Token도 함께 재발급하는 토큰 순환(Token Rotation) 방식을 적용할 수 있다. 또한 Refresh Token이 탈취되는 경우를 대비하여 토큰의 재사용을 감지하고 이를 무효화하는 등의 추가적인 보안 조치가 필요하다. 이러한 이중 토큰 방식은 보안성을 강화하면서도 사용자 경험을 해치지 않는 효과적인 인증 방식으로 평가받고 있다.

 

JWT의 장단점

JWT의 주요 장점은 세션 관리가 필요 없다는 것이다. JWT는 토큰 자체에 모든 정보를 포함하고 있기 때문에 별도의 세션 저장소가 필요하지 않다. 이는 서버의 자원을 절약할 수 있게 한다.

또한 토큰 기반으로 다른 로직에서도 쉽게 인증 절차를 진행할 수 있어, 모바일 애플리케이션 환경에서도 잘 동작한다. 토큰의 무결성이 보장되어 데이터 위변조가 불가능하며, CORS 문제를 해결할 수 있다.

하지만 단점도 존재한다. 토큰의 길이가 세션 ID에 비해 길어 네트워크 부하가 증가할 수 있다. 또한 Payload 자체는 암호화되지 않아 중요한 정보를 담을 수 없다. 또한 한 번 발급된 토큰은 만료 전까지 계속 사용이 가능하여 토큰이 탈취당했을 경우 대처가 어렵다.

하지만 이는 토큰 만료 시간을 짧게 설정하고 서버 데이터베이스에 저장된 Refresh Token을 활용하는 방식(ex: Refresh Token을 만료시켜 Access Token 재발급 거부)을 고려해야 한다.

 

마무리

JWT는 토큰 자체에 인증 정보를 포함하여 서버의 상태를 유지할 필요가 없고, 확장성이 뛰어난 인증 방법으로, 마이크로서비스 아키텍처나 다양한 클라이언트를 지원해야 하는 상황에서 매우 유용하다.

그러나 JWT도 탈취 가능성, 토큰 유효기간 관리 등의 문제를 반드시 고려해야 하며, 이를 위해 Access Token과 Refresh Token의 조합을 사용하는 이중 토큰 방식이 효과적으로 활용되고 있다. 이러한 인증 방법을 이해하고 적절하게 사용하는 것이 애플리케이션의 보안성을 강화하고 사용자 경험을 향상시키는 중요한 요인이다.

반응형