JWT
JSON Web Token. 사용자의 정보를 Json에 담아 보내는 형식의 웹 토큰이다.
핵심
Header / Payload / Signature 로 나뉘며, base64 인코딩을 통해 url-safe한 xxx.yyy.zzz 형태로 표현한다. Header에는 Signature 에 서명한 알고리즘 정보를 담는다. Payload에는 실제 사용자 정보를 Json 형태로 담으며 추가에 열려있다. Signature는 header와 payload가 변경 안되었음을 보증한다.
주로 인증을 위해 사용하는데, JWT의 유효성(위조 여부)만 확인하면 인증은 완료된다. 이미 JWT 발급 시점에 (id, pwd로) 사용자를 인증했고 그 결과로 JWT를 생성했기에, (Signature를 이용하여) JWT 가 위조되지 않았다는 것만 확인하면 JWT 발급 시점과 같은 사용자라는 것을 알게되는 원리이다.
때문에 인증만을 위해 사용하는 순정 JWT는 Stateless 하다. 세션 방식 인증과 달리, 인증을 위한 DB나 캐시가 필요하지 않다. Access 토큰만 있으면 클라이언트에서 인증 여부를 바로 판단할 수 있는 것이다.
리프레시 토큰의 사용
JWT를 실무에서 사용할땐 보통 리프레시 토큰으로 액세스 토큰을 보완한다. 액세스 토큰은 반드시 만료 시간이 필요한데, 액세스 토큰이 탈취당하는 리스크를 줄이기 위함이다. 만료 시간을 짧게 설정할 것이 권장되는데, 이로 인해 1) 사용자가 잦은 로그아웃을 경험하는 문제를 해결하기 위해 리프레시 토큰이 필요하다. 또한, 2) 만료 시간 이내에 액세스 토큰이 탈취되는 문제를 제어하기 위해서도 리프레시 토큰이 필요하다.
리프레시 토큰을 포함한 인증은 아래와 같은 과정을 거친다. (서버가 토큰의 검증을 담당하는 경우). 리프레시 토큰을 위 목적에 맞게 사용하려면 db에 저장해야한다.
- 클라이언트가 로그인하면, 서버는 JWT(액세스 토큰, 리프레시 토큰)를 발급한다.
- 리프레시 토큰은 db에 저장한다.
- 클라이언트는 액세스 토큰과 리프레시 토큰을 쿠키나 로컬 스토리지에 저장한다.
- 클라이언트는 액세스 토큰과 리프레시 토큰을 포함하여 서버에 요청한다.
- 서버는 액세스 토큰의 위조 여부를 확인하여 인증한다.
- 서버는 액세스 토큰이 유효한지 검사한다.
- 액세스 토큰이 만료되었다면, 서버는 리프레시 토큰을 확인한다.
- 리프레시 토큰이 유효한지
- DB에 해당 리프레시 토큰이 존재하는지 확인한다.
- 리프레시 토큰이 인증된다면 서버는 액세스 토큰을 다시 발급한다.
리프레시 토큰이 탈취되는 경우를 대비해 별도의 토큰 저장소를 운영하기도 한다.
- 액세스 토큰과 리프레시 토큰 쌍을 DB에 저장하여
- 리프레시 토큰으로 새 액세스 토큰 발급 요청이 오면
- 리프레시 토큰으로 기존 액세스 토큰을 조회하여 만료 여부를 확인한다
- 기존 액세스 토큰이 만료되지 않았다면, 리프레시 토큰이 탈취된 것으로 간주, 리프레시 토큰을 만료시킨다
로그아웃 구현
우선적으로 클라이언트에서 액세스 토큰을 삭제해야한다. 하지만 그것만으로는 온전하지 않은데, 해당 액세스 토큰은 여전히 유효하기 때문이다. 액세스 토큰을 탈취 당했다면, 비정상적인 접근을 막을 수 없다. 더해서 리프레시 토큰까지 함께 탈취당했다면, 액세스 토큰이 만료된 후에도 계속 비정상적으로 접근 가능해진다.
로그아웃을 위해 보통 블랙리스트 토큰 방식을 사용한다. 로그아웃된 토큰을 db에 블랙리스트로 저장하고, 요청된 토큰이 블랙리스트인지 확인하는 것이다. 보통 리프레시 토큰을 블랙리스트로 저장한다. 리프레시 토큰을 사용하는 시점(액세스 토큰 만료 시점)부터 비정상적 접근을 차단할 수 있는 것이다. 보다 안전하게는 액세스 토큰을 블랙리스트로 저장할 수 도 있다. 하지만, 이 경우 액세스 토큰을 검증하기 위해 매번 DB 접근이 필요하므로, JWT의 이점을 살리기 어려워진다.
JWT 저장 공간
JWT를 쿠키에 (Http only 옵션 사용하여) 저장하면 브라우저에서(js로) 쿠키 접근이 불가해 XSS로 부터 안전하지만, 매번 request에 권한을 담기 때문에 CSRF로 부터 취약하다.
refs
- JSON Web Token - Wikipedia
- RFC 7519: JSON Web Token (JWT)
- JWT (Json Web Token)와 비대칭키
- 🌐 JWT 토큰 인증 이란? (쿠키 vs 세션 vs 토큰)
- [우테코] JWT 방식에서 로그아웃, Refresh Token 만들기(1): JWT의 Stateless한 특징을 최대한 살리려면? — 깃짱코딩
- JWT에서 Refresh Token은 왜 필요한가?
- JWT는 어디에 저장해야할까? - localStorage vs cookie