쿠키, 세션, 토큰

인증의 필요성

HTTP는 Connectionless, Stateless한 프로토콜이다.

  • Connectionless → 클라이언트가 request를 보내고, 서버가 response를 보내면 연결이 끊어진다

  • Stateless → 서버는 클라이언트의 상태 정보를 저장하지 않는다

  • 결국 동일한 클라이언트가 서버에 접속할 때 서버는 해당 클라이언트의 이전 상태를 기억하지 못한다 → 매번 인증이 요구됨

HTTP의 Stateless함으로 인해 인증절차가 중복되는 문제가 있다.

서버 기반 인증(쿠키, 세션) & 토큰 기반 인증(JWT)으로 해결한다

인증 방식의 종류

  1. HTTP 기본 인증 : 사용자의 이름과 비밀번호를 Base64 인코딩하여 HTTP 헤더에 담아 전송하여 인증하는 방식

    • 사용자 정보가 헤더에 담겨있어 보안에 취약함

  2. 서버 기반 인증 : 서버의 세션 & 클라이언트의 쿠키를 기반으로 하는 인증 방식

  3. 토큰 기반 인증 : 클라이언트가 헤더에 토큰을 담아 request를 전송하고, 서버가 해당 토큰으로 인증처리하는 방식

서버 기반 인증

쿠키

브라우저에 저장되는 key-value형태의 문자열

  • 웹서버에 접속하면 해당 서버를 통해 브라우저에 쿠키가 저장된다. (클라이언트가 직접 쿠키 생성하는게 아니라 서버가 쿠키를 생성하여 클라이언트에게 보내주는 것)

  • HTTP1.1 규격에 포함되지 않지만 인증 문제를 극복하기 위해 사용되었다

쿠키의 동작 방식

  1. 웹 브라우저가 서버에게 request 전송

  2. 서버는 상태 유지를 하려는 데이터를 쿠키로 생성하고, 이를 response 헤더의 Set-Cookie 필드에 담아 전송

  3. 웹 브라우저는 전달받은 쿠키를 저장하고, 다음 request 전송시 헤더의 Cookie 필드에 쿠키를 담아 전송

쿠키의 문제점

  1. 쿠키 정보를 HTTP 헤더에 담아 전송하기 때문에 상당한 트래픽 발생

  2. 쿠키 정보가 헤더에 담겨 있어 노출될 수 있음 → 보안에 취약함

  3. 쿠키의 개수, 크기가 한정됨

  4. 여러 브라우저간 쿠키를 공유할 수 없음

쿠키의 대안 : Web Storage API

  • 웹 브라우저가 직접 데이터를 저장할 수 있는 방식이다. (해당 데이터는 서버로 전송되지 않는다)

  • 하나의 origin에 속하는 모든 웹 페이지에서 같은 web storage의 데이터를 공유할 수 있다.

세션

쿠키의 보안 문제를 해결하기 위해 동일한 클라이언트의 request를 하나의 세션으로 여겨 서버가 이를 저장한다.

  • 동일한 클라이언트의 세션을 식별할 수 있는 sessionID가 부여된다.

  • 서버는 sessionID를 redis와 같은 인메모리 DB, DB, 클라이언트에 저장한다.

쿠키 & 세션

활용 방식

  • 클라이언트 세션 정보를 서버에 저장하고, 세션을 식별하기 위한 sessionId를 클라이언트에 저장한다.

쿠키와 세션 비교

CookieSession

저장위치

클라이언트의 웹 브라우저가 지정하는 메모리 또는 하드디스크에 저장

서버의 메모리에 저장

저장형식

Text

Object

만료시점

쿠키 저장시 expires 속성으로 설정(설정 없으면 브라우저 종료 시)

클라이언트가 로그아웃하거나, 설정 시간동안 반응이 없으면 무효화 되기 때문에 정확한 시점 알 수 없음

리소스

클라이언트에 저장되고 클라이언트의 메모리를 사용하기 때문에 서버 자원 사용하지 않음

세션은 서버에 저장되고, 서버 메모리로 로딩 되기 때문에 세션이 생길 때마다 리소스를 차지함

용량제한

클라이언트도 모르게 접속되는 사이트에 의하여 설정될 수 있기 때문에 쿠키로 인해 문제가 발생하는 걸 막고자 한 도메인당 20개, 하나의 쿠키 당 4KB로 제한해 둠

클라이언트가 접속하면 서버에 의해 생성되므로 개수나 용량 제한 없음

