[CS] 인증과 인가 이해 - HTTP 통신, 쿠키, 세션, 토큰

Benjamin·2023년 6월 14일
0

CS

목록 보기
10/10

왜 인증/인가를 알아야할까?

어느 서비스나 로그인은 대게 필수기능이다.

  • 로그인 구현에 필요한 프로세스가 인증/인가이기 때문에, 이 부분을 정확히 공부하고 넘어가야한다

인증 & 인가

인증(Authentication)

  • 사용자가 누구인지 확인하는 것
    ex) 회원가입, 로그인
  1. 로그인 요청
    사용자가 아이디와 비밀번호를 입력하고 로그인을 요청한다.

  2. 사용자 확인
    DB에 저장된 사용자의 비밀번호와 사용자가 입력한 비밀번호를 비교하고, 인증 여부를 결정한다.

  3. 토큰 발급
    비밀번호가 일치하면, 사용자의 정보가 담긴 일종의 출입증인 "토큰"을 사용자에게 전송한다.

  4. 상태 유지
    사용자는 토큰을 받았으니, 다음 요청부터 ID, PW가 아닌 토큰을 제시한다.

인가(Authorization)

  • 사용자의 요청에 대해 권한을 확인하는 것
    ex) 관리자에게만 관리자 페이지 접근 권한 허락

  • 인가를 위해서는 인증이 선행되어야한다.

  1. 데이터 요청
    예를들어 ,사용자는 관리자에게만 허용된 페이지로 넘어가려한다.
    서버에 페이지 요청과 함께 발급받은 토큰도 보낸다.

  2. 토큰 검증
    서버는 토큰을 보고 어떤 사용자가 요청했는지를 식별한 후, DB에서 사용자가 이 페이지에 접근할 권한이 있는지 확인한다.

  3. 인가 처리
    사용자의 권한이 확인되면, 요청을 처리한다.

토큰이 무엇이고 왜 쓰는지 알려면 Cookie와 Session을 알아야한다!

그 탄생배경인 HTTP부터 가볍게 살펴보자.

HTTP 통신

  • HTTP : 인터넷 상에서 데이터를 주고 받을 때 '서버 <-> 클라이언트 모델'을 사용하자라는 약속

  • url앞에 있는 'http'나 'https' : "나 이런 프로토콜로 통신할거야"라고 말해주는 자리

HTTP의 아래와같은 특징때문에 인증과 인가를 위해 토큰, 세션, 쿠키를 이용하게된다.

특징

Connectionless

사용자가 서버에 요청을 했을 때, 서버는 요청에 맞는 응답을 보내준 후, 바로 연결을 끊어버린다.
-> 한 번 로그인해도 다른 페이지로가면 로그아웃된다.

Stateless

서버는 사용자(클라이언트)의 상태 정보를 저장하지 않기 때문에, 똑같은 사용자와 다시 통신을 해도 이전에 통신한 적 있는지, 어떤 데이터를 주고 받았는지 전혀 알지 못한다.
-> 상품을 선택했는데, 장바구니에 선택한 상품이 없다.

쿠키 & 세션 & 토큰

HTTP 통신시 어쩔 수 없는 번거로운 상황을 해결하기 위한게 Cookie, Session이다.

Cookie와 Session의 공통점

  • 클라이언트의 정보를 연속적으로 유지하기 위해 존재

Cookie와 Session의 차이점

  • 상태 정보의 저장 위치
    -> Cookie = 클라이언트(사용자 PC)에 저장
    -> Session = 서버에 저장

각각 다른 장단점이 있으므로, 용도에 맞게 조합해 사용해야한다.

쿠키(Cookie)

  • 사용자가 어떤 웹 사이트 방문할 때, 사용자의 PC에 저장하는 조그만 정보 파일

사례 ) 자주 방문한 사이트에 ID, PW가 자동입력 되어있는 상황
팝업창 "오늘은 다시 보지 않기"를 클릭하는 것 ...

첫 방문 시점에 저장해두고, 이후 동일 사이트에 방문할 경우 서버는 쿠키 정보를 바탕으로 ID, PW가 입력된 사이트, 팝업창이 생략된 사이트를 보여주는 것이다.

장점

  • 사용자 PC에 저장되므로 속도가 빠르고 서버의 자원을 낭비하지 않아 효율적이다.

단점

  • 사용자 PC에 저장되므로 해킹의 위험이 있고, 브라우저가 종료되어도 자동으로 삭제되지 않아 보안 측면에서 세션보다 안좋다.
    -> 따라서 민감 정보를 저장하지 않는다.

세션(Session)

  • 일정 기간 사용자의 상태를 일정하게 유지시키는 기술
    (일정 기간 = 로그인 ~ 로그아웃, 로그인~브라우저 종료)

