개발 기록 남기기✍️

[HTTP 인증] 쿠키, 세션 그리고 토큰(feat. JWT) 본문

Front-End/기초 지식

[HTTP 인증] 쿠키, 세션 그리고 토큰(feat. JWT)

너해동물원 2023. 7. 17. 01:02

인증이 필요한 이유

쿠키와 세션을 이해하기 위해서는 HTTP 프로토콜에 대한 이해가 필요하다. 

 

HTTP 프로토콜은 비연결성과 무상태성을 가진 프로토콜이다.

  • Connectionless(비연결성) : 클라이언트가 서버에 요청을 하고 서버가 클라이언트에게 응답을 보내면 접속을 끊는다.
  • Stateless(무상태성) : 통신이 끝나면 상태 정보를 유지하지 않는다.

 

Connectionless하고 Stateless한 HTTP 프로토콜을 사용하면서 서버가 클라이언트를 식별할 수 있는 방법이 필요했고 쿠키와 세션을 사용하게 되었다.

 

HTTP는 Stateless하기 때문에 로그인 상태 정보를 유지하지 않아서 쿠키와 세션을 사용하지 않으면 게시판이나 메일을 확인할 때 페이지를 이동할 때마다 로그인 해야 한다.

 

인증과 인가

인증과 인가는 요약하자면 시스템의 자원을 적절하고 유효한 사용자에게 전달하고 공개하는 방법이다.

 

인증 (Authentication)

인증은 쉽게 말하자면, 로그인 이다. 클라이언트가 자기자신이라고 주장하고 있는 사용자가 맞는지를 검증하는 과정이다. 예를 들어 로그인 화면에서 유저가 아이디와 비밀번호를 작성해 제출하면, 서버에서는 해당 아이디의 유저가 맞는지 확인한다.

 

인가 (Authorization)

인가는 인증 작업 이후에 행해지는 작업으로, 인증된 사용자에 대한 자원에 대한 접근 확인 절차를 의미한다. 

여기에 일반 유저인 USER1과 USER2가 있다. 일반 유저인 USER1 은 글 작성, 조회, 수정, 삭제 등 일반적인 작업에 대한 권한이 부여되어 있다. 하지만 USER1 은 USER2가 작성한 글을 수정하거나 제거할 수는 없다. 타인의 리소스에 대해서는 인가되어 있지 않기 때문이다. 또한 USER1과 USER2 는 모두 관리자 페이지에 접속할 수 없다. 일반 유저는 관리자 페이지에 대해 인가되어 있지 않기 때문이다.


쿠키(Cookie)

쿠키 인증 방식

웹 브라우저에서 쿠키는 서버가 사용자의 웹 브라우저에 전송하는 작은 데이터 조각으로, key=value 형식의 문자열 데이터 묶음이다.

브라우저는 이 문자열 데이터 조각들을 저장해놓았다가 동일한 서버에 재요청시 쿠키 데이터를 전송할 수 있다.

 

쿠키에는 이름, 값, 만료 날짜, 경로 정보가 들어있으며 일정 시간동안 데이터를 저장할 수 있어서 로그인 상태를 유지하거나 사용자 정보를 일정 시간동안 유지해야 하는 경우에 주로 사용된다.

 

쿠키는 크게 세션 관리, 개인화, 트래킹에 사용된다.

 

  • 세션 관리 : 서버에 저장해야 할 로그인, 장바구니, 게임 스코어 등의 정보 관리
  • 개인화 : 사용자 선호, 테마 등 사용자의 개인 세팅을 저장, 관리
  • 트래킹 : 분석 및 광고 개제를 위해 웹사이트 내 사용자 행동 기록, 관리

 

쿠키 인증 방식의 단점

  • 서버에 요청을 보낼 시, 쿠키의 값을 그대로 보내기 때문에 조작 및 유출의 위험성이 높다.
  • 용량 제한이 있어 많은 데이터 정보를 담을 수 없다.
  • 쿠키의 사이즈가 커질수록 네트워크 성능 부하가 심해진다.

세션 (Session)

세션 인증 방식

세션은 서버에서 가지고 있는 객체로, 특정 사용자의 로그인 정보를 유지하기 위해 사용할 수 있다.

