JWT(Json Web Token)
- 클라이언트와 서버 사이에 통신할 때 유저를 인증하고 식별하기 위해 사용하는 토큰이다.
- 토큰은 세션과 달리 클라이언트에 저장되기 때문에 메모리,스토리지를 통해 세션을 관리했던 서버의 부담을 줄인다.(클라이언트의 쿠키 또는 스토리지에 저장해둔다.)
- 가장 큰 특징은 토큰 자체에 사용자의 권한정보, 서비스를 사용하기 위한 정보가 포함되어 있다는 것이다.
- jwt를 사용하면 무상태(Stateless)인 환경에서 사용자 데이터를 주고받을 수 있게 된다. (세션은 서버에 세션을 저장했어야 됐으나) 단순히 HTTP 헤더에 토큰을 첨부하는 것만으로 데이터를 요청하고 응답받아올 수 있다.
- 웹 상에서 정보를 json형태로 주고받기 위해 표준 규약에 따라 생성한 암호화된 토큰으로 복잡하고 읽을 수 없는 string형태로 저장되어 있다.
순서
- 클라이언트 사용자가 아이디, 패스워드를 통해 웹서비스 인증을 한다.
- 서버에서 서명된 JWT를 발급하여 클라이언트에 응답으로 돌려준다.
- 클라이언트는 서버측에서 받은 JWT를 쿠키나 스토리지에 저장해두고, 서버에 데이터를 추가적으로 요구할 때마다 JWT를 HTTP Header에 첨부하여 요구한다.
- 서버에서는 클라이언트로부터 온 JWT를 검증하고 요청에 응답한다.
JWT 구조
- Header
- JWT에서 사용할 타입, 해시 알고리즘의 종류
- Payload
- 서버에서 첨부한 사용자 권한 정보, 데이터
- Signature
- 1,2번을 Base64 URL-safe Encode를 한 후 Header에 명시된 해시함수를 적용하고, 개인키(Private Key)로 서명한 전자 서명이 담겨있다.
- 전자서명은 1,2번이 변조되었는지 확인하는 중요한 정보로 사용된다.
- 각 요소는 . 으로 구분된다. 1,2,3번 모두 Base64 URL-safe Encode 를 통해 인코딩 하여 직렬화 한 것으로 표현된다.
- 전자 서명에는 비대칭 암호화 알고리즘을 사용한다. (즉, 암호화할 때 키(개인키)와 복호화 키(검증)(공개키)가 다름)
https://jwt.io/
장점
- 사용자 인증에 필요한 정보가 토큰 자체에 포함되어있어 별도의 인증 저장소가 필요없다.
- 기존의 토큰 방식은 인증 서버를 거쳐야만 토큰 검증이 되었었다. 그런데 jwt를 사용하면 정보를 지닌 채로 서버에 도달하여 서버가 검증까지 마친다. 그렇기 때문에 서버 유지보수, 확장이 편리하다.
- jwt를 사용하면 무상태(Stateless)인 환경에서 사용자 데이터를 주고받을 수 있게 된다. (세션은 서버에 세션을 저장했어야 됐으나) 단순히 HTTP 헤더에 토큰을 첨부하는 것만으로 데이터를 요청하고 응답받아올 수 있다.
단점
- 쿠키/세션과 다르게 토큰 자체의 데이터 길이가 길다. 그렇기 대문에 인증 요청이 많아질수록 네트워크 부하가 심해질 수 있다.
- Payload 자체는 암호화되지 않기 때문에 유저의 중요한 정보는 담을 수 없다.
- 토큰을 탈취당하면 대처하기 어렵다. (따라서 사용 기간을 짧게 하고 리프레시 토큰을 함께 사용한다.)
통상적으로 Refresh Token은 어디에 저장되는가?
- 만료 기간이 길기 때문에 탈취될 가능성이 더 적은 곳에 저장해야한다.
- Refresh Token은 보호된 리소스에 대한 접근을 위한 토큰은 아님 → CSRF의 위험성은 어느정도 배제한다.
- XSS에 대한 위험성? → 로컬 스토리지(자바스크립트로 접근하기 쉬워서 XSS공격이 취약) 나 쿠키 모두 이슈가 생길 수 있으나, 쿠키가 어느정도의 XSS는 막아줄 수 있다.
- 따라서 Refresh Token을 쿠키에 저장할 것을 추천한다.( HTTPOnly 와 Secure 옵션을 사용)
하지만, 위와 같은 견해도 의견이 분분하다고 한다. 적절하게 판단하여서 사용해야 될 것 같다.
https://tecoble.techcourse.co.kr/post/2021-10-20-refresh-token/