배운것들

세션 기반 인증과 토큰 기반 인증

Chamy619 2021. 11. 10. 16:31

HTTP 는 상태가 없는 stateless 프로토콜이기 때문에 웹 서버는 요청을 보낸 클라이언트가 로그인한 회원인지에 인증하는 작업이 필요합니다. 인증 방식은 세션 기반 인증과 토큰 기반 인증으로 나뉘고, 두 방식의 동작 및 장단점에 대해 설명하도록 하겠습니다.

세션 기반 인증

세션

일정 시간 동안 같은 사용자(브라우저)로 부터 들어오는 일련의 요구를 하나의 상태로 보고 그 상태를 일정하게 유지시키는 기술

동작 방식

  1. 클라이언트가 로그인을 요청하면 서버는 세션 ID 를 키로 갖는 세션을 메모리에 저장
  2. 서버는 세션 ID 를 쿠키에 담아 클라이언트에게 전달
  3. 클라이언트는 로그인 이후 모든 요청에 세션 ID 가 담긴 쿠키를 함께 전송
  4. 서버는 클라이언트에게 받은 세션 ID 가 세션 메모리에 있는지 확인하고, 응답을 전송

특징

세션 기반 인증은 사용자의 로그인 정보를 서버 메모리 또는 DB 에 저장하고 관리합니다. 따라서 강제 로그아웃 등과 같은 조치를 쉽게 할 수 있고 서버에서 사용자의 로그인 상태 정보를 가지고 있기 때문에 뒤에서 설명할 토큰 기반 인증보다 상대적으로 안전합니다.

 

하지만 서버에서 모든 사용자의 로그인 상태 정보를 가지고 있어야 하기 때문에 사용자가 많아질수록 메모리 또는 DB 에 부하가 생기게 됩니다. 또한 멀티 디바이스 환경에서 로그인할 때 어떻게 디바이스를 식별하고 세션을 저장할 것인지에 대해 생각해야 합니다.

 

서버 메모리가 아닌 외부 저장소를 사용해 세션을 저장하게 될 경우에도 모든 요청마다 저장소에서 세션 정보를 꺼내서 확인하는 작업이 발생하게 되므로 토큰 방식보다 외부 저장소에 요청을 하는 빈도가 더 많습니다.

만날 수 있는 문제

다중 서버에서 세션 클러스터링

다중 서버에서 서버 메모리에 세션 정보를 저장하게 될 경우 모든 서버끼리 메모리는 공유하지 않기 때문에 로그인한 사용자는 자신의 세션이 저장되어 있는 서버로만 요청을 보내야 정상적인 응답을 받을 수 있습니다.

로드 밸런서가 사용자 1을 2 번 서버로 연결해주면 2번 서버는 사용자 1의 로그인 정보를 가지고 있지 않기 때문에 제대로 된 응답을 주지 않게 됩니다.

Sticky 세션

Sticky 세션 방식은 사용자의 요청에 쿠키가 있으면 해당 쿠키에 있는 정보를 바탕으로 지정도니 서버로 요청을 보내는 방식입니다. 위의 그림에서 사용자 1이 1번 서버에서 처음 로그인하고 쿠키가 생성되었으면, 이후 모든 요청은 서버 1에게 전송되게 됩니다.

 

Sticky 세션을 사용하게 될 경우 로드 밸런서의 효율을 떨어뜨리고, 한 대의 웹 서버에 요청이 집중될 수도 있습니다.

세션 클러스터링

세션 클러스터링 방식은 모든 서버가 같은 세션 정보를 가지고 있게 함으로 다중 서버에서 세션 인증시 발생할 수 있는 문제를 해결합니다. 모든 서버가 같은 세션 정보를 가지고 있기 때문에 로그인한 사용자는 어느 서버로 요청을 보내더라도 같은 응답을 받을 수 있습니다.

 

세션 클러스터링 방식의 단점은 서버 메모리 비효율이 발생한다는 점입니다. 하나의 세션을 추가하려고 할 때 모든 서버에 세션 정보를 저장해야하기 때문에 추가적인 네트워크 요청도 발생합니다.

세션 스토리지

세션을 서버 메모리에 저장하지 않고 별도의 저장소에 저장하는 방식입니다. 이러게 되면 새로 서버를 추가하게 되더라도 세션 스토리지에 연결만 해주면 되기 때문에 세션 기반 인증 방식의 확장이 어렵다는 단점도 극복할 수 있습니다. 하나의 세션 저장소(여러 대의 저장소를 사용할 수도 있지만)를 사용하기 때문에 세션 클러스터링에서 세션을 복사하기 위해 발생하는 추가적인 네트워크 요청도 발생하지 않고, 메모리 비효율도 일어나지 않습니다.

