로그인 인증방식

Creating the dots·2022년 4월 10일
0

Session Based Authorization

서버는 클라이언트로부터 유저가 로그인 시 입력한 아이디와 비밀번호를 전달받아 이 데이터가 db에 존재하는지 확인한다. 만약 존재한다면, 서버는 클라이언트의 쿠키에 sessionID를 저장하고, 서버에도 sessionID를 저장한다. 따라서, 클라이언트가 요청을 보낼때마다 서버 또는 데이터베이스에 요청을 보내 유효한 sessionID인지 확인한다.

session의 한계

만약, 저장된 sessionID가 많다면 시간이 오래 걸릴 수 있을 것 같다. 그리고 서버 확장의 관점에서 본다면, 로그인을 요청해서 sessionID를 저장하고 있는 서버로만 요청이 가야한다는 한계를 갖는다. 이를 해결하는 방법으로는 우선 sticky session이 있다.

sticky session

유저1이 1번 서버에 세션을 생성했다면, 앞으로 유저1의 모든 요청은 1번 서버로 보내집니다. 이를 가능하게 하는 것이 바로 load balancer이다. 로드 밸런서는 요청한 브라우저에 쿠키를 생성하여 해당 쿠키를 이용해 각 서버로 요청을 리다이렉트 시켜주는 역할을 한다.

  • 장점
    유저는 하나의 고정된 세션으로만 요청을 보내므로 세션의 정합성이 보장된다.

  • 단점

    • 고정된 세션을 사용함으로 특정 서버에 트래픽이 집중될 수 있다. 4개의 세션 중 하나의 세션에만 트래픽이 몰리더라도, 다른 3개의 세션은 사용될 수 없다.
    • 고정된 세션에 장애가 발생하면 해당 서버를 사용하는 유저들의 세션 정보를 모두 잃어버리게 된다.

session clustering

session clustering은 여러개의 서버가 하나처럼 작동하도록 하는 기술이다. sticky session에서는 하나의 서버가 죽으면, 해당 서버를 사용하는 유저 정보를 모두 잃어버린다는 단점이 있었는데, 이는 다른 서버들이 있기 때문에 문제가 생기지 않는다.

session clustering은 사용하는 WAS에 따라 다른 방법이 적용되기 때문에 프로젝트에서 어떤 WAS를 사용하는지 살펴보아야한다.
여기서 WAS(Web Application Server)란, 사용자의 입력을 받아 서버에서 무언가를 처리하고 그 결과를 보여주는 동적인 데이터를 처리 웹서버이다.

가장 대표적인 WAS인 톰캣이 지원하는 session clustering 방식에 대해 알아보도록 하자.

all-to-all session replication

하나의 세션에 변경이 일어나면 다른 모든 세션에 복제되는 것을 말한다. 이는 소규모 클러스터에 적합한 방식이다.

  • 장점
    • 유저의 요청이 들어왔을때, 어떤 서버로 요청이 들어가도 무관하여 하나의 서버로 트래픽이 몰리는 한계를 극복할 수 있다.
  • 단점
    • 세션을 복사/전파하기 때문에 모든 서버에 동일한 세션 정보가 저장된다. 이는 오버헤드가 크고 효율적인 메모리 관리가 어렵다.
    • 데이터 변경이 발생할때마다 세션을 복사하기 때문에 네트워크 트래픽이 증가한다.
    • 세션 전파 작업 중 모든 서버에 세션이 전파되기까지의 시간차로 세션 불일치와 같은 문제가 발생할 수 있다.

session storage

각 서버의 세션 저장소에 세션정보를 저장하는 것이 아니라, 독립된 세션 저장소에 세션 정보를 저장한다. 따라서 여러 서버들이 이 독립된 세션 저장소에서 세션정보를 읽어온다.

  • 장점
    • 모든 세션 저장소들이 하나의 독립된 세션 저장소의 데이터를 공유하기 때문에 session clustering과 마찬가지로 sticky session의 특정 서버로의 트래픽 과부하 문제가 발생하지 않는다.
    • 세션이 재설정되었을때, 세션 저장소에 있는 세션 정보만 수정하면 된다. 따라서, WAS들간의 불필요한 네트워크 통신과정을 진행하지 않아도 된다.
  • 단점
    • 만약 독립된 세션 저장소에 문제가 생긴다면 모든 WAS에 영향을 미친다. (이는 세션 저장소를 하나 더 구성하여 해결할 수 있다.)
    • 이러한 세션 저장소로는 MySQL, oracleDB 등의 RDBMS와 영속성이 필요하지 않다면 memcached를, 영속성이 필요하다면 redis를 사용할 수 있다.

Token Based Authorization (JWT)

마찬가지로, 유저정보가 db에 존재한다면, 서버는 클라이언트의 쿠키에 토큰을 저장한다. 따라서 클라이언트는 다음 요청부터는 토큰을 실어서 요청을 보낸다. 따라서 서버는 이 토큰이 유효한지 확인한다. session based authorization과는 다르게 서버에서 session id를 관리하고 있지 않다는 특징을 갖는다.

구성