서버 기반 인증

  1. 클라이언트가 로그인 정보를 서버에 전달

  2. 서버는 클라이언트의 로그인 정보를 검증 후 sessionId 생성.

  3. 서버는 sessionId를 담은 쿠키를 response 헤더의 Set-Cookie 필드에 담아 클라이언트에게 전달

  4. 클라이언트는 받은 쿠키를 저장하고, 매 request 헤더의 Cookie 필드에 쿠키를 담아 요청.

  5. 서버는 클라이언트의 request 헤더 속 쿠키에 담긴 sessionId 검증 후 response 전달. (세션 저장소는 세션, 인메모리 DB, RDB가 될 수 있음)

서버 기반 인증의 문제점

  1. 서버 부하 문제 : 사용자 수에 따라 저장할 세션이 많아져 디스크 부하를 일으키거나 메모리를 차지함

  2. 확장성 문제 : 웹 서버 증설시 새로운 서버에 기존 세션 정보를 옮겨야 하는 문제로 Scaling out이 어려워짐

  3. **Cross-Origin에서 쿠키 사용 불가 : 쿠키는 Same-Origin에서만 공유할 수 있기 때문에 Cross-Origin에서 기존 쿠키에 접근할 수 없다.**

토큰 기반 인증

서버가 인증된 클라이언트에게 토큰을 발급하고, 클라이언트는 이후 request의 헤더에 토큰을 담아 요청하는 방식의 인증이다.

  • 클라이언트의 상태 정보를 서버에 저장하지 않기 때문에 Stateless하다.

토큰 기반 인증 과정

  1. 클라이언트가 로그인 정보를 서버에 전달

  2. 서버는 클라이언트의 로그인 정보 검증 후, 클라이언트 식별 정보를 기반으로 Token 발급하여 전달

  3. 클라이언트는 전달받은 Token을 쿠키나 Web Storage에 저장. 이후 request의 헤더에 Token을 담아 요청

  4. 서버는 클라이언트의 request의 헤더 속 Token의 유효성 검사 후 response 전송

토큰 기반 인증의 장점

  1. Stateless → 서버 확장의 유연함 : 서버에 클라이언트 상태 정보를 저장하지 않으므로 Scaling out에 제약이 줄어듦

  2. Cross-Origin에서도 문제 없는 인증 방식

  3. 디바이스 종류에 의존적이지 않는 인증 방식

JWT(JSON Web Token)

JSON 포맷을 사용하여 사용자 정보를 Claim 기반으로 저장한 Web Token

  • Claim : key=value 형식의 데이터

  • JWT는 Base64URL 인코딩되어 URL의 파라미터로 사용될 수 있다.

  • JWT는 헤더 + 페이로드 + 서명으로 구성된다.

    • 헤더 : JWT 토큰 타입, 해시 알고리즘 정보가 담김

    • 페이로드 : 클라이언트에 대한 정보가 담김

    • 서명 : “헤더(문자열) + 페이로드(문자열)”를 서버의 secret key로 해싱하여 생성된 값

JWT의 장단점

장점

  1. 데이터 위변조 방지 : 헤더 + 페이로드를 서버의 secret key로 서명을 생성하기 때문에 헤더 또는 페이로드의 위변조를 감지할 수 있음

  2. 별도의 저장소가 필요 없음

  3. JWT 속에 토큰 정보(헤더), 전달할 정보(페이로드), 위변조 방지 및 검증을 증명하는 정보(서명)가 모두 있음

단점

  1. 네트워크 부하 : JWT 토큰의 길이가 길기 때문

  2. 유저의 민감한 정보를 담지 못함 : 페이로드는 암호화되지 않기 때문

  3. 탈취의 위험성 : 토큰을 탈취 당하면 유효기간이 만료되기 전까지 대체하기 힘듦

JWT의 보안 전략

  1. 만료기한을 짧게 설정 : 토큰의 만료시간을 짧게 설정하여 탈취의 위험성을 줄임

    • 단점 : 로그인을 자주 해야 함

  2. Refresh Token : 서버가 만료시간이 짧은 AccessToken과 함께 만료시간이 긴 Refresh Token을 발급함

    • AccessToken : 사용자 인증 용도, 만료시간이 짧아 탈취의 위험성을 줄임

    • RefreshToken : AccessToken 재발급 용도, 만료시간이 길고 서버가 강제로 만료시킬 수 있음

    • 단점 : RefreshToken을 서버에 저장하기 때문에 Stateless하지 않음

Last updated