221226 항해99 50일차 로그인

요니링 컴터 공부즁·2022년 12월 26일
0
post-thumbnail
post-custom-banner

HTTP 통신 특징

  • 웹에서는 데이터를 교환하기 위해서는 HTTP 통신을 해야한다.
  • 로그인 인증을 하기 위해서도 마찬가지다. FrontEnd에서 IDPassword를 입력하여 BackEnd로 데이터를 보낼 때, fetchaxios같은 HTTP 비동기 통신 라이브러리를 사용하게 된다.
  • HTTP 통신은 OSI 7계층에서 Application에 해당한다.
  • HTTP의 특징으로는 비연결성과 무상태성(Stateless)이 있다.
  • 서버와 클라이언트가 항상 연결되어 있는 것이 아니라 클라이언트가 요청(request)을 보내면 순간 연결이 되고, 서버가 응답(response)을 보내면 통신은 종료된다는 것이다.
  • 상태를 저장하지 않아 자원 낭비를 방지한다는 장점이 있다.
  • 하지만 이 특징으로 인해 로그인 페이지에서 IDPassword을 입력하여 서버에서 "로그인 성공!!"을 반환하더라도 마이페이지에 들어갔을 때, 서버는 내가 방금 로그인에 성공한 유저인지 모른다.
  • 유저는 다시 로그인을 해야만 마이 페이지에 들어갈 수 있게 된다. 이제 매번 어떤 행동을 할때마다 무한 로그인이다.
  • 이 문제점을 해결하기 위해서는 인증 수단이 필요하다. 세션/쿠키를 이용한 방법과 토큰 기반 인증(JWT)이 있다.

쿠키(Cookie)와 Web Storage

  • HTTP는 무상태성(Stateless)이다.
  • 하지만 유저 정보, 지역에 따른 언어 등 여러 기능들을 지원하기 위해서 CookieWeb Storage가 생기게 되었다.

Web Storage

  • Web StorageCookie에 비해 큰 데이터를 저장할 수 있고, 브라우저에 로컬하게 저장된다.
  • 그리고 서버로는 데이터가 전송되지 않는다는 특징이 있다.
  • Web Storage안에서도 Local StorageSession Stroage로 나눌 수 있다.
  • Local Storage는 만료 기간이 없고, 도메인이 다른 경우 접근이 불가능하며 브라우저를 종료해도 유지된다.
  • 이에 반해 Session Storage는 탭에 따라 개별적으로 저장되며, 탭이 종료될 때 데이터가 만료되고 같은 도메인이여도 세션이 다르면 데이터에 접근이 불가능하다.
  • 둘 다 window객체 안에 있다는 공통점이 있다.
  • XSS 공격으로 정보를 쉽게 탈취당할 수 있다는 단점도 존재한다.
  • Web Storage에 비하면 작은 데이터를 저장할 수 있지만 서버에 전송할 수 있기 때문에 서버 데이터를 공유하는 용도로 사용된다.
  • 로그인 성공시 쿠키에 "저 로그인 했어요^0^" 라는 값을 보내준다면 무상태성을 보완할 수 있는 것이다.

만료기간

  • 영구 쿠키(Persistent Cookie) : 만료 기간이 있다.
  • 세션 쿠키(Session Cookies) : 만료 기간이 없어 브라우저 종료시 삭제된다.

도메인

  • First party Cookie : 같은 도메인 또는 서브 도메인에서 생성된 쿠키
  • Third party Cookie : 다른 도메인에서 생성된 쿠키
  • SSR(Server Side Rendering)에서는 Local Storage의 값을 알 수 없기 때문에 쿠키를 활용하여 FrontEnd의 생산성을 높이기도 한다.

  • 또한, 쿠키의 HttpOnly 옵션을 통해 Script를 이용한 XSS 공격을 방지할 수 있고, Secure 옵션을 통해 쿠키를 HTTPS로만 전송되게 만들어 보안 수준을 높일 수 있다.

  • 하지만 로그인 정보를 클라이언트 브라우저의 작은 텍스트 조각인 쿠키에 저장하기에는 여전히 보안이 취약하다.

  • 스니핑과 같은 공격으로 언제든지 탈취당할 수 있다.

  • 그리고 쿠키에 대한 정보를 HTTP Header에 계속 추가해서 보내게 되어 많은 트래픽을 발생시킬 수 있다는 단점도 존재한다.