예를 들어 클라이언트가 웹 사이트에 로그인한 뒤에, 서버에서는 세션 ID에 따른 회원 ID 정보를 기록한다. (클라이언트에서는 세션 ID 값만 가짐)

클라이언트는 해당 세션을 계속 유지한다. 메일함에 접속할 때 세션 ID를 서버에 전송한다.

한마디로 세션은 자신이 누구인지를 서버에 알려주는 역할을 수행한다고 할 수 있다.

 

쿠키 인증방식은 브라우저의 로그인 상태를 유지할 수는 있지만, 헤더에 해당 정보를 담아서 보내기 때문에 보안의 위험이 있었다.

반면 세션 방식에서는 클라이언트 브라우저가 가지고 있는 세션 ID 자체에는 개인정보를 포함하고 있지 않고, 브라우저가 종료되면 만료시간에 상관없이 삭제되는 방식이라서 쿠키의 단점을 보완할 수 있다.

 

세션 인증 방식의 단점

  • 악의적인 공격자가 세션 ID를 탈취하여 사용자인 척 위장할 수 있다.
  • 웹 서버에 세션 정보를 기록하고 있어야 하므로, 접속자가 많을 때 서버에 메모리 부하가 존재할 수 있다.

토큰(Token)

토큰 인증 방식

토큰 인증에서는 클라이언트가 서버에 접속을 하면 서버에서 해당 클라이언트에게 인증되었다는 의미로 토큰을 부여한다. (사용자 인증 정보 서명)

이 토큰은 유일하며, 토큰을 발급받은 클라이언트는 또 다시 서버에 요청을 보낼 때 요청 헤더에 토큰을 심어서 보낸다.

그러면 서버에서는 클라이언트로부터 받은 토큰을 서버에서 제공한 토큰과의 일치 여부를 체크하여 인증과정을 처리한다.

 

기존의 세션 인증은 서버가 파일이나 데이터베이스에 세션정보를 가지고 있어야하고, 이를 조회하는 과정이 필요하기 때문에 많은 오버헤드가 발생했다. 하지만, 토큰은 이와 달리 서버에 사용자 정보를 저장하지 않고, 전달받은 토큰의 서명과 데이터를 검증하는 것만으로 인증이 가능하기 때문에 서버의 부담을 덜 수 있다.

 

사용자의 인증이 완료되면 서버는 비밀키 또는 공개/개인 키를 이용해 서명한 토큰을 클라이언트에게 전달한다.

이후 데이터 요청 시 클라이언트는 토큰을 포함한다(주로 헤더). 서버는 토큰의 서명 값을 이용하여 토큰이 유효한지 검증하고, 유효한 토큰인 경우 요청에 응답한다. 토큰 발급 시 토큰 내 권한 정보를 추가하여 권한에 맞는 데이터 응답도 가능하다.

 

세션 기반 인증과 토큰 기반 인증의 차이점

  • 정보 포함 : 세션 값 자체에는 정보가 포함되지 않지만, 토큰값에는 정보가 포함다. 토큰에는 정보가 포함되어 있기 때문에 일반적으로 길이가 더 길다.
  • 상태 정보 미저장: 세션 방식은 상태 정보를 서버 내에 저장하는 반면, 토큰은 기본적으로 서버에 클라이언트 상태를 저장하지 않는 무상태성 방식이다. 서버에 정보를 저장할 필요가 없기 때문에 서버를 확장하는데 제약이 적고, 저장 없이 유효한 토큰인지 검증만 필요하기 때문에 다른 플랫폼, 서비스 간에 사용하기도 편리하다.

 

토큰 인증 방식의 단점

  • 쿠키/세션과 다르게 토큰 자체의 데이터 길이가 길어서 인증 요청이 많아질수록 네트워크 부하가 심해질 수 있다.
  • Payload 자체는 조회가 가능하기 때문에 유저의 중요한 정보를 담을 수 없다.
  • 토큰은 발급하면 만료될 때까지 계속 사용이 가능하기 때문에 토큰이 탈취당하면 대처하기 어렵다.

 

JWT (JSON Web Token)

JWT 인증 방식

JWT는 인증에 필요한 정보를 암호화한 JSON 형식의 토큰을 의미한다. 쿠키/세션과 함께 가장 대표적인 인증 수단이다.
JWT 기반 인증은 JWT 토큰을 HTTP 헤더에 실어 서버가 클라이언트를 식별할 수 있도록 한다.

