All about Session and JWT

세션 인증방식과 토큰 인증방식에 대해 다루어보자.

그 전에, 쿠키와 로컬/세션 스토리지에 대해서 다루고 넘어가자.

쿠키

쿠키란 클라이언트가 어떤 웹 사이트를 방문할 경우, 사이트의 서버를 통해 클라이언트 브라우저에 설치되는 정보 기록이다.

쿠키는 Key-value 형태를 띄고 있으며, 해당 클라이언트는 앞으로 요청을 보낼 때마다 Request header에 쿠키를 담아 전송하게 될 것이다.

서버는 쿠키에 담긴 정보를 통해 현재 Request를 보낸 클라이언트가 누구인지 식별할 수 있다.

쿠키의 종류

  • Session Cookie: 메모리에만 저장되며, 만료시간이 있지만 브라우저 종료시 삭제되는 쿠키

  • Persistent Cookie: 파일로 저장되며, Max-Age 설정을 통해 장기간 유지 가능하고 브라우저 종료와 관계없이 사용 가능한 쿠키

  • Secure Cookie: HTTPS에서 사용되는 암호화된 쿠키. 비교적 안전하지만 실질적 보안이 제공되지 않아 민감한 데이터 저장 절대 금지

  • Third Party Cookie: 다른 도메인에 요청이 필요할 때 생성하는 쿠키. 주로 광고 목적으로 사용되며, 유저 개인정보 악용의 문제 발생

쿠키의 장점

  • 대부분의 브라우저가 지원

  • 데이터 유효기간 지정 가능 (ex. 1 hour, 1 day)

  • XSS (사이트 간 악성 Js 코드를 심는 행위)로부터 안전 — 서버에서 쿠키의 httpOnly 옵션을 설정하면, Js에서 쿠키에 접근 자체가 불가능

쿠키의 단점

  • 쿠키는 보안에 취약하다. 요청시 내부 정보를 그대로 보내고, 유출 및 조작의 위험이 존재한다.

  • 쿠키에는 용량 제한이 있어 많은 정보를 담을 수 없다.

  • 웹 브라우저마다 쿠키에 대한 지원 형태가 다르기 때문에 브라우저간 공유가 불가능하다.

  • 쿠키의 사이즈가 커질수록 네트워크에 부하가 심해진다.

  • CSRF(사이트 간 요청 위조) 위협 - 공격자가 사용자의 요청을 가로챈 뒤 사용자의 의지와 상관없이 보안적으로 위험한 행동을 하게끔 변조하여 부당 이익을 취하는 행위

  • 문자열만 저장 가능

웹 스토리지

  • 클라이언트에 데이터를 저장할 수 있도록 HTML5부터 나온 새로운 방식의 데이터 저장소

  • 로컬 스토리지와 세션 스토리지가 존재

  • key와 value 쌍의 형태로 데이터 저장

  • window 객체의 프로퍼티로 존재

웹 스토리지의 장점

  • 서버에 불필요하게 데이터 저장 x

  • 넉넉한 데이터 저장 용량 (모바일: 2.5MB, 데스크탑: 5~10MB)

  • 문자열 외에도 자바스크립트의 모든 원시형 데이터와 객체 저장 가능

  • 도메인 단위로 접근이 제한되는 CORS 특성 덕분에 CSRF로부터 안전

웹 스토리지의 단점

  • HTML5를 지원하는 브라우저만 사용 가능

  • XSS로부터 위험 - local storage에 접근하는 Js 코드로 쉽게 접근 가능

로컬 스토리지와 세션 스토리지 차이점

  • 로컬 스토리지는 데이터 영구 저장이 가능, 세션 스토리지는 브라우저 탭/윈도우가 닫히면 스토리지가 초기화

  • 로컬 스토리지는 window.localStorage, 세션 스토리지는 window.sessionStorage 객체 사용

사용처 정리

쿠키 : 일시적으로 필요한 가벼운 데이터 저장이 필요할 때

Ex : 다시 보지 않음 쿠키 팝업창 , 로그인 자동 완성

로컬 스토리지 : 지속적으로 필요한 데이터 저장이 필요할 때

Ex : 자동 로그인

세션 스토리지 : 일시적으로 필요한 데이터 저장이 필요할 때

Ex : 일회성 로그인, 입력 폼 저장, 비로그인 장바구니


세션 기반 인증방식

쿠키를 통해 브라우저의 로그인 상태를 유지할 수 있었지만, 보안의 위험이 있었다.

이를 해결하기 위해 세션은 비밀번호 등 클라이언트의 중요한 정보는 서버측에서 관리하는 방식이다.

클라이언트가 서버에 요청을 보낼 때, 서버는 저장해둔 세션 Id를 활용한다.

로그인 상황을 예시로 들면, 로그인 요청이 성공하는 경우 서버는 세션 Id를 서버에 저장해둔다.

그리고 클라이언트 브라우저의 쿠키에 세션 Id를 저장한다. 이제 서버는 다음 요청이 들어올 때마다, 쿠키의 세션 Id의 유효성 검사를 실시할 것이다.