세션(Session)

  • 쿠키세션에 대해서 검색하면 항상 이 둘은 비교된다.
  • 요약하자면 쿠키는 취약하고 세션은 괜찮다는 식의 얘기이다.
  • 그 이유는 쿠키와는 달리 세션은 클라이언트의 인증 정보를 서버에서 저장하고 관리 하기 때문이다.
  • 하지만 그렇다고 해서 세션쿠키가 전혀 상관없지는 않다.
  • 세션 인증 방식에서는 세션 id쿠키에 담아서 통신하기 때문이다.

세션/쿠키 인증 방식

인증(Authentication)

  1. 유저가 ID와 Password를 입력하여 Back에 HTTP Request를 보내면서 로그인을 시도한다.
  2. BackEnd는 DB에서 유저를 확인하고, 성공시 다음 스탭을 수행하고 실패시 Front에 에러를 던져줄 것이다.
  3. 유저가 확인되면, 서버는 세션을 생성하고 저장한다.(메모리, DB, Redis 등)
  4. 여기서 얻어진 세션ID를 쿠키에 담아 Front에 반환한다. Front는 받은 세션ID를 쿠키에 저장한다.

인가(Authorization)

  1. 마이페이지와 같은 유저의 정보가 필요한 Request에 세션ID가 저장된 쿠키를 함께 보낸다.
  2. 서버에서 세션ID를 확인한다.
  3. 로그인한 유저의 마이페이지 정보를 찾는다.
  4. Front가 요청한 정보를 Response한다.

세션/쿠키 인증 장단점

  • 유저는 세션ID만 가지고 있고, 중요한 정보는 서버에 있다.
  • 탈취 당하더라도 노출될 정보는 세션ID밖에 없어 비교적 안전하다.
  • 하지만 해커가 이 세션ID를 이용해서 클라이언트인척 위장하고 나의 마이페이지를 마구마구 만질 수도 있다.
  • 그래도 세션/쿠키 방식은 서버에서 세션을 관리하므로 해킹이 의심되면 끊어버릴 수 있다.
  • 안전하게 유효기간을 두는 것도 좋은 방법이 될 것이다.
  • 그리고 세션/쿠키 방식은 고유한 세션ID만을 사용하기 때문에 서버에서 일일이 유저 정보를 확인하지 않아도 어떤 유저인지 쉽게 알 수 있다.
  • 단점으로는 역시 서버에서 세션을 관리하다보니 요청이 많아질 경우 부하가 생길 수 있다는 것이다.
  • 만약이라도 서버가 터지면 모두 끝장쓰
  • 서버를 확장할 때에도 복잡한 방법을 사용해야한다.

토큰(JWT) 인증 방식

  • 메모리, 과부하, 확장, 개발 및 유지보수 비용 등 세션 인증 방식의 문제점들을 해결할 수 있는 토큰 방식이 있다.
  • JWT(Json Web Token)는 무상태(Stateless)가 가장 큰 특징이다.
  • 유저의 인증 정보를 서버에 저장하지 않아도 된다는 특징 하나로 세션 인증 방식의 여러 문제점들을 해결할 수 있게 된 것이다.
  • 메모리를 잡아먹을일도 없고, 여러 사용자가 접속해도 과부하가 없으며, 확장에 용이하고, 개발 및 유지보수 비용이 따로 많이 들지 않는다.
  • 그렇다고 JWT가 완벽한것은 아니다.
  • 세션 인증 방식에서는 유저가 해킹당하거나 여러 기기에서 접속할 경우에 유저의 정보가 서버에 있으므로 통제가 가능하다.
  • 하지만 토큰 인증 방식은 무상태이고, 스스로 만료 주기를 갖고 있어 강제 로그아웃과 같은 통제가 불가능하다는 단점이 있다.
  • 한 번 탈취당하면, 심각한 상황이 올 수 있다는 것이다.
  • 그래서 해킹 당한 경우를 고려하여 만료 기간을 짧게 두는 방식으로 보완 하며 사용한다.

JWT

  • 인증에서 어떻게 무상태가 가능할까?
  • 바로 인증에 필요한 정보가 모두 담겨있어 Stateless가 가능한 것이다.
  • 토큰의 타입(jwt)과 해싱 알고리즘 방식을 규정하는 header, 만료 기간과 같은 토큰의 여러 정보를 담는 payload, 토큰의 유효성을 검증할때 필요한 signature로 구성되어 있다.

