세션 기반 인증과 토큰 기반 인증
인증 (Authentication)
사용자가 자신이 누구인지 주장하는 것에 대해서 참인지 거짓인지 확인하는 것
- ex) 로그인
인가 (Authorization)
어떤 사용자가 특정 리소스에 접근하려고 할 때 권한이 있는지 없는지 검사해서 허가해주는 절차
HTTP의 특성(비연결성, 무상태)
HTTP는 stateless한 특징이 있다. 그래서 각 통신의 상태가 저장되지 않는다. 바로 직전의 통신도 기억하지 못하는 것이다. 그렇다면 매번 페이지를 새로 요청할 때마다 새로 로그인을 해야 하는 것일까? 어떻게 하면 이미 인증과정을 거친 사용자인지 확인할 수 있을까?
이 문제를 해결하기 위해 세션(session) 과 토큰(token)이 등장했다.
🍪 쿠키
세션과 토큰을 알아보기 전에 세션(또는 쿠키를 사용하는 토큰)에서 사용하는 쿠키에 대해 알아보자.
쿠키는 웹 브라우저에 저장되어있는 키-값
형식의 데이터다. 크롬의 경우 개발자 도구에서 현재 저장된 쿠키를 확인할 수 있다.
F12 > Application > Cookie
쿠키는 웹 서버가 응답을 보낼 때 Set-Cookie
헤더를 통해 생성된다. Cookie 헤더를 받은 웹 브라우저는 저장장치에 쿠키 데이터를 생성해 저장한다.
이후에 웹 브라우저가 요청을 보낼 때 웹 서버의 도메인에 해당하는 모든 쿠키값이 Cookie 헤더를 통해 함께 전달된다. 이를 통해 서버는 요청을 보낸 클라이언트의 고유한 상태를 구분할 수 있게 된다.
HTTP Response의 Set-Cookie
헤더를 주는 방법 외에도 웹 브라우저에서 JavaScript로 쿠키를 제어할 수도 있다. → document.cookie
세션 기반 인증
쿠키를 이용해 인증하는 방식을 생각해보자.
요청이 들어올 때마다 쿠키를 통해 클라이언트를 구분해서 그 상태를 확인할 수 있다. 예를 들어, Cookie: name=padosum
을 가진 Request와 Cookie: name=yj
를 가진 Request가 있다면 각각 그에 따른 Response를 줄 수 있다.
로그인의 경우를 생각해볼까? 사용자 아이디와 비밀번호를 받고, 올바른 경우 Set-Cookie: name=padosum
과 같이 쿠키를 생성해주고, 이후에는 name
이라는 쿠키를 확인해서 클라이언트 구분을 할 수 있다.
☠️ 하지만 쿠키는 쉽게 조작이 가능하기 때문에 인증을 이런 방식으로 구현해서는 위험하다!
세션이란 개념이 도입되었다. 사용자의 인증 정보가 서버의 세션 저장소에 저장되는 방식이다.
사용자 로그인 구현 시 세션 기반 인증 방식을 살펴보자.
- 사용자 아이디, 비밀번호로 로그인 요청을 한다.
- 서버에서 해당 계정 정보를 검증하고 정확하다면 해당 인증 정보를 서버의 세션 저장소에 저장
- 사용자에게 저장된 세션 정보의 식별자인 session id를 발급
- 발급된 session id는 브라우저의 쿠키 형태로 저장 → 실제 인증 정보는 서버에 저장
- 브라우저는 인증 절차를 마친 이후의 모든 요청마다 HTTP Cookie 헤더에 session id를 함께 서버로 전송한다.
- 서버는 요청을 전달받고 session id에 해당하는 세션 정보가 세션 저장소에 존재한다면 해당 사용자를 인증된 사용자로 판단
세션을 이용하면 민감한 데이터를 클라이언트에게 노출하지 않고 클라이언트의 상태를 제어할 수 있다.
토큰 기반 인증
세션이 인증 정보를 서버에 저장하는 방식이라면, 토큰 기반 인증은 인증 정보를 클라이언트가 직접 들고 있는 방식이다.
인증 정보는 토큰의 형태로 브라우저의 localStorage(혹은 쿠키)에 저장된다.
- 토큰의 종류에 따라 다르지만, 대표적인 토큰인 JWT(JSON Web Token)의 경우 디지털 서명이 존재해서 토큰의 내용이 위변조 되었는지 서버 측에서 확인 가능
사용자 로그인 구현 시 토큰 기반 인증을 살펴보자. 시스템마다 크고 작은 차이가 있지만 대략 다음과 같다고 한다.
- 사용자 아이디, 비밀번호로 로그인 요청을 한다.
- 서버 측에서 해당 계정 정보를 검증한다.
- 계정 정보가 정확하다면 서버 측 유저에게 인증이 되었다는 토큰을 발급해준다.
- 클라이언트는 전달받은 토큰을 저장해둔다.
- 이후 서버 요청마다 사용자가 가지고 있는 토큰을 HTTP의 Authorization 헤더에 실어 보낸다.
- 이 헤더를 수신한 서버는 토큰이 위변조되었거나 만료 시각이 지나지 않았는지 확인한 이후 토큰에 담겨있는 사용자 인증 정보를 확인해 사용자를 인가한다.
세션 기반 인증과 토큰 기반 인증 비교
사이즈
- 세션의 경우 Cookie 헤더에 session id만 실어 보내면 되므로 트래픽을 적게 사용한다.
- JWT(JSON Web Token)의 경우 사용자 인증 정보와 토큰의 발급 시각, 만료 시각, 토큰 id 등 세션에 비해 크다. 그래서 더 많은 트래픽을 사용한다.
안전성과 보안
- 세션의 경우 모든 인증 정보가 서버에서 관리되기 때문에 보안 측면에서 조금 더 유리하다.
- 예를 들어 보안팀이 어떤 계정이 손상된 것으로 의심되는 경우 세션 ID를 비활성화해 사용자가 로그아웃되도록 할 수 있다.
확장성
- 일반적으로 현대 웹 애플리케이션은 한 대가 아닌 여러 대의 서버가 요청을 처리한다. 그래서 별도 작업을 처리해주지 않으면 세션 기반 인증은 세션 불일치 문제를 겪게 된다.
- 또한 서버에서 세션 데이터를 저장, 관리하기 때문에 세션 관련 데이터양이 많아질 경우 서버에 부담이 증가할 것이다.
- 하지만 토큰 기반 인증은 클라이언트에 토큰이 저장되기 때문에 세션 불일치 문제가 발생하지 않는다.
- 클라이언트에 데이터를 저장하기 때문에 서버의 메모리에 부담이 되지 않는다.
결론
각각의 장/단점이 존재하기 때문에 개발자가 애플리케이션 요구사항에 더 적합한 방법으로 결정해야 한다!