JWT가 무엇인가?
Json으로 된 데이터를 네트워크를 통해서 서로 다른 장치끼리 안전하게 전송하기 위해서 설계된 토큰 기반 인증 방식
JWT 구성

header + payload(내용) + signature(서명) ⇒ base64로 인코딩하여 마침표(.)로 연결해서 생성된 텍스트 ⇒ JWT
- header
- payload
- Claim으로 이뤄진 내용들
- 왜 Claim인가?
⇒ payload를 주고 받는 쪽에서 곧이 곧대로 믿으면 안되기 때문에 주장이라고 명칭됨
⇒ 그럼 어떻게 믿는가?
⇒ 서명을 확인한다
- signature
- 이 payload를 누가 보낸것인지 확신할 수 있다
- jwt는 서명 방식(알고리즘)을 강제하지 않는다
JWT 통신 방식
- A가 ‘언제든지 찾아오면 1달러를 주겠다’ 라는 내용의 계약을 B와 맺음
- A가 서명을 하여 B에 건내줌
- B가 계약서를 들고오면 A가 서명을 확인하고 자신이 쓴 계약임을 알 수 있음
- A가 secret key + payload를 HMAC(hash-based message authentication code)에 넣으면 그에 맞는 signature가 생성한다
- 여러 알고리즘 사용 가능
- A가 secret key만 가지고, B에게 HMAC header, payload, signature 정보를 전달한다
- B는 언젠가 내용을 A에게 들고온다
- 헤더를 보니 HMAC으로 만든 서명이라고 적혀있기때문에, A는 HMAC 알고리즘에 B가 가져온 payload와 A(본인)가 가지고 있는 secret key를 넣는다
- 이렇게 생성된 서명이 B가 가져온 서명과 일치하는지 확인한다
- 일치한다면 A가 만든 것이 틀림없다 (why? secret key는 A만 가지고 있기 때문이다)
JWT 응용 분야
- Authentication ( 로그인에 사용 )
- Information Exchange
- Authorization
- Single Sign-On
- Server-to-server communication
Cookie-based Session Management vs. Json Web Token
대부분의 사이트는 세션 기반이 구현이 쉬워서 많이 사용하지만
유저가 1억명 이상인 경우에는 JWT를 사용하는게 낫다
보안이 중요한 사이트는 jwt를 사용한다면 보안 절차를 더 추가하거나, 잘 만들어진 인증/암호 서비스를 이용할 수도 있다 (ex. Firebase)
쿠키 기반 인증

과정
- browser가 server에 로그인을 시도한다
- server는 DB로 쿼리를 조회하여 회원이 존재하는지 확인한다
- 존재한다면 session table에 어떤 사용자(=user id)가 로그인을 했고, 어떤 임시 비밀번호(=session id)를 발급했는지 기록한다
- DB가 session id를 server에 반환한다
- server가 쿠키 값으로 browser에게 응답한다
- 이 쿠키 값은 browser에 저장되고, 다음번에 접속할때마다 server로 전송된다
단점
- 브라우저가 가지고 있는 session id에는 그 외의 정보가 담겨있지 않으므로 다시 쿼리를 요청해야한다
- 서버에 접속할때마다 세션 테이블을 확인해야한다
- 사용자가 다른 장치로 접속할때마다 session id를 생성해줘야한다 ⇒ 세션 테이블에 데이터가 많아질 수 있다
JWT 기반 인증


과정
- browser가 server에 로그인을 시도한다
- server는 DB로 쿼리를 조회하여 회원이 존재하는지 확인한다
- server는 secret key + payload를 서명 알고리즘에 입력하여 서명을 생성하고, 사용한 알고리즘이 적힌 헤더와 payload, 만든 서명을 base64로 인코딩 후 마침표(.)로 연결한 텍스트로 이뤄진 JWT를 만들어낸다
- server가 JWT를 브라우저로 전달한다
- JWT를 가지고 있다는건, 인증 직후에 서버가 발행한 것이기 때문에 로그인 한 적이 있는 사람이라는 증표가 된다
- client는 JWT를 cookie나 localStorage등 브라우저에 저장한다
- JWT를 base64로 디코딩하면 담긴 정보를 얻을 수 있다
- client가 server로 JWT를 보낸다
- server는 base64로 디코딩 후 헤더에 적힌 알고리즘에 기반하여 payload와 server가 지닌 secret key로 서명을 만들어낸다
- 만들어진 서명과 client가 보낸 서명이 일치하는지 확인한다
장점
- stateless함
- payload에 자주 쓰이는 정보를 넣어줄수있다
- 로그인 할 때 한 번만 DB에 접속하고, 확인 과정에서는 DB에 접속할 필요가 없다 ⇒ 서버에 부담을 줄일 수 있다
주의할 점
- 대충 쓰면 보안 이슈 생길 수 있다
- alg : none 공격
- header에 알고리즘 표기 부분에 none으로 적었을 시 공격 당할 수 있다
- JWT는 변환이 너무 쉽다
- 변환이 너무 쉽기 때문에 민감한 정보를 payload에 넣는건 위험하다
- secret key 문제 ( brute-force attack : 무차별 대입 공격 )
- client가 jwt를 탈취 당한다면?
- stateless jwt는 jwt 회수나 사용 정지가 어렵다
- HttpOnly cookie 같이 탈취하기 어려운 브라우저 저장소에 보관한다
- jwt 블랙리스트 table을 저장해두고 검사해본다 (session 방식이랑 다를게 없긴하다)
- jwt의 유효기간을 매우 짧게 설정한다 (ex.5분)
- jwt 재발급을 위한 refresh token (ex.1년)을 운영한다
- refresh token도 저장해서 쓰는거니까 탈취위험이 있기 때문에 Refresh token rotation이 필요하다 ( refresh token은 언제나 1회만 사용이 가능하게끔 )
더 알아볼 키워드
- redis + jwt
- HMAC
- 암호화 알고리즘
- stateful vs. stateless
자료 출처 및 내용 참고
사진 출처 : 생활코딩
https://jwt.io/
https://www.youtube.com/watch?v=36lpDzQzVXs
https://www.youtube.com/watch?v=XXseiON9CV0
https://inpa.tistory.com/entry/WEB-%F0%9F%93%9A-JWTjson-web-token-%EB%9E%80-%F0%9F%92%AF-%EC%A0%95%EB%A6%AC#jwt_%EC%9E%A5%EC%A0%90