[WEB] Authentication (2) JWT
저번 포스팅에 이어 이번엔 인증하는 두 번째 방법, JWT에 대해서 알아보겠습니다.
[WEB] Authentication (1) 세션과 쿠키
JWT 란
JWT란 Json Web Token의 줄임말로 json 형태의 token입니다.
JWT을 만들기 위해서는 header
, payload
, verify signature
총 3가지가 필요합니다.
그리고 3개를 .
으로 조합하여 아래와 같은 형태로 만들어집니다.
header.payload.verify_signature
header
header는 일반적으로 token의 타입과 signature 알고리즘이 포함됩니다.
{
"alg": "HS256",
"typ": "JWT"
}
그 후 JSON은 Base64Url로 인코딩 됩니다.
Signature vs Encryption
Signature : 비밀 키를 가진 소수만 데이터에 서명할 수 있습니다. 그리고 공개 키를 가진 아무나 서명을 검증할 수 있습니다.
Encryption : 공개 키를 가진 아무나 데이터를 암호화 할 수 있습니다. 그리고 비밀 키를 가진 소수만 데이터를 복호화하여 확인할 수 있습니다.
payload
payload는 추가적인 데이터를 넣을 수 있습니다.
{
"name": "minsung"
}
이 외에도 자주 쓰이는 항목들은 등록된 클레임으로 사전에 지정되어 있습니다.
- iss: 토큰 발급자 (issuer)
- sub: 토큰 제목 (subject)
- aud: 토큰 대상자 (audience)
- exp: 토큰의 만료시간 (expiraton), 시간은 NumericDate 형식으로 되어있어야 하며 (예: 1480849147370) 언제나 현재 시간보다 이후로 설정되어있어야합니다.
- nbf : Not Before 를 의미하며, 토큰의 활성 날짜와 비슷한 개념입니다. 여기에도 NumericDate 형식으로 날짜를 지정하며, 이 날짜가 지나기 전까지는 토큰이 처리되지 않습니다.
- iat : 토큰이 발급된 시간 (issued at), 이 값을 사용하여 토큰의 age 가 얼마나 되었는지 판단 할 수 있습니다.
- jti : JWT의 고유 식별자로서, 주로 중복적인 처리를 방지하기 위하여 사용됩니다. 일회용 토큰에 사용하면 유용합니다.
그 후 JSON은 Base64Url로 인코딩 됩니다.
signing된 JWT는 변조로부터 보호되지만 누구나 읽을 수 있습니다.
따라서 별도의 암호화가 없다면 payload에 보안 상 중요한 값은 넣지 않습니다.
verify signature
verify signature을 생성하기 위해 인코딩된 header, 인코딩된 payload, secret이 필요합니다.
예를 들어 signing 알고리즘이 HS256
인 경우에는 아래와 같이 생성됩니다.
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
HS256
은 대칭키 알고리즘으로서 하나의 키가 비밀 키와 공개 키 역할을 모두 수행합니다.일반적으로 서버와 클라이언트의 통신 시, JWT를 사용한다면 서명을 하는 주체와 서명을 검증하는 주체가 모두 서버입니다. 따라서 대칭키 알고리즘을 사용해도 문제가 없을 뿐 아니라 비대칭키 알고리즘에 비해 연산이 간단하여 CPU 사용량도 적습니다.
verify signature은 메세지가 변조되지 않았음을 확인하는데 사용됩니다.
아래 사이트에서 직접 JWT를 만들어 볼 수 있습니다.
JWT를 이용한 인증
- 클라이언트에서 인증서버로 권한을 요청합니다. 다양한 방법이 있겠지만 일반적으로 올바른 아이디와 패스워드를 입력하여 인증을 받을 수 있습니다.
- 인증서버에서 JWT를 생성하여 클라이언트에게 반환합니다.
- 클라이언트는 JWT를 사용하여 보호된 리소스들에 접근할 수 있습니다.
JWT의 장단점
장점
- 인증에 필요한 모든 정보를 토큰 자체가 포함하기 때문에 별도의 인증 저장소가 필요 없습니다.
- 다른 token들에 비해 크기가 작아 트래픽에 대한 부담이 낮습니다.
- expired 기능을 내장하고 있습니다.
- 수평 스케일링에 용이합니다.
- micro service 환경에서 중앙집중식 인증서버에서 벗어나 개별 micro service에서 해결할 수 있습니다.
단점
- JWT를 클라이언트에 저장하여 사용하기 때문에 DB에서 값이 바뀌더라도 JWT에 바로 적용할 수 없습니다.
- payload에 데이터가 많아지면 JWT의 크기가 커집니다.
- JWT는 거의 모든 요청에 전송되므로 트래픽 크기에 영향을 미칠 수 있습니다.
- 한 번 발급한 JWT는 값을 수정하거나 폐기가 불가능합니다.
- 기본적으로 암호화하지 않기 때문에 정보가 노출 될 수 있습니다.
Refresh Token
Refresh Token
은 JWT의 단점들을 극복하기 위해 나온 개념입니다.
JWT 값을 수정과 폐기가 불가능하기 때문에 중간에 탈취당할 경우 보안적인 이슈가 생길 뿐더러 DB 값이 바뀌더라도 갱신할 수 없었습니다.
따라서 access token
과 refresh token
, 두 개의 JWT를 사용합니다.
access token은 만료기간을 굉장히 짧게 가져가고, refresh token은 비교적 길게 가져갑니다.
이를 이용하여 인증하는 방법을 알아봅시다.
두 token을 발급받는 과정은 다음과 같습니다.
일반적인 경우에는 위에서 봤던 JWT를 이용한 인증
과 동일합니다.
이 때 access token이 만료된 경우에는 어떨까요?
만료된 access token으로 요청을 보낸 후 과정은 아래와 같습니다.