JWT란?
1. JWT란?
JWT는 일반적으로 클라이언트와 서버, 서비스와 서비스 사이 통신 시 권한 인가(Authorization)를 위해 사용하는 토큰이다. URL에대해 안전한 문자열로 구성되어 있기 때문에 HTTP 어디든(URL, Header, ...) 위치할 수 있다.
2. JWT의 구조
JWT는 "." 을 기준으로 HEADER / PAYLOAD / SIGNATURE 로 나뉩니다.
HEADER.PAYLOAD.SIGNATURE
Header
JWT를 검증하는데 필요한 정보를 가진 JSON 객체는 Base64 URL-Safe 인코딩된 문자열이다.
헤더(Header)는 JWT를 어떻게 검증(Verify)하는가에 대한 내용을 담고 있다. 즉 alg는 3번째 값인 서명 값을 어떤 알고리즘으로 만들지 적혀 있습니다.
{
"alg": "ES256",
"kid": "Key ID"
}
Payload
JWT의 내용이다. 페이로드(Payload)에 있는 속성들을 클레임 셋(Claim Set)이라 부른다.
클레임 셋은 JWT에 대한 내용(토큰 생성자(클라이언트)의 정보, 생성 일시 등)이나 클라이언트와 서버 간 주고 받기로 한 값들로 구성된다.
{ "iss": "jinho.shin", "iat": "1586364327" }
Signature
- 누군가 JWT를 탈취하여 수정한 후 서버로 보낼 수 있습니다. 이 경우에 대비해 다른 사람이 위변조 했는지 검증하기 위한 부분입니다.
- 서명은 헤더의 인코딩 값, 정보의 인코딩 값을 합친 후 비밀키로 해쉬를 하여 생성합니다.
- 서명은 헤더의 alg에 정의된 알고리즘과 비밀 키를 이용해 성성하고 Base64 URL-Safe로 인코딩한다
- 완성된 JWT는 헤더의 alg, kid 속성과 공개 키를 이용해 검증할 수 있다. 서명 검증이 성공하면 JWT의 모든 내용을 신뢰할 수 있게되고, 페이로드의 값으로 접근 제어나 원하는 처리를 할 수 있게된다.
3. JWT 토큰 저장 방식
JWT 토큰을 저장 하지 않는다면, 새로고침을 할 때마다 새로 토큰을 제공 받아야 한다. 고로, 이를 관리하는 방식을 알아두는 것도 중요하다.
참고로, 토큰이 쓸모 없어지면 저장 장소에서도 동시에 없애야 한다.
[1] Sesson or localStorage ( stateful )
필수 데이터, 세션 / 사용자 ID의 일부만 포함하고 나머지는 서버 측에 저장되는 토큰입니다.
이 솔루션은 토큰을 예측할 수없고 공격자가 검색 할 수 없 다는 점을 고려하여 기본적으로 CSRF 공격으로부터 애플리케이션을 보호합니다
[2] Cookie ( stateless )
Stateless로 유지되지만 서로 다른 도메인의 프로그램 간의 통합이 적용 되지 않습니다.
쿠키는 도메인 (또는 하위 도메인)에 연결되며 다른 도메인에서 호스팅되는 다른 응용 프로그램에서 사용할 수 없습니다.
브라우저의 쿠키에 저장되면 "HttpOnly"플래그 (및 "Secure")를 설정하여 XSS 공격의 경우 토큰 도난으로부터 보호 할 수 있습니다.
단점은 토큰에서 CSRF 보호를 기대할 수 없다는 것입니다. 실제로 토큰은 쿠키와 함께 자동으로 전송됩니다.
4. JWT 토큰의 장/단점
장점
인가를 위해 서버가 별도로 저장하는 경우가 없다. 이를 stateless 하다고 표현한다.
단점
[1] 데이터 증가에 따른 네트워크 부하 증가
모든 요청에 대해서 토큰이 전송되므로 토큰에 담기는 정보가 증가할 수록 네트워크 부하가 증가합니다. 그래서 보통 약자가 많이 사용됩니다.
[2] Self-contained
토큰 자체에 정보를 담고 있습니다. JWT가 만료시간 전에 탈취당하면 서버에서 할 수 있는 것이 없습니다.
즉, 서버가 토큰에 대한 통제력을 가지고 있지 않습니다.
[3] Stateless
JWT는 상태를 저장하지 않기 때문에 한번 만들어지면 제어가 불가능합니다. 토큰을 임의로 삭제하는 것이 불가능하므로 만료 시간을 꼭 넣어 주어야 합니다.
5. 보완점
최초 로그인을 하면,
1) 만료시간이 짧은 Access 토큰
2) 만료시간이 매우 긴 Refresh 토큰
을 모두 부여합니다. 이후에, refresh에 대한 상응 값은 데이터베이스에 저장합니다.
유저의 access 토큰이 기한을 다하면, refresh 토큰을 보내면 저장된 값과 비교하여 맞으면 Access 토큰을 재발급 해준다.