Authentication (인증) / Authorization (인가)
세션 기반 인가와 토큰 기반 인가에 대해 알아보기 이전에
먼저, 인증과 인가가 무엇인지부터 알아야 할 필요가 있다.
인증과 인가를 같거나 비슷한 개념이라고 생각하는 사람들이 많을 텐데, 엄밀하게는 서로 다른 개념이다.
인증과 인가는 시스템의 자원을 적절하고 유효한 사용자에게 전달하고 공개하는 방법이다.
Authentication (인증)
인증은 쉽게 말하자면, 로그인을 뜻한다.
클라이언트가 자기 자신이라고 주장하고 있는 사용자가 맞는지를 검증하는 과정이다.
예를 들어 로그인 화면에서 내가 아이디와 패스워드를 입력해 제출하면,
서버에서는 내가 입력한 아이디와 패스워드에 대해 유효한 사용자가 맞는지 확인한다.
이와 같은 로그인 과정을 인증이라고 한다.
Authorization (인가)
인가는 인증 작업 이후에 수행되는 작업으로,
인증된 사용자에 대한 자원에 대한 접근 확인 절차를 의미한다.
일반 유저인 USER1과 USER2가 있다고 하자.
일반 유저인 USER1 은 글 작성, 조회, 수정, 삭제 등 일반적인 작업에 대한 권한이 부여되어 있다.
하지만 USER1 은 USER2가 작성한 글을 수정하거나 제거할 수는 없다.
타인의 리소스에 대해서는 인가되어 있지 않기 때문이다.
또한 USER1과 USER2는 모두 관리자 페이지에 접속할 수 없다.
일반 유저는 관리자 페이지에 대해 인가되어 있지 않기 때문이다.
이처럼 인증된 사용자 개개인의 권한에 따라 자원에 대한 접근을 제한하는 작업을 인가라고 한다.
HTTP의 비상태성(Stateless)
HTTP는 비상태성이라는 특성을 갖는다.
서버는 클라이언트의 상태를 저장하지 않으며, 따라서 이전 요청과 다음 요청의 맥락이 이어지지 않는다.
HTTP는 바로 직전에 발생한 통신을 기억하지 못한다.
따라서 HTTP 단독으로는 요청한 클라이언트가 이전에 이미 인증과정을 거쳤는지 알 방법이 없다.
그렇다고, 매번 사용자에게 로그인을 하라고 요청할 수는 없다.
매 작업마다 로그인을 사용자에게 요청하는 것은 UX를 전혀 고려하지 않은 방식이다.
그렇다면, 사용자의 아이디와 패스워드를 브라우저에 그대로 저장해 놓고,
매 요청마다 함께 그 정보를 보내는 방법은 어떨까?
이런 방식은 전송 데이터가 커져 비효율적일뿐더러,
클라이언트에 민감한 데이터가 그대로 저장되어 보안에도 굉장히 취약하다.
서버 입장에서도 매 작업마다 데이터베이스를 조회하고, 인증과정을 거치는 것이 비효율일 것이다.
이런 HTTP 환경에서 서버는 어떤 방식으로 사용자를 인가할까?
웹 어플리케이션에서는 이 문제를 세션 또는 토큰을 사용하여 문제를 해결한다.
즉, 세션과 토큰은 인증보다는 인가와 관련된 기술이라고 할 수 있다.
세션 기반 인증
기존의 인증 시스템은 서버 기반의 인증 방식으로,
서버 측에서 사용자들의 정보를 기억하고 있어야 한다.
사용자들의 정보를 기억하기 위해서는 세션을 유지해야 하는데,
메모리나 디스크 또는 데이터베이스 등을 통해 관리한다.
서버 기반의 인증 시스템은 클라이언트로부터 요청을 받으면,
클라이언트의 상태를 계속해서 유지하고 이 정보를 서비스에 이용하는데,
이러한 서버를 Sateful 서버라고 한다. 예를 들어 사용자가 로그인을 하면,
세션에 사용자 정보를 저장해 두고 서비스를 제공할 때 사용하곤 한다.
이러한 서버 기반의 시스템은 다음과 같은 흐름을 갖는다.
세션기반 인가는 사용자의 인증 정보가 서버의 세션 저장소에 저장되는 방식이다.
사용자가 로그인을 하면, 해당 인증 정보를 서버의 세션 저장소에 저장하고,
사용자에게는 저장된 세션 정보의 식별자인 Session ID를 발급한다.
발급된 Session ID는 브라우저에 쿠키 형태로 저장되지만, 실제 인증 정보는 서버에 저장되어 있다.
브라우저는 인증 절차를 마친 이후의 요청마다
HTTP Cookie 헤더에 Session ID를 함께 서버로 전송한다. 서버는 요청을 전달받고,
Session ID에 해당하는 세션 정보가 세션 저장소에 존재한다면 해당 사용자를 인증된 사용자로 판단한다.
- 세션
사용자가 인증을 할 때, 서버는 이러한 정보를 저장해야 하고 이를 세션(Session)이라고 부른다.
대부분의 경우에는 메모리에 저장하는데, 로그인 중인 사용자가 늘어날 경우에는
서버의 RAM에 부하가 걸리게 된다. 이를 피하기 위해 데이터베이스에 저장을 하기도 하는데,
이러한 방식 역시 데이터베이스에 무리를 줄 수 있다. - 확장성
사용자가 늘어나게 되면 더 많은 트래픽을 처리하기 위해
여러 프로세스를 돌리거나 컴퓨터를 추가하는 등 서버를 확장해야 한다.
세션을 사용한다면 세션을 분산시키는 시스템을 설계해야 하지만 매우 어렵다. - CORS(Cross-Origin Resource Sharing)
웹 어플리케이션에서 세션을 관리할 때 자주 사용되는 쿠키는
단일 도메인 및 서브 도메인에서만 작동하도록 설계되어 있다.
따라서 쿠키를 여러 도메인에서 관리하는 것은 번거롭다.
이러한 문제들 때문에 토큰 기반의 인증 시스템을 사용하게 되었다.
토큰 기반 인증
세션 기반 인증이 인증 정보를 서버에 저장하는 방식이라면,
토큰 기반 인증은 인증 정보를 클라이언트가 직접 들고 있는 방식이다.
이때 인증 정보가 토큰의 형태로 브라우저의 로컬 스토리지(혹은 쿠키)에 저장된다.
토큰의 종류에 따라 다르겠지만, 대표적인 토큰인 JWT의 경우 디지털 서명이 존재해
토큰의 내용이 위변조 되었는지 서버 측에서 확인할 수 있다.
토큰 기반 인증에서는 사용자가 가지고 있는 토큰을 HTTP의 Authorization 헤더에 실어 보낸다.
이 헤더를 수신한 서버는 토큰이 위변조 되었거나, 만료 시각이 지나지 않은지 확인한 이후
토큰에 담겨있는 사용자 인증 정보를 확인해 사용자를 인가한다.
이러한 토큰 기반의 시스템은 다음과 같은 흐름을 갖는다.
위와 같은 토큰 기반의 인증 시스템은 인증받은 사용자들에게 토큰을 발급하고,
서버에 요청을 할 때 헤더에 토큰을 함께 보내도록 하여 유효성 검사를 한다.
이러한 시스템에서는 더 이상 사용자의 인증 정보를 서버나 세션에 유지하지 않고
클라이언트 측에서 들어오는 요청만으로 작업을 처리한다.
즉, 서버 기반의 인증 시스템과 달리 상태를 유지하지 않으므로 Stateless 한 구조를 갖는다.
이러한 토큰 기반의 인증 방식을 통해 수많은 문제점들을 해결할 수 있는데,
대표적으로 사용자가 로그인이 되어있는지 안되어있는지 신경 쓰지 않고 손쉽게 시스템을 확장할 수 있다.
이러한 토큰 기반의 인증 시스템의 과정을 정리하면 다음과 같다.
- 사용자가 아이디와 비밀번호로 로그인을 한다.
- 서버 측에서 해당 정보를 검증한다.
- 정보가 정확하다면 서버 측에서 사용자에게 토큰을 발급한다.
- 클라이언트 측에서 전달받은 토큰을 저장해 두고,
서버에 요청을 할 때마다 해당 토큰을 서버에 함께 전달한다.
이때 Http 요청 헤더에 토큰을 포함시킨다. - 서버는 토큰을 검증하고, 요청에 응답한다.
토큰 기반 인증의 이점
- 무상태성(Stateless) & 확장성(Scalability)
토큰은 클라이언트 측에 저장되기 때문에 서버는 완전히 Stateless 하며,
클라이언트와 서버의 연결고리가 없기 때문에 확장하기에 매우 적합하다.
만약 사용자 정보가 서버 측 세션에 저장된 경우에 서버를 확장하여 분산처리 한다면,
해당 사용자는 처음 로그인 했었던 서버에만 요청을 받도록 설정을 해주어야 한다.
하지만 토큰을 사용한다면 어떠한 서버로 요청이 와도 상관이 없다. - 보안성
클라이언트가 서버로 요청을 보낼 때 더 이상 쿠키를 전달하지 않으므로,
쿠키 사용에 의한 취약점이 사라지게 된다.
하지만 토큰 환경의 취약점이 존재할 수 있으므로 이에 대비해야 한다. - 확장성(Extensibility)
시스템의 확장성을 의미하는 Scalability와 달리
Extensibility는 로그인 정보가 사용되는 분야의 확장을 의미한다.
토큰 기반의 인증 시스템에서는 토큰에 선택적인 권한만 부여하여 발급할 수 있으며,
OAuth의 경우 Facebook, Google 등과 같은 소셜 계정을 이용하여
다른 웹서비스에서도 로그인을 할 수 있다. - 여러 플랫폼 및 도메인
서버 기반 인증 시스템의 문제점 중 하나인 CORS를 해결할 수 있는데,
애플리케이션과 서비스의 규모가 커지면
여러 디바이스를 호환시키고 더 많은 종류의 서비스를 제공하게 된다.
토큰을 사용한다면 어떤 디바이스, 어떤 도메인에서도
토큰의 유효성 검사를 진행한 후에 요청을 처리할 수 있다.
이런 구조를 통해 assests 파일(Image, html, css, js 등)은 모두 CDN에서 제공하고,
서버 측에서는 API만 다루도록 설계할 수 있다.
최근에는 Json 포맷을 이용하는 JWT(Json Web Token)을 주로 사용한다.
JWT 토큰에 대한 내용은 아래의 포스팅을 참고하면 된다.
참고자료
https://hudi.blog/session-based-auth-vs-token-based-auth/
https://mangkyu.tistory.com/55
'IT > Server' 카테고리의 다른 글
[Server] Reverse Proxy / Forward Proxy (2) | 2024.09.25 |
---|---|
[Server] 상호 배제 알고리즘 - Dekker's Algorithm (3) | 2024.09.25 |
[Server] Spin lock & Mutex & Semaphore (0) | 2024.09.24 |
[Server] OAuth의 개념 및 프로세스 (3) | 2024.09.08 |
[Server] What is JWT ( Json Web Token ) (0) | 2024.08.26 |