Access Token을 이용한 인증

  1. 유저가 ID와 Password를 입력하여 Back에 HTTP Request를 보내면서 로그인을 시도한다.
  2. BackEnd는 DB에서 유저를 확인한다.
  3. 성공시 Access Token을 발급한다.
  4. FrontEnd는 응답과 Access Token을 받는다.
  5. 유저의 정보가 필요한 요청에 Access Token을 담아 보낸다.
  6. Access Token을 검증한다.
  7. 유저 정보가 검증되면 요청했던 데이터를 응답해준다.
  • 동작 방식은 세션 인증 방식과 비슷하다.
  • Backend에 Access Token을 보낼 때, 쿠키 또는 Authorization을 사용한다.
  • 둘다 HTTP Request header 내부 필드이므로 보안성은 동일하다.
  • 어디에 담을지는 그냥 백엔드 개발자와 협의하면 된다.
  • http-only으로 보안성을 증가시킬 수 있다.

Refresh Token + Access Token

  • 토큰을 이용한 인증 방식에서 해커에게 탈취되었을 경우를 언급하며 유효 기간을 짧게 한다고 했었다.

  • Access Token의 유효 기간을 짧게 잡으면, 유저가 아직 서비스를 이용하고 있는데 갑자기 로그아웃 될 수 있다.

  • 이 불편함을 해결하고 Access Token의 유효 기간도 짧게 설정하기 위해 사용하는 것이 Refresh Token이다.
    업로드중..

  • Access Token이 만료되기 전까지의 동작 방식은 Access Token만 이용한 토큰 인증 방식과 유사하다.

  • 토큰 발급시 Refresh Token도 발급된다는 것 빼규

    1. 평소와 같이 유저의 정보가 필요한 요청과 함께 Access Token을 Back에 넘겨준다.
    2. 서버는 Access Token이 만료된 것을 확인한다.
    3. 서버는 Front에 Access Token이 만료되었다는 것을 알려준다.
    4. Front는 Access Token과 함께 Refresh Token도 같이 넘겨준다.
    5. 서버는 Refresh Token이 검증되면, 새로운 Access Token을 발급한다.
    6. 새로 발급받은 Access Token을 Front에 넘겨준다.
    7. 이전에 요청했던 것을 새로운 Access Token을 담아 서버에 보낸다.
  • 동작 방식을 보면 알 수 있듯이 구현하기는 상당히 복잡해보인다.

  • 그리고 Access Token의 유효 기간이 얼마나 짧은지에 따라 HTTP 요청수가 증가하여 서버의 자원 낭비가 일어날 수 있다.

  • 그렇다면 프론트에서 어떻게 Access Token과 Refresh Token을 관리하는지 궁금해진다.

  • 흔히 사용하는 방법은 Access Token을 서버에서 받으면 보통 상태관리에 넣고, Refresh Token은 http-only 넣는 방법이다.

Refresh Token이 탈취당하면..?

  • 데이터베이스에 각 사용자에 1대1로 맵핑되는 Access Token, Refresh Token 쌍을 저장한다.
  • 정상적인 사용자는 기존의 Access Token으로 접근하며 서버측에서는 데이터베이스에 저장된 Access Token과 비교하여 검증한다.
  • 공격자는 탈취한 Refresh Token으로 새로 Access Token을 생성한다. 그리고 서버측에 전송하면 서버는 데이터베이스에 저장된 Access Token과 공격자에게 받은 Access Token이 다른 것을 확인한다.
  • 만약 데이터베이스에 저장된 토큰이 아직 만료되지 않은 경우, 즉 굳이 Access Token을 새로 생성할 이유가 없는 경우 서버는 Refresh Token이 탈취당했다고 가정하고 두 토큰을 모두 만료시킨다.
  • 이 경우 정상적인 사용자는 자신의 토큰도 만료됐으니 다시 로그인해야 한다.
  • 하지만 공격자의 토큰 역시 만료됐기 때문에 공격자는 정상적인 사용자의 리소스에 접근할 수 없다.

참조:
오늘만큼은 로그인을 부셔보자.

post-custom-banner

0개의 댓글