인증과 인가란?

세션과 JWT에 대해서 설명드리기 전에 인증과 인가에 대해서 말씀드리겠습니다. 인증이란 Authentication 으로 사용자 또는 장치의 신원을 확인하는 과정입니다. 예를 들어 어떤 서비스를 이용하기 전에 아이디와 패스워드를 입력해서 서비스가 사용자의 신원을 확인하는 과정을 인증이라고 합니다. 인가는 Authorization 으로 사용자가 어떤 리소스에 접근할 수 있는지 또는 어떤 동작을 수행할 수 있는지 검증을 하는 것을 의미합니다. 예를 들어 무신사에서 상품을 삭제하는 기능을 사용자가 사용할 수 있는지 권한을 확인하는 과정을 의미합니다.

저희가 서비스를 개발할 때 인증과 인가를 사용해서 현재 로그인되어 있는 사용자가 어떤 기능을 사용할 수 있는지 확인하는 과정을 거쳐야합니다. 그런데 저희가 사용하는 HTTP 는 클라이언트가 서버에 요청을 보내고, 서버가 클라이언트에게 데이터를 응답하는 방식으로 동작하는 프로토콜인데, HTTP 의 대표적인 특징으로는 Stateless가 있습니다. Stateless란 클라이언트와 첫번째 통신에서 데이터를 주고받았을지라도, 두번째 통신에서는 이전 데이터를 유지하지 않는다는 것입니다. 그렇기 때문에 로그인 상태를 유지하기 위해서는 서버에 요청을 보낼 때마다 내가 누구인지를 알려줘야 합니다.

그런데 모든 요청마다 사용자가 로그인을 할 수는 없으니 로그인 상태를 유지해야하는데 이때 사용되는 기술이 세션과 JWT입니다.

세션

세션 방식 로그인은 기존에 전통적으로 많이 사용되어온 방식입니다.

세션 방식의 로그인 과정은 아래와 같습니다.

유저가 사이트에 접속을 한 후 로그인을 진행합니다. 유저가 로그인을 완료하면 서버에서 세션 ID를 생성하고 세션 ID, 사용자 정보, 세션 유효기간 등의 정보가 담긴 새로운 세션을 생성하고 서버의 메모리나 세션 스토어등에 저장합니다 생성한 세션 ID를 클라이언트에 Header 의 Set-Cookie로 전달해줍니다. 이후 클라이언트에서는 서버로부터 전달받은 세션 ID를 클라이언트의 쿠키에 저장합니다. 해당 사이트에 대한 모든 요청에 세션 ID를 담은 쿠키를 함께 전송합니다. 서버는 클라이언트가 보낸 세션 ID와 서버에서 관리하고 있는 세션 ID를 비교해서 일치한다면 인가를 수행해줍니다. 이 과정에서의 중요한 점은 유저의 정보들을 서버 쪽에서 관리한다는 것입니다.

세션의 장점은 아래와 같습니다.

  1. 사용자 정보가 서버에 저장되기 때문에 클라이언트가 정보를 직접 보관하지 않아 보안성이 높습니다.
  2. 클라이언트는 세션 ID만 저장하면 되기 때문에, 클라이언트의 저장 공간을 절약할 수 있습니다.
  3. 서버에서 세션 정보를 관리하므로, 사용자의 추가 정보나 상태를 쉽게 업데이트하고 관리할 수 있습니다.
  4. 사용자가 여러 장치에서 로그인할 경우, 서버는 이를 관리해서 사용자가 각 장치에서 동일한 세션을 사용할 수 있게 하여 편리함을 제공해줍니다.

단점은 아래와 같습니다 서버는 모든 사용자 세션 정보를 메모리나 데이터베이스에 저장해야 하므로, 많은 사용자 트래픽을 처리할 경우 서버의 리소스가 많이 소모됩니다. 중앙 세션 스토어가 아닌, 서버 컴퓨터의 메모리나 하드디스크에 저장할 경우 확장성이 좋지 않습니다. 그 이유는 서버 컴퓨터를 추가할 경우 각 서버 컴퓨터마다 세션 정보를 공유해야하기 때문입니다. 사용자의 아이디와 패스워드를 몰라도 공격 대상이 이미 시스템에 접속되어 세션이 연결되어 있는 상태를 가로채기 하는 공격으로 공격자가 인증 작업 등이 완료된 정상적으로 통신하고 있는 다른 사용자의 세션을 가로채서 별도의 인증 작업을 거치지 않고 가로챈 세션으로 통신을 계속하는 세션 하이재킹 공격을 당할 수 있습니다. 이를 방지하기 위해 HTTPS를 사용해 요청 자체를 탈취해도 정보를 읽기 힘들게 하고, 세션에 유효기간을 넣어, 정보를 탈취하더라도 유효기간이 끝나면 더이상 해커가 이용할 수 없도록 해야합니다.

JWT

JWT는 JSON Web Token의 약자로 특수한 형태의 문자열입니다

. 을 기준으로 구분되어 header, payload, signature 로 구성되어 있습니다. JWT는 암호화되어 있지 않기때문에 누구나 확인할 수 있습니다. 그렇기 때문에 중요한 정보를 JWT에 담으면 안됩니다.

Header에는 typ 와 alg 라는 정보가 존재하는데 typ 에는 토큰의 타입이 작성되어 있고, alg에는 Signature 에서 사용하는 알고리즘이 무엇인지가 작성되어 있습니다.

