JWT (Json Web Token)
웹에서 사용되는 Json 형식의 토큰
RFC 7519 웹 표준
자가 수용적으로 사용자 정보를 안전성 있게 전달함
자가 수용적 (self-contained)
- 자가 수용적: 필요한 것을 수행하기 위해 내가 가지고 있는 것으로 만족한다.
- 즉, 다른 것 필요 없이 JWT만으로 로직을 진행할 수 있다는 뜻이다.
- 그 이유는 JWT가 사용자 식별을 위해 필요한 모든 정보를 자체적으로 지니고 있기 때문이다.
JWT 사용처
인증
서버는 클라이언트가 로그인을 요청하면 사용자 정보(username, authorities 등)를 이용하여 token을 만들고, 클라이언트에게 전달한다.
인가
클라이언트는 매 요청마다 토큰을 함께 전달한다. 서버는 해당 토큰이 유효하고 인증되었는지 검증한다.
정보 교류
token 검증 시 정보가 조작되었는지 확인할 수 있으므로 안전하게 정보를 전달할 수 있다.
JWT vs Session
서버 측에 사용자의 정보가 저장되어 있다.
Stateful
- 클라이언트의 상태를 계속 유지해야 하므로 세션 과부하가 올 수 있다.
서버 확장의 어려움 - 여러 대의 서버가 있을 때 처음 로그인했던 서버에만 요청을 보내도록 해야 한다.
클라이언트가 인증에 필요한 정보를 가지고 있다.
Stateless
- 서버는 사용자 정보를 유지할 필요가 없다.
웹과 앱을 하나의 서버로 관리할 수 있다
과정
1) 사용자가 로그인을 요청한다.
2) 서버 측에서 사용자의 username, password를 검증한다.
3) 정보가 정확하다면 서버측에서 클라이언트에게 token을 발급한다.
4) 클라이언트는 발급 받은 token을 저장한다.
5) 서버에 요청을 할 때마다 token을 함께 전달한다.
6) 서버는 token을 검증하고 요청에 응답한다.
JWT 구조
type: 토큰의 타입
alg: 해싱 알고리즘
{ "typ": "JWT", "alg": "HS256" } base64 Encoding: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
토큰의 Body 부분이며 실질적인 정보를 담는다.
Payload에 추가하는 데이터를 Claim
이라고 부르며, Claim은 (name, value) 형식이다.
Registered(미리 정의된) Claim과 Custom Claim을 선택적으로 사용할 수 있다.
민감 정보를 담지 않도록 주의한다.
Registered Claim
1) iss: 토큰 발급자
2) sub: 토큰 제목
3) aud: 토큰 대상자
4) exp: 토큰 만료시간
5) nbf: 토큰 활성 날짜
6) iat: 토큰이 발급된 시간
7) jti: JWT 고유 식별자
{ "iss": "example.com", "exp": "1516239022", "username": "test01@gmail.com" } base64 encoding: eyJpc3MiOiJleGFtcGxlLmNvbSIsImV4cCI6IjE1MTYyMzkwMjIiLCJ1c2VybmFtZSI6InRlc3QwMUBnbWFpbC5jb20ifQ
1) base64(Header) + "." + base64(payload): eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJleGFtcGxlLmNvbSIsImV4cCI6IjE1MTYyMzkwMjIiLCJ1c2VybmFtZSI6InRlc3QwMUBnbWFpbC5jb20ifQ 2) 임시 비밀키 "secretbase64"로 해싱: IB7FCuLuZsR25P42eOxC3gEUprEeAMZXJz-YTce6RxE 3) 얻은 값을 base64 encoding: -jn6ZgIl5y8A9DO8c7psjDPC5nhRFPqbleeu2bXPOjM
JWT 저장 방식
Refresh Token
token은 local, header, cookie 등 다양한 곳에 저장할 수 있지만, 어디서든 탈취 위험이 있다.
따라서 token의 유효기간을 적절히 설정할 필요가 있다. 여기서 딜레마가 발생한다.
기간을 짧게 설정하면 사용자가 자주 로그인을 해야하는 불편함이 있고, 기간을 길게 설정하면 token 탈취 위험성이 높아진다.
이를 해결하기 위해 나온 아이디어가 2개의 JWT(Access Token
, Refresh Token
)을 사용하는 것이다.
Access Token
은 유효기간을 짧게, Refresh Token
은 유효기간을 길게 설정한다.
과정
1) 클라이언트가 로그인 인증에 성공하면 서버는Access Token
,Refresh Token
두 개를 클라이언트에게 보낸다.2) 클라이언트는
Access Token
을 header나 cookie에 저장하고,Refresh Token
을 local에 저장한다. (이때,Refresh Token
도 header나 cookie에 저장하자는 관점이 있기도 하다)3) 매 요청마다 클라이언트는
Access Token
을 가지고 통신한다.4) 일정 기간이 지나
Access Token
의 유효기간이 만료된다.5) 클라이언트는
Access Token
과Refresh Token
을 함께 서버로 보낸다.6) 서버는 클라이언트에게 받은
Refresh Token
과 local에 저장된Refresh Token
를 비교한 후, 유효성이 검증되면 새로운 Access Token을 발급한다.7) 만약
Refresh Token
도 만료되었다면 사용자는 다시 로그인을 해야 한다.
장단점
1) 장점
2) 단점
Payload에 민감 정보가 들어가면 탈취될 염려가 있음
Payload의 정보가 많아질수록 네트워크 부하가 커짐
참고
- https://velog.io/@dnjscksdn98/JWT-JSON-Web-Token-%EC%86%8C%EA%B0%9C-%EB%B0%8F-%EA%B5%AC%EC%A1%B0
- https://velog.io/@dnjscksdn98/JWT-%ED%86%A0%ED%81%B0-%EA%B8%B0%EB%B0%98-%EC%9D%B8%EC%A6%9D%EC%9D%B4%EB%9E%80
- https://velog.io/@chang626/JWT-%EA%B8%B0%EB%B3%B8%EA%B0%9C%EB%85%90
- https://samtao.tistory.com/65
- https://jusths.tistory.com/350
- https://velog.io/@0307kwon/JWT%EB%8A%94-%EC%96%B4%EB%94%94%EC%97%90-%EC%A0%80%EC%9E%A5%ED%95%B4%EC%95%BC%ED%95%A0%EA%B9%8C-localStorage-vs-cookie
- https://velog.io/@chuu1019/Access-Token%EA%B3%BC-Refresh-Token%EC%9D%B4%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B4%EA%B3%A0-%EC%99%9C-%ED%95%84%EC%9A%94%ED%95%A0%EA%B9%8C