데이터들이 JSON 형태로 작성되며, 데이터를 비밀키 또는 공개/개인 키로 서명해 사용한다. 이를 통해 JWT는 인가와 정보 교환을 위해 사용될 수 있다. 사용자에게 발급된 토큰으로 인가된 서버 리소스에 접근할 수 있고, 공개/개인 키는 사용해 서명함으로써 송신자를 확인할 수 있으며, 데이터의 무결성도 확인할 수 있다.

 

 




JWT 구조

JWT 구조

  • Header : 토큰 타입을 명시하는 "typ"와 HMAC, SHA256 등의 서명 알고리즘을 적는 "alg"로 이루어져 있다.
  • Payload : 키와 값 형식으로 이루어진 정보(claim)의 구성 -> 이 값을 서버로 전달한다.
    • Registered claims : 서비스에 필요한 정보가 아닌 토큰에 관한 정보를 담기 위해 이미 등록된 클레임 (선택적 사용 가능)
    • Public claims : 사용자가 정의할 수 있는 클레임
    • Private claims : 토큰 사용자 간(서버-클라이언트) 정보 공유를 위해 만들어 사용하는 클레임
  • Signature : (헤더 + 페이로드 + 키) 정보를 해싱 알고리즘으로 서명한 값으로, 서버는 이 서명과 전달된 헤더, 페이로드를 같은 알고리즘으로 해시한 값이 동일한 것을 확인함으로써 유효한 토큰인지를 검사한다.

 

JWT 장점

  • 세션/쿠키는 별도의 저장소 관리가 필요하지만 JWT는 발급한 후 검증만 하면 되기 때문에 추가 저장소가 필요 없다. (Stateless한 서버) 이는 서버를 확장하거나 유지보수하는데 유리하다.
  • 확장성이 뛰어나다. 토큰 기반으로 하는 다른 인증 시스템, 웹 서버에도 접근이 가능하다.

 

JWT 단점

  • 이미 발급된 JWT에 대해서는 돌이킬 수 없다. 세션/쿠키의 경우 쿠키가 악의적으로 이용된다면 해당 세션을 지워버리면 되는데, JWT는 한번 발급되면 유효기간이 완료될 때까지 계속 사용이 가능하다. 따라서 악의적인 사용자는 유효기간이 지나기 전까지 정보를 탈취할 수 있다.
  • Payload는 따로 암호화되지 않기 때문에 디코딩하면 누구나 정보를 확인할 수 있다. 따라서 유저의 중요한 정보들은 Payload에 넣을 수 없다.
  • 세션에 비하여 토큰 자체의 데이터 길이가 길다. 따라서 인증이 필요한 요청이 많아질수록 서버의 자원 낭비가 발생하게 된다.

 

1번 단점을 위한 해결법

  • 기존의 Access token의 유효기간을 짧게 하고 Refresh token이라는 새로운 토큰을 발급한다. 그렇게 되면 Access token을 탈취당해도 상대적으로 피해를 줄일 수 있다.

 

 

Refresh token

JWT의 단점을 해결하기 위해 Access token, Refresh token으로 이중으로 나누어 인증을 한다.

Access token과 Refresh token은 둘다 똑같은 JWT이다. 다만 토큰이 어디에 저장되고 관리되느냐에 따른 차이일 뿐이다.

  • Access Token : 클라이언트가 갖고 있는 실제로 유저의 정보가 담긴 토큰으로, 클라이언트에서 요청이 오면 서버에서 해당 토큰에 있는 정보를 활용하여 사용자 정보에 맞게 응답을 진행
  • Refresh Token: 새로운 Access Token을 발급해주기 위해 사용하는 토큰. 해당 토큰은 보통 데이터베이스에 유저 정보와 같이 기록.

처음에 로그인했을 때 Access token과 동시에 발급되는 Refresh token은 긴 유효기간을 가지면서 Access token이 만료되었을 때 새로 토큰을 발급해주는 열쇠가 된다.

 

즉, Access token의 유효기간을 짧게 만들고, 유효기간이 만료될 때마다 Refresh token을 통해 새로운 Access token을 만들어서 보안을 조금이라도 더 안전하게 한 것이다.

(하지만 Access token이 유효한 동안에는 이를 바로 차단할 방법은 없다. JWT의 한계)