장단점

  • 쿠키를 포함한 요청이 외부에 노출되더라도 세션 Id 자체는 유의미한 개인정보를 담고 있지 않다.

  • 그러나 해커가 이를 중간에 탈취하여 클라이언트인척 위장할 수 있다는 한계가 존재한다.

  • 각 사용자마다 고유한 세션 ID가 발급되기 때문에, 요청이 들어올 때마다 회원정보를 확인할 필요가 없다.

  • 서버에서 세션 저장소를 사용하므로 요청이 많아지면 서버에 부하가 심해진다.

JWT (Json Web Token)

Jwt는 인증에 필요한 정보들을 암호화시킨 토큰을 의미한다.

클라이언트의 세션 상태를 저장하지 않고 필요한 정보를 토큰에 저장한다.

서버는 이 토큰을 클라이언트에게 전달하고, 그것을 증명서처럼 사용한다.

JWT는 . 을 구분자로 세 가지로 나뉘는 구조를 지닌다.

JWT의 구조

헤더 (Header)

Header의 alg과 typ는 각각 정보를 암호화할 해싱 알고리즘 및 토큰의 타입을 지정한다.

페이로드 (Payload)

Payload는 토큰에 담을 정보를 지니고 있다.

주로 클라이언트의 고유 ID 값 및 유효 기간 등이 포함되는 영역이다.

key-value 형식으로 이루어진 한 쌍의 정보를 Claim이라고 칭한다.

Payload의 내용은 해독이 가능해서 중요한 정보는 포함해서는 안된다.

시그니처 (Signature)

Signature는 인코딩된 Header와 Payload를 더한 뒤 비밀키로 해싱하여 생성한다.

Header와 Payload는 단순히 인코딩된 값이기 때문에 제 3자가 복호화 및 조작할 수 있지만, Signature는 서버 측에서 관리하는 비밀키가 유출되지 않는 이상 복호화할 수 없다.

따라서 Signature는 토큰의 위변조 여부를 확인하는데 사용된다.

JWT 인증 과정

  1. 클라이언트 로그인 요청이 들어오면, 서버는 검증 후 클라이언트 고유 ID 등의 정보를 Payload에 담는다.

  2. 암호화할 비밀키를 사용해 Access Token(JWT)을 발급한다.

  3. 클라이언트는 전달받은 토큰을 저장해두고, 서버에 요청할 때 마다 토큰을 요청 헤더 Authorization에 포함시켜 함께 전달한다.

  4. 서버는 토큰의 Signature를 비밀키로 복호화한 다음, 위변조 여부 및 유효 기간 등을 확인한다.

  5. 유효한 토큰이라면 요청에 응답한다.

장점

이 방식을 사용하면 토큰을 제 3자가 변경하려 하여도 서버의 비밀 키를 알 수 없어서 변경이 어렵고, 변경을 하더라도 서명이 다르기때문에 요청을 받지 않게 될 것이다.

이를 통해 데이터의 위변조를 막을 수 있으며, 인증 정보에 대한 별도의 저장소가 필요 없다.

클라이언트 인증 정보를 저장하는 세션과는 다르게 서버가 Stateless가 된다.

또한 확장성이 매우 좋고, 모바일 애플리케이션에서도 잘 동작한다.

단점

위에서 설명한 대로 Payload 자체는 조회가 가능하기 때문에 중요한 정보를 담을 수는 없다.

또한, 토큰의 길이가 길어 인증 요청이 많아질 수록 네트워크 부하가 심해질 것이다. (:= 적당한게 좋다)

또한 토큰은 발급하면 만료될 때까지 계속 사용이 가능하기 때문에 토큰이 탈취당하면 대처하기가 어렵다. (:= 솔직히 탈취당하면 뭐든 대처하기 어렵다)

대안

  1. 위에서 말한 단점들을 보안하기 위해, 토큰의 만료 시간을 짧게 설정하는 방법이 있다. 토큰이 탈취되더라도 빠르게 만료되기 때문에 피해를 최소화할 수 있다는 장점이 있으나, 사용자가 자주 로그인해야 하는 불편함이 수반된다.

  2. (게시판 예시)글을 작성하는 도중 토큰이 만료가 된다면 Form Submit 요청을 보낼 때 작업이 정상적으로 처리되지 않고, 이전에 작성한 글이 날아가는 등의 불편함이 존재한다. 이를 해결하기 위해 Sliding Session이라고 서비스를 지속적으로 이용하는 클라이언트에게 자동으로 토큰 만료 기한을 늘려주는 방법이 있다. 글 작성 혹은 결제 등을 시작할 때 새로운 토큰을 발급해줄 수 있다. 이를 통해 사용자는 로그인을 자주 할 필요가 없어진다.

  3. Access Token과는 별개로 Refresh Token을 사용하는 방법이 있다. Access Token에는 짧은 유효기간을 설정하고, 그보다는 긴 유효기간을 가진 Refresh Token을 함께 발급해준다. 서버는 DB에 저장된 Refresh Token과 비교하여 유효성 검사를 실시하고, 유효한 경우 새로운 Access Token을 발급해준다.

대안 3번의 경우, 서버에서도 Refresh Token을 관리해줘야 하기 때문에 Jwt의 장점을 완전히 누릴 수 없다.

그러나 서버에서 원치 않는 경우 Refresh Token을 강제 만료시킬 수 있다는 장점도 존재한다.

Last updated