개발기록

[Network] 인증 토큰 방식과 세션을 통한 인증 방식 본문

네트워크@클라우드

[Network] 인증 토큰 방식과 세션을 통한 인증 방식

Danuvibe 2021. 6. 4. 15:08

웹서비스를 운영하고 구축하고자 할때! 각각의 클라이언트는 웹 서비스에서 개별적인 컨텐츠를 소비합니다. 그러므로 Client에서 API를 요청하였을 때, 서버는 누구의 요청인지 정확하게 식별해야만 합니다. 즉, 서버는 각 클라이언트의 개인적인 정보들을 보관하고 이를 클라이언트의 요청에 맞추어 제공해야만 합니다. 이러한 과정 속에 '인증'(Authentication)이 이루어지지 않는다면 개인정보가 유출되거나 변조되는 등의 취약점이 발생할 수 있습니다. 

 

HTTP 는 클라이언트(브라우저)와 서버 사이의 의사소통 방식입니다. 이러한 HTTP 는 비연결성(Connectionless)과 무상태(Stateless)라는 특성을 가집니다. 비연결성이란 클라이언트가 요청(request)을 하고, 서버가 해당 요청에 적합한 응답(response)를 하게 되면 바로 연결을 끊는 성질을 의미합니다. 

 

무상태(Stateless)

비연결적인 특성으로 연결이 해제됨과 동시에 서버와 클라이언트는 클라이언트가 이전에 요청한 결과에 대해서 잊어버리게 됩니다. 즉, 클라이언트가 이전 요청과 같은 데이터를 원한다고 하더라도 다시 서버에 연결을 하여 동일한 요청을 시도해야만 합니다.

 

 HTTP는 이러한 특성으로 인해 'Stateless Protocol' 이라고 불리며, 독립적인 쌍의 요청과 응답을 처리함으로 단순하고, 상태를 저장해야 하는 서버의 부담을 감소시킬 수 있습니다. HTTP가 비연결성과 무상태 라는 강력한 특성을 갖는 건 알겠는데 상태가 서버에 저장되어 있지 않는다면 '인증'은 어떻게 구현해야 할까요? 매번 클라이언트는 데이터베이스를 왕복하며 인증을 해야 하는 걸까요?

 

Session 기반 인증

세션 기반인증을 위해 Session 과 Cookie 가 사용된다.

 

쿠키(Cookie)

쿠키는 웹 브라우저가 보관하는 데이터입니다. 웹 서버는 쿠키를 생성하여 웹 브라우저에 정보를 전송할 수 있습니다. 쿠키는 키-밸류 형태로 웹 브라우저의 쿠키 저장소에 저장됩니다. 서버로부터 쿠키를 전달받은 웹 브라우저는 이후 웹 서버에 요청을 보낼 때 쿠키를 헤더에 실어서 함께 전송합니다. 이를 이용하면 웹 서버와 클라이언트는 필요한 값을 공유하고 상태를 유지할 수 있습니다.

 

클라이언트에 보관된 쿠키는 유효기간 설정이 가능합니다. 유효기간을 설정하면 쿠키는 특정 시간이 지나면 자동으로 소멸합니다. 유효기간을 설정하지 않을 시에는 브라우저 종료와 함께 소멸합니다.

 

하지만 쿠키만으로 로그인을 구현하는 것은 한계가 있습니다. 쿠키는 네트워크를 통해 전달되기 때문에 중간에 쿠키를 탈취할 수 있다는 취약점이 있습니다. 이를 보완하고자 우리는 세션(Session) 을 사용합니다.

 

세션(Session)

세션도 마찬가지로 클라이언트의 상태를 저장할 수 있습니다. 쿠키와 다른 점은 쿠키는 각 브라우저의 별도 쿠키 저장소에 저장되는 반면에 세션은 서버에 저장이 됩니다.

 

웹 브라우저는 각각 별도의 세션을 갖습니다. 각 세션을 구분하기 위해 고유 ID 를 할당하고, 웹 서버는 각 브라우저에 세션 ID 를 전송합니다. 웹 브라우저는 웹 서버에 연결 시 매번 세션 ID 를 보내서 웹 서버가 어떤 세션을 사용할 지 알 수 있도록 합니다. 이 때, 웹 서버와 웹 브라우저가 세션 ID 를 주고받기 위해서 사용하는 것이 쿠키입니다. (Tomcat 에서 발급하는 쿠키의 Key 는 JSESSIONID 입니다.)

이를 종합하여 로그인이 이루어지는 과정을 보겠습니다. 우리는 로그인 정보를 웹 컨테이너 메모리의 세션 객체에 저장하게 되고, 클라이언트는 세션 ID를 전송하여 브라우저 고유 세션을 식별하게 됩니다. 이 후 세션 객체 내부에 로그인 여부를 확인할 수 있는 특정 속성이 존재하면 로그인한 것으로 판단할 수 있습니다.

 

 아래 그림을 보면 클라이언트와 웹서버가 세션과 쿠키를 이용하여 어떻게 로그인 인증 절차를 가지는지 확인하실 수 있습니다.

  • 유저가 첫 로그인에 대한 검증을 마치고 웹 서버에서 로그인한 계정에 대한 세션이 서버 메모리 상에 저장된다. 이 때 세션을 식별하기 위한 Session Id 를 기준으로 정보를 저장하고 -> 웹 브라우저에 세션ID를 전달한다. 
  • 웹 브라우저에 쿠키저장소에 Session Id 가 저장된다.
  • 쿠키에 세션 정보가 담겨있기 때문에 브라우저는 해당 사이트에 대한 모든 Request에 헤더에 쿠키를 삽입해 전송한다.
  • 서버는 클라이언트가 보낸 Session Id 와 서버 메모리로 관리하고 있는 Session Id 를 비교하여 Verification 을 수행한다.

