- JWT(Json Weeb Token)은 하나의 인터넷 표준 인증 방식이다. 말 그대로 인증에 필요한 정보들을 Token에 담아 암호화 시켜 사용하는 토큰이다.
- 인증을 진행하는 구조는 Cookie와 크게 다르지 않다. 하지만, JWT는 서명된 토큰이다. 공개/개인 키를 쌍으로 사용하여 토큰에 서명할 경우 서명된 토큰은 개인 키를 보유한 서버가 이 서명된 토큰이 정상적인 토큰인지 인증할 수 있다.
- 이런 구조 때문에 인증 정보를 담아 안전하게 인증을 시도하게끔 전달할 수 있다.
- Header
- Payload
- Signature
- 위 구성요소로 되어 있으며, "."로 구분된다.
- header에는 보통 토큰의 타입이나, 서명 생성에 어떤 알고리즘이 사용되었는지 저장한다.
- 위와 같은 경우에는 현재 토큰의 타입이 JWT이고, 앞서 이야기 했던 개인키로 HS512 알고리즘이 적용되어 암호화가 되어있다고 볼 수 있다.
- payload는 보통 claim이라는 사용자에 대한 , 혹은 토큰에 대한 property를 key-value의 형태로 저장한다. Claim이라는 말 그대로 토큰에서 사용할 정보의 조각인 셈이다. 사실 어떤 Claim 값을 넣는지는 개발자의 마음이긴 하지만 지금은 표준 스펙을 공부해 보았다.
- 표준 스펙상 key의 이름은 3글자로 되어있다. JWT의 핵심 목표는 사용자에 대한, 토큰에 대한 표현을 압축하는 것이기 때문에 이를 정의한 것으로 볼 수 있다.
- iss(Issuer): 토큰 발급자
- sub(Subject): 토큰 제목 - 토큰에서 사용자에 대한 식별 값이 됨
- aud(Audience): 토큰 대상자
- exp(Expiration): 토큰 만료 시간
- nbf(Not Before): 토큰 활성 날짜(이 날짜 이전의 토큰은 활성화되지 않음을 보장)
- iat(Issued At): 토큰 발급 시간
- Jti(JWT Id): JWT 토큰 식별자(issuer가 여러 명일 때 이를 구분하기 위한 값)
- 위 표준 스첵으로 정의되어있는 Claim 스펙이 있는 거지, 꼭 이 7가지를 포함해야 하는 것은 아니다. 그래서 상황에 따라 해당 서버가 가져야 할 인증 체계에 따라 사용하면 된다.
- 표준 스펙 외에도 필요하다 싶으면 추가해도 전혀 문제가 되지 않는다. 예를 들어 Access Token과 Refresh Token을 구분하고 싶다면 "token_type"이라는 커스텀한 Claim을 만들고 값을 아래와 같이 "access token"으로 두어 구분 지어도 된다.
- 가장 중요한 것은 payload에 민감한 정보를 담지 않는 것이다. 유ㅏ애 header와 payload는 json이 디코딩되어 있을 뿐이지 특별한 암호화 걸려있는 것이 아니기 때문에 누구나 jwt를 가지고 디코딩을 한다면 header나 payload에 담긴 값을 알 수 있기 때문이다.
- 가장 중요한 서명이다. 위 이미지는 암호화가 되어 있어, 그 구조에 대한 이미지를 가져온 것이다.
- 지금까지 Header와 Payload를 보여줄 때는 인코딩 되어있던 값들을 JWT에 담겨있는 것처럼 디코딩된 상태를 사용한다. header를 디코딩한 값, payload를 디코딩한 값을 위처럼 합치고 이를 your-256-bit-secret 즉, 서버가 가지고 있는 개인키를 가지고 암호화되어있는 상태이다.
- 따라서, signature는 서버에 있는 개인키로만 암호화를 풀 수 있으므로 다른 클라이언트는 임의로 Signature를 복호화할 수 없다.
- 결국, JWT 토큰을 클라이언트가 서버로 요청과 동시에 전달한다. => 서버가 가지고 있는 개인키를 가지고 Signature를 복호화한 다음 base64UrlEncode(header)가 JWT의 header값과 일치한 지, base64UrlEncode(payload)와 일치한 지 확인하여 일치한다면 인증을 허용 한다.
- 만약 클라이언트가 payload에 담긴 식별자가 변조된 JWT로 요청을 하더라도 서버가 애초에 발급했던 Signature안의 Payload와 다르기 때문에 인증이 불가능 해진다.
- 쿠키와 세션에서 겪었던 모든 단점을 해결하는 것이 JWT인 것이기 때문에 단점들을 뒤집으면 JWT의 장점이다.
- 이미 토큰 자체가 인증된 정보이기 때문에 세션 저장소와 같은 별도의 인증 저장소가 "필수적"으로 필요하지않다.
- 세션과는 다르게 클라이언트의 상태를 서버가 저장해 두지 않아도 된다.
- signature를 공통 키, 개인키 암호화를 통해 막아두었기 때문에 데이터에 대한 보완성이 늘어난다.
- 다른 서비스에 이용할 수 있는 공통적인 스펙으로써 사용할 수 있다.