Payload에는 토큰의 실제 내용을 담고 있습니다. 여기에는 클레임 이라고 불리는 정보 조각이 포함됩니다.

Signature에는 헤더와 페이로드를 조합하여 특정 비밀키로 서명되어 생성됩니다. Signature를 사용해 해당 토큰이 변조되지 않았음을 검증하는 데 사용됩니다.

JWT 토큰을 사용한 로그인 과정에 대해서 설명해보겠습니다.

사용자가 사이트에 접속을 한 후 로그인을 진행합니다. 로그인이 완료되면 서버에서 JWT 토큰을 생성하고 클라이언트에 전송합니다. 클라이언트는 JWT 토큰을 쿠키나 로컬 스토리지에 저장을 하고 모든 요청에 Authorization 헤더에 JWT 토큰을 포함하여 서버에 전송합니다. 서버에서는 JWT에 포함된 Signature를 확인하여 토큰의 무결성을 검사하고 만료 시간을 체크한 후에 요청을 처리합니다. 앞의 세션과의 가장 큰 차이점은 세션은 사용자의 정보를 서버에 저장하고 SESSIONID만 클라이언트에 전송하는 것과 사용자의 정보를 JWT 토큰에 저장하고 토큰 자체를 클라이언트에 전송하는 것입니다.

JWT 방식의 로그인의 장점에 대해서 말씀드리겠습니다.

  1. JWT는 클라이언트에 저장되므로 서버는 사용자 세션 정보를 유지할 필요가 없어 서버의 메모리 사용량을 줄이고 여러 대의 서버 사용을 용이하게 만듭니다.
  2. JWT는 사용자 정보의 메타데이터를 토큰 자체에 포함하기 때문에 서버는 JWT를 검증함으로써 사용자의 정보를 즉시 조회할 수 있어 별도의 데이터베이스 호출이 필요하지 않습니다.
  3. http 헤더나 url 파라미터를 통해 간단하게 전송되기 때문에 네트워크 부하가 적습니다

다음으로 JWT 방식의 로그인의 단점에 대해서 말씀드리겠습니다.

  1. XSS 공격에 대한 취약성입니다. XSS 공격은 악성 스크립트를 웹 페이지에 삽입해 사용자의 브라우저에서 실행되도록 하는 공격 방식입니다. JWT 토큰이 클라이언트 측의 로컬 스토리지나 세션 스토리지에 저장되면, 악의적인 스크립트가 삽입될 경우 XSS 공격에 의해 JWT가 탈취될 수 있으며, 이렇게 탈취된 토큰을 공격자가 사용할 수 있습니다.
  2. CSRF 공격에 대한 취약성입니다. CSRF 공격은 신뢰할 수 있는 사이트에서 사용자의 인증이 되어있을 때 사용자의 웹 브라우저가 악의적인 웹사이트나 이메일, 메시지 등에 의해 원치않는 action을 수행하는 공격입니다. 이러한 공격은 웹 브라우저의 request가 자동적으로 세션 쿠키를 포함한 모든 쿠키를 자동적으로 포함하기 때문에 발생합니다. JWT를 쿠키에 저장할 경우, 요청 시 자동으로 포함되기 때문에 CSRF 공격에 취약할 수 있습니다.
  3. 토큰의 크기 문제입니다. JWT는 헤더, 페이로드, 서명을 포함하기 때문에 상대적으로 크기가 커 요청 시 매번 전송해야 할 데이터량이 많아질 수 있습니다. 이는 네트워크 대역폭을 낭비하게 됩니다.
  4. 정보를 수정할 수 없습니다. JWT는 서명된 토큰으로 발급 후에 내용을 수정할 수 없습니다. 사용자 정보가 변경되면 새로운 JWT를 발급받아야 하며, 추가적인 서버 자원 소모를 유발할 수 있습니다
  5. 탈취 시 접근 허용 JWT가 탈취당하면 해당 토큰을 사용하여 공격자가 인증된 사용자로 서버에 접근할 수 있다는 문제가 생깁니다. 특히 JWT는 서버에서 상태를 유지하지 않기 때문에, 토큰 자체를 검증하는 방식으로 작동하며, 탈취된 토큰이 만료되기 전까지는 이를 무효화하기 어렵습니다. 따라서, 탈취된 JWT는 만료 시점까지 악용될 수 있으며, 이를 방지하려면 짧은 만료 시간을 설정하고, 추가로 리프레시 토큰이나 IP 확인 등 보안 조치를 도입하는 것이 필요합니다.

결론적으로 세션 방식의 로그인과 JWT 방식의 로그인 중 하나를 선택할 때에는 사용 환경과 요구 사항에 따라 결정을 해야합니다. 세션 방식은 서버에서 사용자의 세션을 관리하기 때문에, 보다 강력한 보안을 요구하는 상황에 적합하고, 특히 사용자 정보를 서버에 안전하게 저장하고 싶거나, 실시간으로 사용자 세션을 업데이트해야 하는 경우에 유리합니다. 예를 들어 금융 서비스와 같이 사용자의 데이터 보호가 중요한 시스템에서 세션 방식을 사용합니다. JWT 로그인 방식은 서버의 상태를 유지하지 않기 때문에 확장성이 뛰어나고 서버의 부하를 줄일 수 있습니다. MSA 와 같이 분산된 시스템에서는 JWT 방식이 유용할 수 있습니다.