로그아웃하거나 브라우저를 닫아버리면 세션이 끊기므로 다음 접속시 다시 로그인해야한다.

  • 브라우저 하나당 하나의 세션이 생성되고, 해당 브라우저에서 들어오는 요청들은 모두 동일한 세션 ID로 식별해서 처리한다.
    -> 로그인 후 다른 화면으로 이동해도 로그인이 풀리지 않고 로그인 상태가 유지되는 것은 세션 덕분이다.

❓ 의문점 : '브라우저 하나'에서 하나의 범위는 어디까지일까?

추측하기로는, chrome에서 하나의 '창'에 여러개의 '탭'이 있다고 가정할 때 '창'이 다르면 다른 브라우저일거라고 추측했다.
테스트해보니, 브라우저 하나 단위라는건 chrome, safari 등 브라우저 종류마다 다른 것 같다.
예를 들어, chrome에서 다른 '창'이지만 구글 로그인 프로필이 동일하면 세션이 하나로 되어있는것처럼 동작한다. (a창에서 네이버 로그인을 하면, b창에도 로그인이 적용된다)

장점

세션은 서버에서 관리하기 때문에 상대적으로 안전한 상태를 유지할 수 있고, 브라우저를 닫으면 자동으로 삭제되기 때문에 쿠키보다 보안이 좋다.

단점

세션은 서버에 저장되기 때문에 많은 사람들이 사용하면 과부하가 올 수 있고, 서버와 통신하므로 속도가 느리다는 단점이 있다.

세션은 쿠키와 함께 사용되는데, 프로세스를 살펴보자.

세션 + 쿠키

  1. 사용자가 서버에 웹 페이지를 요청할 때, 쿠키 정보를 함께 보낸다.
  2. 서버는 사용자가 전달한 쿠키에 세션 id가 있는지 확인한다.
  3. 세션 id가 존재하면 상태를 유지해주고, 존재하지 않으면 세션 id를 새로 생성해 DB에 저장한다.
  4. 사용자에게 웹페이지를 돌려줄 때, 쿠키에 방금 생성한 세션id 정보를 함께 넣어준다.
  5. 이 쿠키는 요청을 보낸 사용자 PC에 저장된다.
  6. 사용자는 다른 요청을 보낼 때, 세션 id가 포함된 쿠키를 동봉하게되고, 서버는 세션 id로 사용자를 식별해 사용자의 상태에 맞게 처리한다.

좋아보이지만, 이 방식에 문제가 있다!

문제점

  • 로그인 할 때, 쿠키/세션 방식을 사용하면 해커가 쿠키를 가로채서 치명적인 보안 문제를 일으킬 수 있다.
  • 서버는 수 많은 사용자의 세션을 저장하고, 요청이 들어올 때마다 확인 작업을 하느라 서버의 부담이 커질 수 있다.

따라서 토큰이 등장한다!

토큰 기반 인증은 세션/쿠기보다 보안성이 높고, 서버에게도 효율적이다.

Token

  • 사용자의 인증 정보를 암호화한 것 (일종의 출입증 역할)
  • 클라이언트에서 인증 정보를 보관
  • 사용자가 최초 로그인 시 토큰을 발급해주고, 이후 사용자는 이 토큰으로 다른 페이지도 출입할 수 있게된다.

  1. 사용자가 로그인시, 서버는 토큰을 발급한다.
  2. 사용자는 발급된 토큰을 PC에 저장한다. (쿠키처럼 로컬에 저장)
  3. 사용자는 이후 다른 요청을 보낼 때, 토큰을 동봉해서 보낸다.
  4. 서버는 사용자의 토큰 정보를 검증한 뒤(복호화...), 사용자의 권한을 확인하고 요청을 처리한다.
  • 서버는 토큰만으로 클라이언트의 세부적인 동작을 추적할 수 없다 : 서버는 각 요청을 독립적으로 처리하고, 클라이언트의 상태나 이전 요청과의 관계를 알 수 없다.

물론 토큰도 http 통신중 해커가 가로채는 위험이 발생할 수 있다.

보안 피해를 최소화하기위해 서버는 2가지 종류의 토큰을 사용자에게 발급한다.

  1. Access Token : 출입증으로 사용
  2. Refresh Token : Access Token이 만료되었을 때 인증상태 연장해주는 역할

종류

Access Token

  • 보호된 정보들에 접근할 수 있는 권한부여에 사용

  • 즉, 클라이언트가 처음 인증을 받게 될 때 (로그인), access token, refresh token 둘다 받게 되지만 실제로 권한을 얻는데 사용하는 토큰은 access token 이다.
    권한을 부여받는 데엔 access token만 있으면 된다.

