쿠키, 세션, 토큰, JWT.. 참 많이 듣긴 했는데 도대체 머가 다른지, 각자가 왜 필요한지 모르겠써요..
그래서 한방에 다 정리해 보았습니다 @~@
최대한 납득이 가는 흐름으로 정리해 보았는데 이해가 안 되거나 틀린 내용이 있을 수 있기 때문에 댓글로 알려주세요!
일단 우리가 개발을 하면서 네트워킹을 하고! 데이터를 주고받고! 하기 위해서는 인증&인가라는 것이 필요한데 인증&인가가 무엇인지부터 천천히 알아봅시다
인증, 인가
- 인증
- 인증이란, 접근 가능한, 유효한 유저임을 증명하는 것.
- 비행기 타는 것을 예로 들면, 탑승객이 비행기를 타기 위해서는 여권과 비행기 표를 확인해야 비행기를 탈 수 있는 것처럼 이렇게 유효한 탑승객인지 증명하는 과정을 인증이라고 합니다!
- 인가
- 인가란, 인증되어 우리 서버에 접근 가능한 사용자라고 하더라도 권한에 따라 접근할 수 있는 리소스가 다르면 그 권한에 따라 인가(허가)하는 것.
- 비행기를 예로 들면, 탑승객의 비행기 좌석 등급에 따라 앉을 수 있는 자리가 다르기 때문에 좌석 등급별 , 서비스에 대한 접근 권한이 가각 다른 것이죠.
인증이 누구인지 확인하는 것이라면, 인가는 무엇을 할 수 있는 사용자인지 알아보는 것!
인증/인가 까지는 무엇인지 이해하셨나요?
이러한 인증/인가를 구현하는 방법이 바로!
위에서 말한 쿠키, 세션(session) 방식 그리고 토큰(Token), JWT 방식이 있는 것입니다.
쿠키, 세션(session), 토큰(Token), JWT 이런 게 바로 인증/인가를 위한 티켓으로 쓰이는 것이죠 :)
그럼 왜 인증/인가를 위해 위에서 말한 티켓이 필요한가? 의문이 들 텐데
그 이유는 클라이언트(브라우저, 앱 환경)와 서버는 데이터를 주고받기 위해 HTTP 프로토콜 방식을 범용적으로 사용하고 있기 때문입니다!
HTTP도 많이 들었지만 뭔지 헷갈린다 그죠?
http의 동작 방식부터 특징, 그리고 http의 어떤 특성 때문에 인증/인가를 위해 쿠키, 세션(session), 토큰(Token), JWT 이런 티켓이 필요한지 까지 천천히 정리해 보겠습니다.
HTTP
HTTP란?
HTTP는 Hypertext Transfer Protocol의 약자로,
서버와 클라이언트가 인터넷상에서 데이터를 주고받기 위한 프로토콜(protocol)을 뜻합니다.
이 프로토콜은 TCP/ IP를 이용하는 응용 프로토콜이라고 합니다.
TCP/ IP를 자세히 공부하진 않았지만 간단하게 어떤 건지만 짚고 넘어가면,
- 인터넷은 보통 TCP/IP라는 약속으로 연결되어 있는데, TCP는 Transmission Control Protocol (전송 제어 프로토콜)을 뜻함.
- TCP는 응용 프로그램이 데이터를 교환할 수 있는 네트워크 대화를 설정하고 유지하는 방법을 정의하는 표준
- 월드 와이드 웹, 이메일, 원격 관리, 파일 전송과 같은 주요 인터넷 애플리케이션은 전송 계층의 일부인 TCP에 의존
- TCP는 인터넷 프로토콜 (IP)과 작동하여 컴퓨터가 서로 데이터 패킷을 보내는 방법을 정의
- TCP protocol은 3-way handshaking을 통해 연결을 수립하고 4-way handshaking을 통해 해제
TCP/ IP 에 대한 내용을 자세히 이야기하면 끝도 없으니 찍먹만! 언젠가는 이것도 자세히 공부해야 하는 날이 오겠찌..
HTTP 동작 방법
HTTP는 서버와 클라이언트가 인터넷상에서 데이터를 주고받기 위한 프로토콜(protocol) 이라고 했는데, 데이터를 주고받기 위해 어떤 식으로 동작한단 말임..?
HTTP는 크게 connect, request, response 과정을 통해 데이터를 주고받는데! 각각 간단히 설명하면 아래와 같다!
- connect : 클라이언트가 원하는 서버에 접속
- request : 클라이언트가 이 서버에 요청.클라이언트가 서버에게 연락하는 것을 요청이라고 하며 요청을 보낼때는 요청에 대한 정보를 담아 서버로 보낸다.
- response : 서버가 요청에 대한 응답결과를 클라이언트에게 보내는 것을 응답이라고 한다.응답이 끝나면 서버와 클라이언트 연결 끊음(Stateless)
설명을 보니 익숙한데 우리가 개발할 때 네트워킹 하는 과정이지 않은가..!
맞다. 우리가 네트워킹할 때 요청과 응답으로 이루어졌던 건 바로 HTTP의 동작 방법 때문이었던 것!
HTTP가 어떤 식으로 동작하는지 알아본김에 요청할 때의 데이터 포맷과 응답할 때의 데이터 포맷을 알아보면!
HTTP 요청 데이터 포맷
- Header
- 요청메서드 : GET, PUT, POST, PUSH, OPTIONS 등의 요청방식
- 요청 URL : 요청하는 자원의 위치를 명시한다.
- HTTP 프로토콜 버전 : 웹 브라우저가 사용하는 http 프로토콜의 버전이다.
- Body
- 요청을 할 때 함께 보낼 데이터를 담는 부분
- 요청메서드가 POST나 PUT을 사용하게 됐을 때 함께 보냄 ( GET 방식은 요청할 때 가지고 가야 되는 자원도 URL에다 붙여사 갖고 감. 그래서 GET방식은 요청바디가 없음.)
HTTP 응답 데이터 포맷
- Header
- 첫 번째 줄에는 반드시 응답 HTTP 프로토콜의 버전/응답코드/응답메세지
- 나머지 헤더 부분에는 날짜, 웹서버 이름과 버전, 콘텐츠 타입, 캐시 제어 방식, 콘텐츠 길이 등의 값이 나옴
- Body
- 빈 줄 다음에 나오는 것이 실제 응답 리소스 데이터가 나오는 부분
- 응답에는 대부분의 경우 본문이 있다. 보통 데이터를 요청하고 응답 메시지에는 요청한 데이터를 담아서 보내주기 때문이다. 응답 메시지에 HTML이 담겨 있는데 이 HTML을 받아 브라우저가 화면에 렌더링한다.
HTTP 특징
HTTP의 특징에는 크게 두 가지가 있는데 이 특징이 쿠키, 세션, 토큰, JWT의 필요성과 연결되니 꼭 짚고 넘어갑시당
- 비연결지향성 (connectionless)
- HTTP는 먼저 클라이언트가 요청을 서버에 보내면, 서버는 클라이언트에게 요청에 맞는 응답을 보내고 TCP/IP 연결을 끊는다
- (( 1요청 1응답 후 연결 끊음 ))
- 무상태성 (stateless)
- 연결을 끊는 순간 클라이언트와 서버의 통신이 끝나고 상태 정보를 유지하지 않는 특성
- ((연결 끝나면 다음 요청이 올 때까지 어떤 사용자인지, 어떤 정보를 가지고 있는지 기억하지 않음. 즉 로그인을 했더라도 1요청 1응답이 끝나면 다음화면으로 이동하거나 다음 액션 실행 시 유저가 로그인했는지 인증된 인물인지 알지 못한다.))
이러한 특징의 장점이라면
- 불특정 다수를 대상으로 하는 서비스에 적합하고
- 계속 서버와 클라이언트의 연결상태를 유지하는 게 아니기 때문에 클라이언트와 서버 간의 최대 연결수보다 훨씬 많은 요청과 응답을 처리 가능하다는 점이죠
But, 어플리케이션은 상태를 유지해야 하는 서비스가 존재하는데
-> 이에 대표적인 서비스가 '로그인' !
-> 하지만 클라이언트가 한 번 요청하고 응답하면 연결을 끊고 상태를 기억하지 않는 connectionless, stateless 같은 HTTP 프로토콜의 한계를 보안하기 위해 쿠키, 세션, 토큰, JWT을 사용하는 것입니다!
지금까지의 내용을 요약해 보자면
HTTP를 통해 인증/인가(대표적으로 로그인)를 해야 하는데 , HTTP의 connectionless, stateless와 같은 특성 때문에 로그인 상태를 유지할 수 없다는 한계점을 보완하기 위해 등장한 개념들이 쿠키, 세션, 토큰, JWT과 같은 것들입니다!
⭐️ 지금까지 쿠키, 세션, 토큰, JWT 이 대체 왜 필요한지 알아보았고, 이제 각각 어떻게 동작하고 어떤 특징이 있는지 알아봅시당
쿠키 Cookie
- 쿠키는 Key-Value 형식의 문자열 덩어리
- 클라이언트가 어떠한 웹사이트를 방문할 경우, 그 사이트가 사용하고 있는 서버를 통해 생성하여 -> 클라이언트의 브라우저에 설치되는 작은 기록 정보 파일이다. (웹 브라우저가 보관하는 데이터)
- 웹 브라우저는 수신한 쿠키를 미리 정해진 기간 동안 또는 웹 사이트에서의 사용자 세션 기간 동안 저장합니다. (쿠키에는 사용자 인증이 유효한 시간을 명시할 수 있다)
- 웹 브라우저는 향후 사용자가 웹 서버에 요청할 때 관련 쿠키를 헤더에 실어서 함께 전송
어떤 녀석인지 궁금하다면 개발자 도구에서 네트워킹 요청의 헤더 부분을 보면 쿠키를 볼 수 있습니다!!
쿠키는 어디에 저장?
웹 브라우저는 사용자 기기의 지정된 파일에 쿠키를 저장합니다.
예를 들어, Google Chrome 웹 브라우저는 모든 쿠키를 "Cookies"라는 파일에 저장하죠. Chrome 사용자는 개발자 도구를 열고 "애플리케이션" 탭을 클릭한 다음 왼쪽 메뉴에서 "쿠키"를 클릭하여 브라우저에 저장된 쿠키를 확인할 수 있습니다!
쿠키는 어떤 용도로 사용?
- ⭐️(인증 부분 관련해서는) 사용자 세션
- 로그인하면 웹 사이트 서버에서 세션 쿠키가 생성되고 이 쿠키가 브라우저로 전송
- 어떤 페이지에 대한 HTTP 요청이 있을 때 요청에 세션 쿠키가 포함. 웹 사이트에 이 쿠키가 있으므로 새 페이지가 로드될 때 다시 로그인할 필요가 없습니다.
- 개인화
- 쿠키가 웹 사이트에서 사용자 행동 또는 사용자 기본 설정이 "기억"되는 데 도움이 되므로 웹 사이트에서 사용자 경험이 맞춤화될 수 있습니다.
- (ex. 오늘 하루 더 이상 보지 않기 )
- 추적
- 일부 쿠키에는 사용자가 방문한 웹 사이트가 기록된다.
- 어떤 웹사이트에서 추적 쿠키를 브라우저에 전송해 놓았을 경우? -> 다음번에 브라우저가 해당 서버 콘텐츠를 로드할 때 쿠키를 생성한 서버로 전송된다.
- ex. 사용자가 이전에 추적 쿠키를 전송한 A웹사이트에 방문한 적이 있는 경우,
- → 이 쿠키에는 사용자가 어떤 사이트에서 어떤 제품을 보고 있었는지에 대한 정보가 기록될 수 있다.
- → 그다음 추적 쿠키를 브라우저에 전송한 A웹사이트를 로드할 때 쿠키의 정보를 기반으로 그 제품에 대한 광고가 표시될 수 있다.
쿠키 동작 방식
- 클라이언트가 페이지를 요청 ( 로그인 요청)
- 서버에서 쿠키를 발급하고 HTTP 헤더에 쿠키를 포함시켜 응답
- 최초 로그인 응답 이후 → 응답 헤더에는 Cookie 미포함, 브라우저가 종료되어도 쿠키 만료 기간이 있다면 클라이언트에서 보관하고 있음.
- 쿠키가 존재하면 요청을 할 경우 HTTP 헤더에 쿠키를 함께 보내서 요청
- 서버에서 쿠키를 읽어 이전 상태 정보를 변경할 필요가 있을 경우, 쿠키를 업데이트하여 변경된 쿠키를 HTTP 헤더에 포함시켜 응답.
이런 식으로 쿠키를 이용하면 웹 서버와 클라이언트는 필요한 값을 공유하고 상태를 유지할 수 있겠죠??
⇒ 이런 식으로 로그인이 유지될 수 있는 것
하지만 쿠키만으로 로그인을 구현하는 것은 한계가 있습니다... 그러니 나머지 세션이나 토큰 방식이 필요한 거겠죠??
일단, 쿠키는 네트워크를 통해 전달되기 때문에 중간에 쿠키를 탈취할 수 있다는 취약점이 있습니다. 개발자 도구를 켜서 바로 볼 수도 있기 때문에 중요한 사용자 정보라도 저장되어 있으면 큰일이겠죠.
이를 보완하고자 우리는 세션(Session)을 사용합니다.
세션 Session
- 인증 및 권한 부여 정보를 포함하여 사용자의 인증 관련 데이터를 저장하기 위한 서버 측 메커니즘
- 웹 브라우저는 웹 서버에 연결 시 매번 세션 ID를 보내서 웹 서버가 어떤 세션을 사용할지 알 수 있도록 합니다.
- 이때, 웹서버와 웹 브라우저가 세션 ID를 주고받기 위해서 사용하는 것이 쿠키입니다.
- ⭐️쿠키방식과 와 다른 점은 쿠키방식은 각 브라우저의 별도 쿠키 저장소에 저장되는 반면에세션방식은 사용자에 대한 정보가 서버에 저장이 됩니다.
세션의 동작과정
- 사용자가 서버에 로그인 request
- 서버는 request가 들어오면 세션 ID를 생성하여 세션 DB에 저장
- → response header에 포함시켜 response. ( 만들어진 sessionID는 쿠키를 통해 브라우저로 돌아오고 저장된다.)
- 사용자는 서버에서 해당 세션 ID를 받아 쿠키에 저장을 한 후 제한된 요청에 접근할 때마다 쿠키를 request header에 포함시켜 내보낸다.
- 서버에서는 쿠키를 받아 세션 저장소에서 검증한 후 요청에 해당하는 데이터를 반환한다.
세션의 특징, 장/단점
- 세션 ID를 담는 ‘쿠키’에 중요한 정보를 담지 않기 때문에 http 요청 중 노출되어도 크게 위험하진 않지만
- 쿠키 자체를 훔쳐 세션에 접근하면 중요한 정보를 빼낼 수도 있게된다.
- 단점
- 서버에 세션을 저장하기 때문에 사용자 수가 많아지면 서버의 부담이 늘어난다.
- 또한 서버 확장성(scalability)이 나빠진다. (한대가 아닌 여러 대의 서버가 요청을 처리하게 됐을 때(서버의 수평 확장 경우) 이때 별도의 작업을 해주지 않는다면, 세션 기반 인증 방식은 세션 불일치 문제가 발생함)
- client의 HTTP 요청이 탈취당하여 쿠키가 해킹당한다면 (세션 하이재킹) 서버는 사용자를 오인하여 정보를 제공한다.
- *세션 하이재킹 (Session Hijacking) 은 공격자가 두 컴퓨터 간의 유효한 세션을 장악할 때 발생합니다. 공격자는 시스템에 침입하여 데이터를 스누핑하기 위해 유효한 세션 ID를 훔칩니다. (참고 : https://developer.mozilla.org/ko/docs/Glossary/Session_Hijacking)
- (⇒ 이것을 막기 위하여 HTTPS를 사용하거나 세션에 유효기한을 걸기도 한다.)
HTTPS 라는건 뭔데?
https
: HTTPS(Hypertext Transfer Protocol Secure)는 HTTP의 확장 버전 또는 더 안전한 버전
: HTTPS에서는 브라우저와 서버가 데이터를 전송하기 전에 안전하고 암호화된 연결을 설정
http, https 차이
HTTP는 암호화되지 않은 데이터를 전송합니다. 즉, 브라우저에서 전송된 정보를 제3자가 가로채고 읽을 수 있습니다. 이는 이상적인 프로세스가 아니었기 때문에, 통신에 또 다른 보안 계층을 추가하기 위해 HTTPS로 확장되었습니다. HTTPS는 HTTP 요청 및 응답을 SSL 및 TLS 기술에 결합합니다.
- 장점
- 로그인 상태 등 모든 유저의 정보를 DB에 저장하기 때문에 가능한 것들이 장점
- 특정유저 쫓아내고 싶을 때 DB에서 그 유저 삭제 가능
- 인스타그램처럼 로그인된 모든 계정을 보여줄 수 있음
- 넷플릭스처럼 계정 공유 숫자 제한 가능
- 로그인 상태 등 모든 유저의 정보를 DB에 저장하기 때문에 가능한 것들이 장점
세션방식도 위에서 본 것처럼 장점만 있는 것이 아니기 때문에 또 다른 방법들을 알아봅시다
토큰 Token
- 인증에서의 토큰은 제한된 리소스에 대해 일정 기간 동안 접근할 수 있는 권한을 캡슐화한 것.
- 토큰은 일반적으로 의미를 알 수 없는 임의의 문자열 형태로 사용자에게 발급
- 서버에서는 클라이언트로부터 받은 토큰을 서버에서 제공한 토큰과의 일치 여부를 체크하여 인증 과정을 처리
- 유효 기간이 끝날 때까지 사용자 인증 가능 (그래서 물리적 탈취 시에 위험)
토큰의 동작과정
- 사용자가 로그인 request
- 서버는 request가 들어오면 사용자 검증을 통해 유효성을 확인하고 통과한다면 토큰을 response와 반환한다.
- 클라이언트는 토큰을 저장, 서버 요청 시 토큰을 request header에 담아 서버에 요청을 보낸다.
- 서버는 토큰을 검증 후, 요청에 응답.
- 서버는 유저로부터 전달받은 토큰을 본인들이 발급한 토큰이 맞는지, 만료되지는 않았는지 등을 따져 유효성을 검사하고, 유효한 토큰인 경우 접근을 허가합니다.
토큰의 특징, 장/단점
- 모바일 앱 사용에 편리
- 앱과 서버가 통신 및 인증할때 가장 많이 사용된다. 왜냐하면 웹에는 쿠키와 세션이 있지만 앱에서는 없기 때문이다.
- 세션 기반 인증을 사용하면 앱에서는 쿠키가 없기 때문에 쿠키 매니저를 따로 관리해야 하지만 토큰 기반 인증은 요청 api 헤더에 토큰을 넣어서 요청하기 때문에 따로 쿠키 매니저가 필요하지 않다.
- 토큰은 세션과는 달리 서버가 아닌 클라이언트에 저장되기 때문에 메모리나 스토리지 등을 통해 세션을 관리했던 서버의 부담을 덜 수 있다.
- 단점
- stateless한 토큰의 특성 때문에(인증했다는 상태 정보를 서버에 유지하지 않는다.) 토큰을 강제로 만료할 수 없다는 점이다. (큰이 공격자에게 탈취되었다고 가정하면, 공격자는 토큰이 만료될 때까지 서버에 요청을 할 수 있다는 것... ㅠㅠ)
- -> (따라서 사용 기간 제한을 설정하는 식으로 극복한다)
- Session에서 장점으로 말한 기능들을 사용할 수 없다. ( 사용자가 인증되었다는 정보를 메모리 또는 데이터베이스에 유지하지 않기 때문)
토큰 인증 방식의 단점을 보완하기 위해 토큰의 타입을 'Refresh Token'과 'Access Token'으로 나누어 사용하는 방식의 JWT 토큰을 사용하게 된다.
JWT JsonWebToken
- JWT(JSON Web Token)란 인증에 필요한 정보들을 암호화시킨 JSON 토큰
- JWT 기반 인증은 JWT 토큰(Access Token)을 HTTP 헤더에 실어 서버가 클라이언트를 식별하는 방식!
- 토큰은 base64로 인코딩한 string으로 이루어진다. (JSON 데이터를 Base64 URL-safe Encode를 통해 인코딩하여 직렬화)
- *Base64 URL-safe Encode는 일반적인 Base64 Encode 에서 URL에서 오류 없이 사용하도록 '+', '/' 를 각각 '-', '_' 로 표현한 것이다.
- 서버만 알고 있는 Secret Key로 디지털 서명화되어 있기 때문에 신뢰할 수 있다.
- ⭐️JWT에서는 토큰 자체에 유저 정보를 담아서 HTTP 헤더에 전달하기에 유저 세션을 유지할 필요가 없다. ( 위에서 살펴본 토큰 방식과 동일하게 stateless한 서버 방식 )⭐️
- 세션/ 쿠키는 (유저 상태를 저장해놓는)별도 저장소의 관리가 필요하지만, JWT는 서버 입장에서 요청을 받았을 때 발급한 후 검증만 하기 때문에 추가로 저장소가 필요 없다.
JWT 구조
JWT는 . 을 구분자로 나누어지는 세 가지 문자열의 조합입니다
JSON 형태인 각 부분은 Base64로 인코딩 되어 표현되고 각각의 부분을 이어 주기 위해 . 구분자를 사용하여 구분하는 것이죠!
- Header 에는 JWT에서 사용할 타입과 해시 알고리즘의 종류가 담겨있으며,
- alg : 서명 암호화 알고리즘(ex: HMAC SHA256, RSA)
- typ : 토큰 유형 ("JWT")
- Payload는 서버에서 첨부한 사용자 권한 정보와 데이터가 담겨있다. ( 서버와 클라이언트가 주고받는 시스템에서 실제로 사용될 정보에 대한 내용을 담고 있는 섹션)
- payload에 담는 정보의 한 ‘조각’을 클레임(Claim) 이라고 부르고, 이는(Key/Value) 형태의 한 쌍으로 이루어져 있습니다.
- 마지막으로 Signature 에는 Header, Payload를 각각 Base64 URL-safe Encode한 이후, Header 에 명시된 암호화 알고리즘으로 해싱을 하고, 이 값을 다시 BASE64로 인코딩하여 생성됩니다.
이렇게 생성된 토큰은 HTTP 통신을 할 때 요청 헤더에 Authorization이라는 key의 value로 사용됩니다. 일반적으로 value에는 Bearer가 앞에 붙여집니다.
{
"Authorization": "Bearer {생성된 토큰 값}",
}
이렇게요! 근데 Bearer는 뭔데 토큰 앞에 붙는 걸까요?
* 토큰 인증 기반에서 Bearer란?
- Bearer는 위 형식에서 인증에 대한 type중 하나에 해당한다고 보면 됩니다.
- 토큰에도 많은 종류의 type이 있기 때문에 서버가 어떤 타입의 토큰을 받았는지 구분을 해야겠죠?
- 서버는 전송받은 type에 따라 토큰을 다르게 처리하기 때문에 "JWT 토큰을 전달하는 거야~~" 라고 Bearer 라는 키워드를 통해 타입을 구분할 수 있게 해 주는 거죠!
Bearer 말고도 인증 타입이 많다고 하지만 이번 글에서는 여기까지만 이해하고 넘어갈게요!
여기서 쉽게 JWT 토큰을 인코딩(생성) 하거나 디코딩할 수 있다.
JWT 동작과정
- 처음 유저가 로그인할 때 ID, PW 를 서버에 보내는 것은 동일! (but, ID, PW를 보내도 ( 세션 방식에서의 세션 DB에 저장하는 것처럼) 서버는 DB에 뭔가를 생성하지 않는다.)
- 서버는 유저의 정보를 가져다가 ⭐️서버가 가진 “시크릿키”⭐️을 사용해서 signed information을 담은 token 만들어 string 형태로 보낸다 (이 string은 세션ID 보다 훨씬 길다. 쿠키는 공간 제약(space limit)이 있지만, JWT는 공간 제약(space limit)이 없어서 엄청 길어도 됨)
- 이후에는 서버에 request 보낼 때마다 token(signed information)을 보낸다.
- 서버가 토큰을 받으면 자신이 가진 ⭐️시크릿키로 해당 토큰의 유효성검사⭐️를한다(토큰을 조작했는지 여부)
- 토큰이 유효하다면, 유저 정보 파악 ( 토큰 해석해서 유저이름, 만료시기, 권한등을 파악한다)
- 인증 & 응답을 보낸다.
JWT 특징
- 세션 방식은 유저를 확인할 때 DB를 조회해봐야 하는데 JWT는 DB를 건드리는 대신, 토큰이 유효한지만 검증하면 된다.
- 세션/ 쿠키는 별도 저장소의 관리가 필요하지만, JWT는 서버 입장에서 요청을 받았을 때 발급한 후 검증만 하기 때문에 추가로 저장소가 필요 없다.
- => 클라이언트 인증 정보를 저장하는 세션과 다르게, 서버는 무상태(StateLess)가 되어 서버 확장성이 우수해질 수 있다.
- 모바일 어플리케이션 환경에서도 잘 동작한다. (모바일은 세션 사용 불가능)
- 주의해야 할 점
- JWT는 ⭐️ 암호화되지 않았기 때문에 ⭐️ 해독이 쉬움
- ⭐️payload 자체는 암호화된 것이 아니라 BASE64로 인코딩 된 것⭐️이기 때문에, 중간에 Payload를 탈취하여 디코딩하면 데이터를 볼 수 있으므로, payload에 중요 데이터를 넣지 않아야 한다.
- 토큰 자체에 정보를 담고 있기 때문에 비밀정보는 JWT 안에 두면 안 된다.
- 토큰 길이 : 토큰의 Payload에 정보가 많아질수록 토큰의 길이가 늘어나 네트워크에 부하를 줄 수 있다.
- stateless 특징을 가지기 때문에, 토큰은 클라이언트 측에서 관리하고 저장한다. 때문에 토큰 자체를 탈취당하면 대처하기가 어렵게 된다.
- JWT는 ⭐️ 암호화되지 않았기 때문에 ⭐️ 해독이 쉬움
주의해야 할 점에서 본 것처럼 토큰이 탈취되면 사용자 정보 노출의 위험성이 있겠죠?
세션 방식은 서버에 정보가 저장되어 있어서 그 사용자를 삭제하거나 인증 정보를 삭제해 버리면 세션ID를 알더라도 무용지물이 되는데, 토큰은 서버에 정보가 저장되어 있지 않기 때문에 탈취한 토큰이 있으면 서버에 접근할 수도 있는 거죠.
그래서 토큰에는 유효기간이 있어야 하는데
유효기간이 짧으면 사용자가 매번 다시 인증해야 하니 불편하고, 유효기간이 길면 탈취의 위험성이 계속되겠죠.
그렇기 때문에 JWT 방식에서는 Access Token과 Refresh Token으로 나누어 유효기간이 다른 토큰을 두는 것인데요.
이 두 가지는 무엇이고 왜 나눠져 있는지 봅시당
Access Token & Refresh Token
- Access Token
- Access Token은 단순하게 자원에 접근하는 Access Token이 아니라, 권한/ 인증에 대한 Token
- Refresh Token
- Refresh Token은 Access Token과 똑같은 형태의 JWT이며 Access Token의 탈취 문제를 해결하기 위해 발급하는 토큰
그럼 각각 언제 쓰는가를 네트워킹 과정에 접목해서 살펴보면
서버는 access token 과 refresh token 을 한번에 만들어낸다
-> 서버는 refresh token만 서버 저장소에 저장한다. ( access token은 저장하지 않음)
-> access token 과 refresh token 둘 다 헤더에 담아 보내서 클라이언트가 둘 다 저장
-> access token이 만료된 후에 서버에 이걸로 요청한다면
-> 서버는 만료되었다고 알려주고
-> 브라우저는 다시 access token 과 refresh token 을 둘 다 서버에 보낸다
-> 그럼 서버는 업데이트된 access token를 브라우저로 보내준다.
[서버 기반(Stateful) vs 토큰 기반(Stateless)]
서버 기반(Stateful)
- 서버(세션) 기반 인증 시스템서버의 세션을 사용해 사용자 인증을 하는 방법으로 서버측(서버 램 or 데이터베이스)에서 사용자의 인증정보를 관리하는 것을 의미한다. 그러다 보니, 클라이언트로부터 요청을 받으면 클라이언트의 상태를 계속에서 유지해 놓고 사용한다.(Stateful) 이는 사용자가 증가함에 따라 성능의 문제를 일으킬 수 있으며 확장성이 어렵다는 단점을 지닌다.
- 쿠키와 세션을 사용했을 때는 ⭐️stateful 서버⭐️로서 인증에 성공하였을 때의 결과(세션)을 메모리 또는 데이터베이스에 유지한다
- -> 서버에 부하가 발생할 수 있다.
토큰 기반(Statelessful)
- 서버기반 인증 시스템의 단점을 극복하기 위해서 "토큰 기반 인증 시스템"이 나타났다.인증받은 사용자에게 토큰을 발급하고, 로그인이 필요한 작업일 경우 헤더에 토큰을 함께 보내 인증받은 사용자인지 확인한다. 이는 서버 기반 인증 시스템과 달리 상태를 유지하지 않으므로 Stateless 한 특징을 가지고 있다.
- 토큰을 사용했을 때는 ⭐️stateless 서버⭐️로서, 인증했다는 상태 정보를 유지하지 않는다.
- -> (서버가 전달받은 토큰을 검증만 하면 되기 때문에 서버의 부담을 줄이고 서비스의 확장성을 높일 수 있다.)