정리하면 세션 인증 방식은 세션 정보를 서버에서 관리하는 방식입니다. 클라이언트는 세션 ID 와 같은 의미가 크지 않은 정보만을 가지고 있으면 되기 때문에 토큰 방식보다 상대적으로 안전합니다. 하지만 다중 서버에서 고려해야 할 점들이 있고, 모든 요청에 메모리 또는 세션 스토리지에 세션 정보를 확인하는 작업이 필요하기 때문에 사용자가 많아질수록 부하가 발생할 수 있습니다.

토큰 기반 인증

토큰 기반 인증은 세션에 대한 정보를 클라이언트에서 가지고 있고, 이를 사용해 인증을 하는 방식입니다.

동작 방식

  1. 클라이언트가 로그인을 요청하면 서버는 사용자에 대한 토큰을 생성한 후 클라이언트에게 전달
  2. 이후 모든 요청에 토큰 함께 전송
  3. 서버는 클라이언트로에게 받은 토큰이 유효한 토큰인지 검증한 후 응답을 전송

특징

전통적인 토큰 기반 인증의 경우 세션을 서버 메모리에 저장하지 않기 때문에 메모리 부하에 대해 걱정할 필요가 없습니다. 또한 세션 정보를 서버에서 관리하지 않기 때문에 확장에도 유리합니다.

 

하지만 토큰에 사용자 정보가 담겨 있고, 외부에 공개되어 있기 때문에 노출되어도 문제가 되지 않는 정보만 토큰에 담아야하고, 강제 로그아웃 등과 같은 기능을 사용하려면 별도의 작업이 필요합니다. 또한 한번 발행된 토큰은 이후에 서버에서 제어가 힘들고, 토큰을 주로 브라우저의 로컬 스토리지에 저장하게 되는데 서버에 저장되어 있는 것보다 탈취될 위험이 더 크기 때문에 이에 대한 대책을 만들어야 합니다.

만날 수 있는 문제

토큰의 탈취 및 토큰 유효 시간

토큰 기반 인증 방식에서 서버는 한 번 발행한 토큰을 삭제할 방법이 없습니다. 따라서 토큰을 탈취한 공격자가 아무런 제지 없이 악의적인 요청을 서버에 전송할 수 있게 됩니다. 악의적인 공격을 눈치챈 사용자가 계정 신고를 한 이후 처리 부분도 문제가 될 수 있습니다. 세션 기반 인증의 경우 해당 세션을 지워 로그아웃 처리를 하고, 이후 로그인을 하지 못하도록 처리할 수 있는데 토큰 기반 인증의 경우 블랙 리스트 관리를 하려면 세션 스토리지와 같은 별도의 저장소를 사용해야 합니다.

액세스 토큰과 리프레시 토큰

위에서 설명한 토큰의 역할을 액세스 토큰이 하게 되고, 액세스 토큰이 만료 되었을 때 별도의 로그인 없이 리프레시 토큰으로 액세스 토큰을 발급 받는 방식입니다. 액세스 토큰은 짧은 만료 기간(30분~2시간)을 갖고, 리프레시 토큰은 상대적으로 긴 만료 기간(2주~1개월)을 갖습니다. 액세스 토큰은 서비스를 이용할 때 로그인한 회원인지 인증하는 용도로 사용하고 리프레시 토큰은 만료된 액세스 토큰을 재발급 받기 위해서만 사용됩니다.

리프레시 토큰을 발행하는 방식을 사용하면 악의적인 사용자 신고가 들어왔을 때, 해당 유저의 경우 액세스 토큰을 발행하지 않는 방법을 사용할 수 있습니다. 또한 토큰이 탈취 되더라도 액세스 토큰의 만료 기간이 짧기 때문에 한 개의 토큰을 사용할 때보다 더 안전합니다.

 

토큰 기반 인증의 경우 세션에 대한 정보를 클라이언트에서 가지고 있습니다. 따라서 확장에 용이하고, 모든 요청에 데이터베이스에 로그인 정보를 확인하지 않아도 되기 때문에 서버와 데이터베이스의 부하를 줄일 수 있습니다. 하지만 토큰은 사용자에 대한 정보를 가지고 있기 때문에 민감한 정보를 담지 않도록 주의해야 하고 토큰의 길이가 세션 ID 의 길이보다 훨씬 길기 때문에 서버와 클라이언트 사이의 네트워크 부하가 발생합니다.

정리

클라이언트 - 서버 사이의 네트워크 부하를 고려해야 한다면 세션 기반 인증이 더 유리하고, 서버 - DB 사이의 통신 횟수 및 확장성을 고려해야 한다면 토큰 기반 인증 방식이 더 유리하다고 생각됩니다.

참고자료

https://tansfil.tistory.com/58?category=475681

https://tansfil.tistory.com/59?category=475681

https://tjdrnr05571.tistory.com/3