인증(Authentication)이란 해당 유저가 실제 유저인지 확인, 인증하는 행위이다. 로그인을 하는 행위 자체가 인증 절차라고 할 수 있다. 인가(Authorization)란 해당 유저가 특정 리소스에 접근이 가능한지 확인하는 것이다. 예를 들면 회원/비회원 여부에 따라 다른 권한을 부여받는 것, 관리자 권한을 가질 경우에만 관리자 페이지에 접근할 수 있는 것 등이 있다.
웹 서버는 일반적으로 서버-클라이언트 구조로 되어있고 Http라는 프로토콜을 이용하여 통신하는데 이 통신은 비연결성, 무상태로 이루어진다. 즉, 서버와 클라이언트가 실제로 연결되어 있지 않고(비연결성) 서버가 클라이언트의 상태를 저장하지 않는 상태(무상태)로 통신을 하는 것이다. 그러나 우리가 인터넷을 사용할 때는 이전의 정보들이 잘 있는 것처럼 연속성있게 사용해왔다. 그렇다면 어떻게 비연결성, 무상태 프로토콜에서 '유저가 인증되었다'라는 정보를 유지시켰을까?
쿠키-세션 방식은 서버가 '특정 유저가 로그인되었다'는 상태를 저장하는 방식이다. 쿠키는 클라이언트(웹 브라우저)에 저장되어 인증과 관련된 아주 약간의 정보만 서버가 가지고 있게 되고 이 최소한의 정보로 로그인을 유지시킨다.
쿠키는 클라이언트에 저장될 목적으로 생성한 작은 정보를 담은 파일이다. 웹 브라우저를 보면 도메인별로 저장된 쿠키를 확인할 수 있다.
구성 요소
Name : 쿠키를 구별하는데 사용되는 키
Value : 쿠키 값
Domain : 쿠키가 저장되는 도메인
Path : 쿠키가 사용되는 경로
Expires : 쿠키의 만료 기한 (만료되면 삭제)
세션은 서버에서 일정 시간동안 클라이언트 상태를 유지하기 위해 사용된다. 서버에서 클라이언트 별로 유일무이한 '세션 ID'를 부여한 후 필요한 정보를 서버에 저장한다. 서버에서 생성한 세션 ID는 클라이언트의 쿠키값(세션 쿠키)으로 저장되어 클라이언트 식별에 사용된다.
세션 동작 흐름
1. 클라이언트가 서버에 요청
2. 서버가 세션 ID를 생성하고, 쿠키에 담아 응답 헤더에 전달
3. 클라이언트가 쿠키에 세션 ID 저장(세션 쿠키)
4. 클라이언트가 서버에 쿠키값(세션 ID)를 포함하여 요청
5. 서버가 세션 ID를 확인하고 1번 요청과 같은 클라이언트임을 인지
JWT 기반 인증 방식은 토큰을 이용한 방식이다. JWT(JSON Web Token)는 인증에 필요한 정보들을 암호화시킨 토큰을 의미한다. JWT 토큰은 일반적으로 쿠키 저장소에 저장되며 HTTP 헤더에 실어 서버가 클라이언트를 식별한다.
서버가 2대 이상일 때 세션 방식을 사용할 경우 세션마다 다른 클라이언트 로그인 정보를 가지고 있을 수 있다. 이를 해결하기 위해 로직이 추가되게 되는데 JWT를 사용하면 모든 서버에서 로그인을 처리하기 쉬워진다. 또한 로그인 정보를 서버에 저장하지 않고 클라이언트에 암호화하여 저장한 뒤 JWT를 통해 인증/인가 과정을 거치므로 서버의 부하가 낮아진다. 다만 구현이 복잡하고 네트워크 비용이 증가할 수 있으며 Secret key가 유출될 경우 보안에 취약해진다는 단점이 있다.
JWT 동작 흐름
1. 서버에서 로그인 정보를 JWT로 암호화 (Secret key 사용)
2. 서버에서 쿠키를 생성해 JWT에 담아 클라이언트에 응답
3. 브라우저 쿠키 저장소에 자동으로 JWT 저장
4. 클라이언트는 api 요청 시마다 쿠키에 포함된 JWT를 찾아서 사용
5. 서버는 클라이언트가 전달한 JWT 검증