sol 개발 블로그 로고
Published on

Login 유지관리

Authors
  • avatar
    Name
    Chan Sol OH
    Twitter

목차

로그인 세션 유지 관리 방법

기본적으로 서버와 브라우저는 Stateless다. 그렇다면 유저의 인증을 어떻게 저장할까? 저장된 인증 정보가 없다면 유저의 요청에 인가할 근거가 없게되는 문제가 생긴다!! 이러한 문제를 해결하기 위해 몇가지 필요사항이 있다.

  1. 서버는 유저가 회원가입할 때 받은 정보를 DB에 저장해야한다.
  2. 서버는 인증한 유저의 정보를 확인할 수 있어야한다.
  3. 브라우저는 자신이 인증된 유저임을 서버에게 증명할 수 있어야한다.

위 3가지의 기본적인 규칙을 수행하기 위해 몇가지 방법이 있다.

  1. Session : 유저의 고유 정보를 서버가 관리, 서버의 Stateful.
  2. JWT : 유저의 고유 정보를 브라우저가 관리, 서버의 Stateless.

Session

사용자가 인증을 수행하면 서버는 Session 저장소에 사용자 정보를 저장해 놓고, 브라우저에 Session ID를 저장한다. 그리고 브라우저가 Session ID를 가지고 서비스 인가를 요청하면, 서버는 그에 맞는 데이터를 확인하고 요청을 인가한다.

장점

  • 브라우저에 Session ID만 저장하기 때문에 유저 고유 정보가 유출될 가능성을 낮출 수 있다.
    • 다만, 네트워크 레이어를 해커가 훔칠 수 있다면, HTTP 전문을 훔치고 쿠키든 Token 값을 가져와서 자신의 HTTP에 담아 보내면 서버 입장에서는 유저인지 해커인지 알기 어렵긴 똑같다.
  • Cookie에 SameSite, httpOnly 설정을 통해 보안을 강화할 수 있다.
  • Session ID가 탈취되더라도 서버는 Stateful하기 때문에 서버가 능동적으로 탈취된 Session ID를 저장한 쿠키를 만료시켜 해킹을 차단할 수 있다.

단점

  • Session 저장소는 매 인가 요청이 들어올 때마다 쿼리를 수행해야하기 때문에 비싼 메모리 기반 DB(Redis)를 사용해야한다.
    • 서비스 유저가 늘어남에 따라 서버도 늘어나야하고 그에 맞춰 Session 저장소의 크기를 늘려야한다.
    • 다만, DB는 동기화의 문제가 있어서 수평적 확장에 어려움이 존재한다. 그렇기에 단순히 서버 성능을 늘리는 수직적 확장(더 비싼 DB 서버)을 적용해야한다.
  • 브라우저에 Session ID가 탈취됐을 때 상황을 가정하고 보안을 강화해야한다.
    • 예를 들어 네이버는 Session ID를 탈취하고 해킹을 시도해도 인가되지 않았다고 한다.
    • Session ID를 생성한 기기 정보나 IP 같은 기타 정보를 함께 취합해서 인가하는 것이 더 안전한 방법이다.
  • Cookie는 csrf 공격에 취약하다고 한다.

JWT

유저의 고유 정보를 Client Side Storage, 웹이라면 Cookie를 앱이라면 자체 저장소에 저장한다. JWT를 Cookie에 저장해서 사용하면 [수업 듣고 이어서 작성] 그러나 단순히 저장하면 유저 정보가 다 탈취될 것이기 때문에 암호화를 해야하지만, JWT는 BASE64 기반으로 인코딩(암호화 X)이기 때문에 보안에 취약하다. JWT는 다음과 같은 장단점이 존재한다.

장점

  • app은 브라우저와 달리 Cookie를 저장할 공간이 없기 때문에 app의 저장소에 token을 저장할 수 있다.
    • Cookie를 사용하는 브라우저용 api와 token을 사용하는 app용 api를 따로 만들지 않고, 하나로 통합하기에 빠르게 개발할 수 있다.
  • Stateless기 때문에 서버의 부하를 줄일 수 있다.
  • Signature를 통해 서버로부터 온 Payload 값의 위변조를 판단할 수 있다.
  • MSA 아키텍쳐와 같이 동기화 이슈가 있을 때 동기화할 필요조차 없는 Stateless JWT를 사용하기도 한다.

단점

  • Payload에 유저 인증 정보를 담고 있기 때문에 JWT 유출시 사용자의 타격이 크다.
    • JWT는 JS가 쉽게 접근 가능한 session/local storage에 저장하기 때문에 httpOnly, SameSite를 세팅한 Cookie 보단 보안에 취약하다.
    • JWT도 보안 세팅한 Cookie에 저장할 순 있다. 그런데 이러면 여러 도메인에 cookie를 저장하고 사용하기 쉽지 않을 것이다. ㅋㅋㅋ
  • Stateless라서 실시간성을 보장할 수 없다.
    • 서버 DB에 데이터가 변경돼도, JWT를 새롭게 발급받지 않는 이상 브라우저에는 과거 정보가 저장되어있다.
  • Stateless기 때문에 JWT가 탈취됐을 떼, 서버에서 알 수 없고, 저장된 token을 만료시킬 방법이 없다.
    • 위 문제를 방지하기 위해 짧은 만료시간을 가진 access token과 refresh token을 사용한다.
    • access token이 탈취되더라도 금방 만료되기 때문에 refresh token만 탈취되지 않으면 문제가 어느정도 해소된다.
    • 다만, 짧은 access token 만료 주기를 가진다면, 서버가 Stateful하게 되는 것과 비슷해지고, Refresh 비용이 증가할 수 있다.

무엇을 써야할까?

Session 방식과 JWT 방식을 비교했더니 둘 다 장점보단 단점이 더 많은 것 같다. 정보를 보호하는 것은 어렵기 때문에 모든 경우의 수를 고려하기 때문에 어려운 것은 당연하다. JWT는 서버의 사용량을 줄이고 MSA와 같이 동기화 문제가 발생할 아키텍처를 사용하는 경우 사용하는 것이 좋다고 생각한다. 또한, 브라우저를 사용하지 않고 쿠키를 사용할 수 없는 앱에서 인증 정보를 저장할 때 사용한다. 나머지 유저 인증 사용량이 적고, MSA가 아니고 웹 애플리케이션 서비스라면 Session을 사용하는게 맞는 것 같다.