생성된 토큰은 헤더, 페이로드, 시그니처로 구성되어있다.

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

  • 헤더
    암호화할 알고리즘과 토큰의 타입(이 경우는 JWT)이 정의되어있다. Base64Url로 암호화되어 있다.

  • 페이로드
    토큰을 만드는데 사용되는 데이터가 저장되어있다. 헤더와 마찬가지로 Base64Url로 암호화되어 있으므로 디코딩이 가능하기 때문에 비밀번호, 카드번호 등의 중요한 정보는 저장해서는 안된다.

  • 시그니처
    헤더와 페이로드를 설정한 비밀키로 암호화된 값이 저장된다. 만약 토큰이 탈취되어 페이로드의 토큰 유효기간을 임의로 변경한다면 Base64URL로 새롭게 암호화된 페이로드는 다른 값을 가진다. 하지만, 시그니처는 비밀키를 모르면 변경할 수 없다. 따라서, 이 토큰은 더이상 유효하지 않다.


어디에 저장할 것인가

cookieslocal storagesession storage
capacity4kb10mb5mb
browsersHTML4/ HTML5HTML5HTML5
accessible fromAny windowAny windowSame tab
expiresManually setNEVER (unless logout or manually remove)On tab close
storage locationBrowser (but sent to server)Browser onlyBrowser only

web storage: local storage, session storage

  • 자바스크립트를 사용해서 제어가 가능하다.
    자바스크립트로 값을 쉽게 저장하고 가져오고, 삭제할 수 있어 편하다.

  • XSS 공격에 취약하다.

    • XSS(Cross Site Scripting)란, 공격자가 상대방의 브라우저에 스크립트가 실행되도록 해 사용자의 세션을 가로채거나, 웹사이트를 변조하거나, 악의적 콘텐츠를 삽입하거나, 피싱 공격을 진행하는 것
  • 로컬스토리지에 저장된 액세스 토큰은 Bearer 스키마를 사용해 Authorization 헤더에 담아 HTTP 요청을 보내야한다. Authorization Bearer ${access_token} 서버에서는 이 내용을 파싱해서 토큰을 확인한다.

  • 웹스토리지와 마찬가지로 자바스크립트를 통해 제어가 가능하다.

  • 쿠키의 httpOnly 옵션을 true로 설정하면, 자바스크립트로 쿠키 접근을 제한할 수 있어 로컬 스토리지에 비해 XSS 공격에 대한 보안을 높일 수 있다.

  • 쿠키는 해당 도메인에 대해 자동으로 모든 HTTP 요청에 포함되어 보내진다.
    웹스토리지와 다르게 매 요청마다 헤더를 직접 설정해주지 않아도 된다.

  • 쿠키는 4kb로 사이즈가 제한된다.

  • CSRF 공격에 취약하다.

    • CSRF(Cross-site request forgery)는 웹사이트 취약점 공격의 하나로, 사용자가 자신의 의지와는 무관하게 공격자가 의도한 행위(수정, 삭제, 등록 등)를 특정 웹사이트에 요청하게 하는 공격
    • CSRF가 발생하는 시나리오
      A.com에서 생성한 쿠키는 B.com에서는 확인할 수 없다. A.com으로 보내는 HTTP 요청들은 브라우저가 자동으로 쿠키를 헤더에 담아서 보낸다. HttpOnly 옵션을 설정한 쿠키의 경우 자바스크립트로도 쿠키를 얻을 수 없다. 그렇다면 어떻게 쿠키를 가로챌 수 있을까?
      예를 들어, 해커가 hacking.com이라는 사이트를 만들어서 A.com을 사용하는 유저에게 해당 해킹 사이트로 접속을 유도하는 이메일을 보냈다고 해보자. 해킹 사이트의 HTML 페이지는 <img src= "https://A.com/travel_update?.src=Korea&.dst=Hell">라는 이미지 태그를 갖는다. 따라서, 유저가 해당 사이트에 접속했다면, 브라우저는 이미지 파일을 받아오기 위해 도착지를 임의로 변경하는 공격용 URL을 열 것이다. 브라우저에 A.com의 액세스 토큰이 저장되어있다면, 이 쿠키를 담아서 요청을 보낼 것이다.
      결국, 유저가 알지 못하는 사이에 도착지가 변경되는 문제가 발생한다.

    • CSRF를 해결하는 방법
      다른 사이트에서 자사의 쿠키를 가지고 인증하여 생기는 보안 이슈는 "다른 사이트"의 접근을 제한하는 것과 "자사의 쿠키 사용"을 제한하는 것으로 해결 할 수 있다.

      • 백엔드에서 CORS 설정하기
        다른 사이트의 접근 제한은 CORS 설정을 통해 해줄 수 있다. 브라우저는 보안을 위해 기본적으로 SOP(Same-Origin Policy) 정책을 따르는데, 다른 사이트에서 접근을 일부 허용해주는 정책이 CORS(Cross-Origin Resource Sharing)이다. express에서 CORS를 사용하기 위해서는 cors 미들웨어를 설치해야한다.
      • 쿠키의 sameSite 옵션 설정하기
        자사의 쿠키 사용을 제한하는 것은 쿠키의 sameSite 옵션으로 설정해줄 수 있다. express에서는 쿠키를 사용하기 위해서 cookie-parser 미들웨어를 설치해야한다.

reference

profile
어제보다 나은 오늘을 만드는 중

0개의 댓글