Session 기반 인증은 다음과 같은 장단점을 갖는다.

 

+ 세션 기반 인증 방식은 구현이 상당히 명확하다는 장점이 있다. 또한 실제 서버에서 로그인 상태 확인이 굉장히 유용하다.

+ 상대적으로 안전하다. 서버측에서 관리하기 때문에 클라이언트 변조에 영향받거나 데이터의 Stale (손상) 우려가 없다.

- 유저들의 세션에 대한 정보를 서버 메모리에 들고 있게 된다는 부담이 있다.

- 서버 메모리에 세션 정보가 저장되기 때문에 Scale Out / Scale In 이 부담이 될 수 있으며, 결국에는 유저 상태에 무관하게 동작할 수 있     도록 Data-Driven 아키텍처가 요구된다.

- 멀티 디바이스 환경에서 로그인 시 신경써줘야할 부분들이 생긴다. 

 

Token 기반 인증

Token 기반 인증의 방법으로 많은 웹 서버들은 JWT(JSON Web Token) 을 사용한다.

토큰 기반의 인증 시스템은 인증받은 사용자들에게 토큰을 발급하고, 서버에 요청을 할 때 헤더에 토큰을 함께 보내도록 하여 유효성 검사를 한다. 이러한 시스템에서는 더이상 사용자의 인증 정보를 서버나 세션에 유지하지 않고 클라이언트 측에서 들어오는 요청만으로 작업을 처리한다. Token 기반 인증 방식과 Session 기반 인증 방식의 가장 큰 차이점은 유저의 정보가 서버에 저장되지 않는다는 점이다.

 

 

  • 사용자가 아이디와 비밀번호로 로그인을 한다.
  • 서버 측에서 해당 정보를 검증한다.
  • 정보가 정확하다면 서버 측에서 사용자에게 Signed 토큰을 발급한다. (Signed는 해당 토큰이 서버에서 정상적으로 발급된 토큰임을 증명하는 Signature를 가지고 있다는 것)
  • 클라이언트 측에서 전달받은 토큰을 저장해두고, 클라이언트는 요청시 저장된 Token을 Http 요청 헤더에 포함시킨다.
  • 서버는 매 요청시 클라이언트로부터 전달받은 Header 의 Token 정보를 Verification 한 뒤, 해당 유저에 권한을 인가한다.

토큰 기반 인증 시스템의 이점

  1. 무상태성(Stateless) & 확장성(Scalability)
    토큰은 클라이언트 측에 저장되기 때문에 서버는 완전히 Stateless하며, 클라이언트와 서버의 연결고리가 없기 때문에 확장하기에 매우 적합하다. 만약 사용자 정보가 서버 측 세션에 저장된 경우에 서버를 확장하여 분산처리 한다면, 해당 사용자는 처음 로그인 했었던 서버에만 요청을 받도록 설정을 해주어야 한다. 하지만 토큰을 사용한다면 어떠한 서버로 요청이 와도 상관이 없다.
  2. 보안성
    클라이언트가 서버로 요청을 보낼 때 더 이상 쿠키를 전달하지 않으므로, 쿠키 사용에 의한 취약점이 사라지게 된다. 하지만 토큰 환경의 취약점이 존재할 수 있으므로 이에 대비해야 한다.
  3. 확장성(Extensibility)
    시스템의 확장성을 의미하는 Scalability와 달리 Extensibility는 로그인 정보가 사용되는 분야의 확정을 의미한다. 토큰 기반의 인증 시스템에서는 토큰에 선택적인 권한만 부여하여 발급할 수 있으며 OAuth의 경우 Facebook, Google 등과 같은 소셜 계정을 이용하여 다른 웹서비스에서도 로그인을 할 수 있다.
  4. 여러 플랫폼 및 도메인
    서버 기반 인증 시스템의 문제점 중 하나인 CORS를 해결할 수 있는데, 애플리케이션과 서비스의 규모가 커지면 여러 디바이스를 호환시키고 더 많은 종류의 서비스를 제공하게 된다. 토큰을 사용한다면 어떤 디바이스, 어떤 도메인에서도 토큰의 유효성 검사를 진행한 후에 요청을 처리할 수 있다. 이런 구조를 통해 assest 파일(Image, html, css, js 등)은 모두 CDN에서 제공하고, 서버 측에서는 API만 다루도록 설게할 수 있다.

 

+ 클라이언트에 저장되기 때문에 서버의 메모리에 부담이 되지않으며 Scale 에 있어 대비책을 고려할 필요가 없다

+ 멀티 디바이스 환경에 대한 부담이 없다.

- 상대적으로 Stale (손상) 의 위험이 크다.

- 결국 구현을 하다보면 서버측에 token blacklist 를 관리하게 될 가능성이 있고 그렇게 되면 서버측 메모리의 소모가 발생하게 된다

- Token 은 일반적으로 Session ID 보다 길다.

- XSS 공격에 취약할 수 있어 가능한 민감한 정보는 포함시키지 않을 필요가 있다.

 

 

Comments