인증과 인가

세션기반 인가와 토큰기반 인가에 대해 알아보기 이전에 먼저, 인증과 인가가 무엇인지 부터 알아야할 필요가 있다. 인증과 인가를 같거나 비슷한 개념이라고 생각하는 사람들이 많을텐데, 엄밀하게는 서로 다른 개념이다. 인증과 인가는 요약하자면 시스템의 자원을 적절하고 유효한 사용자에게 전달하고 공개하는 방법이다.

인증 (Authentication)

인증은 쉽게 말하자면, 로그인 이다. 클라이언트가 자기자신이라고 주장하고 있는 사용자가 맞는지를 검증하는 과정이다. 예를 들어 로그인 화면에서 내가 유저 아이디를 USER1 로 입력하고 패스워드를 입력해 제출하면, 서버에서는 내가 진짜로 USER1 이라는 유저가 맞는지 확인한다.

인가 (Authorization)

인가는 인증 작업 이후에 행해지는 작업으로, 인증된 사용자에 대한 자원에 대한 접근 확인 절차를 의미한다.

여기에 일반 유저인 USER1과 USER2가 있다. 일반 유저인 USER1 은 글 작성, 조회, 수정, 삭제 등 일반적인 작업에 대한 권한이 부여되어 있다. 하지만 USER1 은 USER2가 작성한 글을 수정하거나 제거할 수는 없다. 타인의 리소스에 대해서는 인가되어 있지 않기 때문이다. 또한 USER1과 USER2 는 모두 관리자 페이지에 접속할 수 없다. 일반 유저는 관리자 페이지에 대해 인가되어 있지 않기 때문이다.

HTTP의 비상태성(Stateless)

HTTP는 비상태성이라는 특성을 갖는다. 서버는 클라이언트의 상태를 저장하지 않으며, 따라서 이전 요청과 다음 요청의 맥락이 이어지지 않는다. HTTP는 바로 직전에 발생한 통신을 기억하지 못한다. 따라서 HTTP 단독으로는 요청한 클라이언트가 이전에 이미 인증과정을 거쳤는지 알 방법이 없다.

그렇다고, 글을 조회하거나 작성할 때 마다 사용자에게 로그인을 하라고 요청할 수는 없는 노릇이다. 매 작업마다 로그인을 사용자에게 요청하는 것은 UX를 전혀 고려하지 않은 방식이다.

그렇다면, 사용자의 아이디와 패스워드를 브라우저에 그대로 저장해놓고, 매 요청마다 함께 그 정보를 보내는 방법은 어떨까? 이런 방식은 전송 데이터가 커져 비효율적일 뿐더러 클라이언트에 민감한 데이터가 그대로 저장되어 보안에도 굉장히 취약하다. 서버 입장에서도 매 작업마다 데이터베이스를 조회하고, 인증과정을 거치는 것이 비효율일 것 이다.

이런 HTTP 환경에서 서버는 어떤 방식으로 사용자를 인가할까? 웹 어플리케이션에서는 이 문제를 세션 또는 토큰을 사용하여 문제를 해결한다. 즉, 세션과 토큰은 인증 보다는 인가와 관련된 기술이라고 할 수 있다.

쿠키 (Cookie)

이런 HTTP의 비상태성을 보완하기 위해 등장한 것이 쿠키이다. 쿠키는 HTTP 요청과 응답에 함께 실려 전송된다. 쿠키는 클라이언트 즉, 브라우저에 저장된다. 웹 서버가 클라이언트로 보내는 응답의 헤더 중 Set-Cookie 라는 헤더에 키와 값을 함께 실어 보내면 그 응답을 받은 브라우저는 해당 쿠키를 저장하고, 그 다음 요청부터 자동으로 쿠키를 헤더에 넣어 송신한다.

Set-Cookie 헤더

MDN에 따르면 Set-Cookie 헤더는 아래와 같이 전송될 수 있다고 한다.

`Set-Cookie: <cookie-name>=<cookie-value> Set-Cookie: <cookie-name>=<cookie-value>; Expires=<date> Set-Cookie: <cookie-name>=<cookie-value>; Max-Age=<non-zero-digit> Set-Cookie: <cookie-name>=<cookie-value>; Domain=<domain-value> Set-Cookie: <cookie-name>=<cookie-value>; Path=<path-value> Set-Cookie: <cookie-name>=<cookie-value>; Secure Set-Cookie: <cookie-name>=<cookie-value>; HttpOnly

Set-Cookie: <cookie-name>=<cookie-value>; SameSite=Strict Set-Cookie: <cookie-name>=<cookie-value>; SameSite=Lax`

이때 ; 로 구분되는 옵션을 Directive라고 하며, 여러개의 Directive를 설정하려면 아래와 같이 헤더를 설정하면 된다.

Set-Cookie: <cookie-name>=<cookie-value>; Domain=<domain-value>; Secure; HttpOnly