Session, JWT, OAuth
서버에서 인증을 할 때 사용되는 Session, JWT, OAuth의 특징 및 동작 방식에 대해 알아봅니다.
서버 기반의 인증 시스템
기존의 인증 시스템은 서버 기반의 인증 방식으로, 서버 측에서 사용자들의 정보를 기억하고 있어야 합니다. 사용자들의 정보를 기억하기 위해서는 세션을 유지해야 하는데, 보통 데이터베이스 등을 통해 관리합니다.
서버 기반의 인증 시스템은 클라이언트로부터 요청을 받으면 클라이언트의 상태를 계속해서 유지하고 이 정보를 서비스에 이용하는데, 이러한 서버를 Stateful 서버라고 합니다.
예를 들어 사용자가 로그인을 하면 세션에 사용자 정보를 저장해두고 서비스를 제공할 때 사용하곤 합니다.
이러한 서버 기반의 인증 시스템은 다음과 같은 흐름을 갖습니다.
- 사용자가 로그인을 한다.
- 서버에서는 회원이 있는지 검사하고, 세션 저장소에 회원 정보를 등록한 뒤 세션ID를 발급한다.
- 클라이언트는 세션ID를 쿠키에 저장하고, 인증이 필요한 요청마다 쿠키를 헤더에 실어 요청한다.
- 서버에서는 세션ID를 통해 인증을 하여 응답한다.
이러한 인증 방식은 요청 중 노출되더라도 세션ID 자체가 유의미한 값을 가지고 있지 않기 때문에 비교적 안전합니다. 하지만 탈취된 세션ID로 HTTP요청을 보낼 경우 서버는 정상적으로 요청하기 때문에 문제가 될 수 있습니다. 또한 서버에 세션의 양이 많아지면 부하가 일어날 수 있습니다.
토큰 기반의 인증 시스템
토큰 기반의 인증 시스템은 인증된 사용자에게 토큰을 발급하고, 서버에 요청을 할 때 헤더에 토큰을 함께 보내도록 하여 인증을 합니다. 이를 통해 서버 기반의 인증 시스템을 보완하고, 손쉽게 시스템을 확장할 수 있으며, 이를 Stateless 서버라고 합니다.
이러한 토큰 기반의 인증 시스템은 다음과 같은 흐름을 갖습니다.
- 사용자가 로그인을 한다.
- 서버에서는 회원이 있는지 검사하고, 그에 맞는 Access Token(Header + Payload + Verify Signature)을 발급한다.
- 클라이언트는 Access Token을 저장해두고, 인증이 필요한 요청마다 Access Token을 헤더에 실어 요청한다.
- 서버에서는 Access Token을 통해 인증을 하여 응답한다.
이러한 인증 방식은 클라이언트 입장에서는 세션ID와 차이가 없어보이지만 서버에서는 세션 저장소에 유저의 정보를 넣는 것과 달리 토큰에 유저를 정보를 넣고 따로 저장하지 않으므로 세션 저장소를 설계하지 않아도 되며 서버의 부하를 막을 수 있다는 장점이 있습니다.
하지만 정보가 많아질수록 토큰의 길이가 늘어나 네트워크에 부하를 줄 수 있다는 단점이 있습니다.
또한 서버 기반의 인증 시스템과 달리 토큰을 탈취당할 경우 토큰 만료시간이 끝날 때까지 서버에서 특별한 처리를 할 수 없습니다. 따라서 Access Token의 만료시간을 짧게하고 Refresh Token을 통해 새로운 Access Token을 발급하는 식으로 구현해야 합니다.
OAuth2 기반의 인증 시스템
OAuth2 기반의 인증 시스템은 계정 인증에 타 서비스의 계정을 사용하는 인증 방식입니다. 타 서비스를 통해 유저 ‘인증’ 과정을 거치지만 사용자의 정보는 서버에서 관리하므로 세션 또는 토큰 기반의 인증 시스템으로 사용자 인증을 합니다.
제가 사용한 구글 OAuth2 기반의 인증 시스템은 다음과 같은 흐름을 갖고 있습니다.
- 서버는 OAuth2 시스템을 이용할 구글에 OAuth2를 사용할 사이트와 리디렉션 URL을 등록하고 클라이언트 ID 및 비밀번호를 발급받는다.
- 사용자는 서버가 등록한 웹 사이트를 통해 구글 로그인을 한다.
- 로그인이 완료되면 구글에서 서버가 등록해둔 리디렉션 URL을 통해 서버에게 code 값을 전송해준다.
- 서버는 code 값, 클라이언트 ID 및 비밀번호, 새로운 리디렉션 URL을 구글에 전송하면 구글은 새로운 리디렉션 URL을 통해 서버에게 토큰을 발급한다.
- 서버는 토큰을 통해 구글에서 사용자의 유저 정보를 받아와 데이터베이스에 저장하고 사용자에게 그에 맞는 Access Token을 발급한다.
- 클라이언트는 Access Token을 저장해두고, 인증이 필요한 요청마다 Access Token을 헤더에 실어 요청한다.
- 서버에서는 Access Token을 통해 인증을 하여 응답한다.
이러한 인증 방식은 구현이 매우 복잡하지만 사용자가 새로 회원가입을 하지 않아도 되며 OAuth2를 제공하는 서비스의 특정 API를 사용할 수 있다는 장점이 있습니다.
하지만 타 서비스는 인증 과정만을 거칠 뿐 실질적인 유저 관리는 서버가 해야하므로 결국은 세션/토큰 기반의 인증 시스템을 추가로 사용해야 합니다.
Leave a comment