하지만 해커에 의해 토큰이 탈취된다면,로그인을 해서 여러 나쁜 행위들을 할 수 있다.
그래서 access token의 만료기간을 짧게 주고 오랫동안 사용할 수 없도록 한다.

access token이 만료될 때마다 refresh token을 통해 access token을 refresh 한다.

그래서 access token은 로그인 정보에 접근할 수 있는 카드키, refresh token은 카드키 재발급이라고 생각하면 기억하기 편할 것이다.

유저의 편의보다 정보를 지키는 것이 더 중요한 웹사이트들은 refresh token을 사용하지 않는 곳도 있다. 그러면 유저는 일정주기 마다 새로 로그인을 해야 할 것이다.

ex) 정부 사이트는 로그인 제한시간 60분으로 되어있다.

Refresh Token

  • 새로운 Access Token을 발급하기 위한 토큰

  • 기본적으로 Access Token은 외부 유출 문제로 인해 유효기간을 짧게 설정하는데, 정상적인 클라이언트는 유효기간이 끝난 Access Token에 대해 Refresh Token을 사용하여 새로운 Access Token을 발급받을 수 있다.
    따라서, Refresh Token의 유효기간은 Access Token의 유효기간보다 길게 설정한다.

그런데, 만약 Refresh Token이 유출되어서 다른 사용자가 이를 통해 새로운 Access Token을 발급받았다면?!

이 경우, Access Token의 충돌이 발생한다!
서버측에서는 두 토큰을 모두 폐기시켜야 한다. 국제 인터넷 표준화 기구(IETF)에서는 이를 방지하기 위해 Refresh Token도 Access Token과 같은 유효 기간을 가지도록 하여, 사용자가 한 번 Refresh Token으로 Access Token을 발급 받았으면, Refresh Token도 다시 발급 받도록 하는 것을 권장하고 있다.

Refresh Token은 만료시에만 노출되기 때문에, 해킹을 당할 위험이 적다.

Access Token + Refresh Token에 대한 재발급 원리

한계

어느 정도 규모가 있는 서비스에서, 사용자 인증 용도로 토큰을 사용하기에는 부족한 경우가 있다.

예를 들어, 현재 로그인된 사용자의 모든 장비들을 나열해주거나, 특정 장비에서 로그아웃을 허용하는 기능을 구현하려면 서버 단에 사용자 세션을 저장하지 않고는 어렵기 때문이다.

❓궁금점 : 넷플릭스나 인프런과 같이 동시 로그인 감지 기능이 있는 서비스는 어떤 방식으로 인증/인가를 진행할까?

  • 로그인된 장비를 계속 감지하고있어야 하기때문에 세션을 사용하는걸로 추측했는데, 알아 본 결과 세션을 사용한다고한다. (by chatGPT)

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

무상태성(Stateless) & 확장성(Scalability)

  • 사용자의 인증 정보를 서버나 세션에 유지하지 않고 클라이언트 측에서 들어오는 요청만으로 작업을 처리한다.
    즉, 서버 기반의 인증 시스템과 달리 상태를 유지하지 않으므로 Stateless한 구조.
    따라서 클라이언트와 서버의 연결고리가 없기 때문에 확장하기에 매우 적합. (사용자의 로그인 여부를 신경쓰지않고 시스템을 확장할 수 있다)
    -> 서버는 토큰에 대한 검증(암호화된 토큰 복호화)만 수행하면 되기때문에, 서버에 부담이 적은 방식이다.

만약 사용자 정보가 서버 측 세션에 저장된 경우에 서버를 확장하여 분산처리 한다면, 해당 사용자는 처음 로그인 했었던 서버에만 요청을 받도록 설정을 해주어야 한다.
하지만 토큰을 사용한다면 어떠한 서버로 요청이 와도 상관이 없다.

보안성

클라이언트가 서버로 요청을 보낼 때 더 이상 쿠키를 전달하지 않으므로, 쿠키 사용에 의한 취약점이 사라지게 된다.
하지만 토큰 환경의 취약점이 존재할 수 있으므로 이에 대비해야 한다.

확장성(Extensibility)

시스템의 확장성을 의미하는 Scalability와 달리 Extensibility는 로그인 정보가 사용되는 분야의 확정을 의미한다.
토큰 기반의 인증 시스템에서는 토큰에 선택적인 권한만 부여하여 발급할 수 있으며 OAuth의 경우 Facebook, Google 등과 같은 소셜 계정을 이용하여 다른 웹서비스에서도 로그인을 할 수 있다.


참고
https://uncertainty.oopy.io/8f8ca9b9-cc23-4dde-80aa-4c6fbe977772

0개의 댓글