JWT 인증 방식에 대해 공부해보다가, 다른 인증 방식과의 차이를 정리해두어야겠다는 생각이 들었다.
클라이언트의 인증을 위한 대표적인 방식 Cookie, Session, Token을 다뤄보자
📌 Cookie 인증
쿠키(Cookie)는 사용자의 브라우저에 저장되어 통신할 때 포함되어 전달한다.
사용자의 브라우저에 저장되는 데이터들이므로, 고유 정보 식별이 가능하다.
1. 클라이언트가 서버에 요청(Request)를 보낸다.
2. 서버는 클라이언트의 요청에 대한 응답(Response)을 작성하고, 응답 헤더의 Set-Cookie에 사용자의 브라우저에 저장될 데이터를 담아 보낸다.
3. 이후 해당 클라이언트는 요청을 보낼 때마다, 저장된 쿠키를 요청 헤더의 Cookie에 담아 보내게 된다.
4. 따라서, 서버는 쿠키에 담긴 정보를 확인하여 사용자를 식별할 수 있다.
✅ 단점
- 쿠키 값이 담겨 요청되므로 누군가가 쉽게 열람하여 데이터가 유출될 수 있기에 보안성이 낮다.
- 또한, 임의로 수정과 삭제가 가능하다.
- 따라서, 지워지고 삭제되어도 상관없는 수준의 데이터들만 보관하는 것을 권장한다.
- 용량 제한이 있어 많은 정보를 담을 수 없다.
- 브라우저마다 쿠키의 형태가 다르기 때문에 브라우저간 공유가 불가능하다.
📌 Session 인증
세션(Session)은 쿠키보다 좀 더 보안성을 높이고자, 사용자의 브라우저가 아닌, 서버에 저장되고 관리한다.
그렇기에 브라우저가 종료될 때까지 유지가 되며, 서버에 저장되어 있기에 탈취를 방지할 수 있다.
클라이언트가 서버에 접속하면, 서버는 클라이언트에게 세션 ID를 부여한다.
클라이언트는 이를 쿠키로 저장하고 페이지를 접속할 때, 이 세션 ID를 전달하는 방식이다.
1. 클라이언트가 서버에 접속하면, 서버는 Session ID를 부여하여 이를 기준으로 정보를 저장한다.
2. 서버에서 브라우저의 쿠키로 Session ID를 저장하도록 한다.
3. 쿠키로 저장된 Session ID는 클라이언트 요청 시에 같이 전달된다.
4. 따라서, 서버는 클라이언트가 보내온 쿠키에서의 Session ID와 저장된 Seesion ID를 비교하여 식별이 가능하다.
✅ 단점
- 중요 데이터를 보관할 수 있지만, 접속자가 많아지면 서버에 과부하가 걸릴 수 있다.
+) 스티키세션
만약 서버가 여러 개로 증축되는 스케일아웃을 할 때, 사용자가 서버1에는 로그인을 했으나, 서버2에는 로그인한 적이 없는 경우, 서버2에 대해서는 로그아웃 형태가 되는 문제가 발생한다.
이를 방지하고자, 기존에 어느 서버로 요청을 했었는지를 기억할 수 있도록 저장하는 것을 스티키세션이라 한다.
혹은, 각 서버마다 기록하지 않고 외부 세션 저장소(redis)를 만들어 저장한다.
📌 Token 인증
토큰은 클라이언트가 서버에 접속하면, 인증되었다는 의미로 클라이언트에게 토큰을 부여한다.
또한, 서버에서는 클라이언트의 요청에 담겨있는 토큰을 가지고 비교하여 인증 과정을 처리한다.
기존 세션 인증의 경우, 서버에서 세션ID를 모두 가지고 있어야 하며, 조회하여 비교해야하는 과정이 있는데, 이런 과정이 없기 때문에 토큰 인증을 통해서 서버의 부담을 줄일 수 있다.
1. 클라이언트가 서버에 접속하면, 서버는 토큰을 발급하여 클라이언트에게 부여한다.
2. 클라이언트는 토큰을 저장해두고, 요청 시에 해당 토큰을 담아 전달한다.
3. 서버는 전달받은 토큰을 검증하고 요청에 응답한다. 토큰에는 클라이언트의 정보가 담겨있으므로, DB를 조회하지 않고도 식별이 가능하다.
✅ 단점
- 토큰의 데이터 길이가 쿠키와 세션보다 길기 때문에, 인증 요청이 많으면, 부하가 심해질 수 있다.
- payload는 암호화가 되지 않기 때문에 중요한 정보를 담을 수는 없다.
- 탈취당하면 대처가 어려우므로, 사용 기간을 제한하여 극복한다.
📌 JWT
JWT(Json Web Token)은 인증에 필요한 정보들을 암호화한 JSON 토큰이다.
JWT 기반 인증은 이 JWT를 통해 서버가 클라리언트를 식별하는 방식이다.
JWT란, JSON 데이터를 Base64 URL -safe Encode를 통해 인코딩하여 직렬화한 것이며, 위변조 방지를 위해 개인키를 통한 전자서명도 포함되어 있다.
❓ JWT의 구조
JWT는 .을 기준으로 나누어지는 세 개의 문자열 조합이다.
- Header : JWT에서 사용할 타입, 해시 알고리즘의 종류
- Payload : 사용자의 정보 및 데이터
- Signature : Header의 해시 알고리즘이 적용된 개인키를 통한 전자서명
전자 서명에는 비대칭 알고리즘이 사용되어, 암호화에는 개인키를, 복호화에는 공개키를 사용한다.
1. 클라이언트가 서버에 접속하면, Header, Payload, Signature를 정의한다.
암호화하여 JWT를 생성하고 이를 발급한다.
2. 클라이언트는 발급된 JWT를 저장하며 요청 시에 Authorization Header에 담아 보낸다.
3. 서버에서는 요청에 담긴 토큰을 검증하여 확인한다.
4. 만약 토큰의 유효 시간이 만료되면, 클라이언트는 Refresh Token을 통해 서버로부터 새로운 토큰을 재발급받는다.
Access Token : 클라이언트가 가지고 있는 토큰, 이 토큰을 서버에서 검증한다.
Refresh Token : 새 Access Token 발급을 위한 토큰으로, Access Token보다 유효 시간이 길다. DB에 함께 저장되어 기록된다.
✅ 장점
- Header, Payload를 통해 Signature을 생성하므로 위변조를 방지할 수 있다.
- 별도의 저장소가 필요없으므로 서버의 부담이 줄어든다.
- 서버의 무상태(StateLess)로 서버 확장성이 우수해진다.
✅ 단점
- 토큰 자체에 정보가 담겨있다.
- 토큰의 길이가 늘어나 네트워크에 부하를 줄 수 있다.
- Payload에 중요한 데이터가 담겨선 안된다.
- 토큰의 탈취 위험성.