JWT(JSON Web Token)는 데이터를 안전하고 간결하게 전송하기 위해 고안된 인터넷 표준 인증 방식으로써 토큰 인증 방식에서 가장 범용적으로 사용되며 JSON 포맷의 토큰 정보를 인코딩 후, 인코딩 된 토큰 정보를 Secret Key로 서명(Sign)한 메시지를 Web Token으로써 인증 과정에 사용한다.
JWT는 보통 다음과 같이 두 가지 종류의 토큰을 사용자의 자격 증명에 이용한다.
액세스 토큰(Access Token)
리프레시 토큰(Refresh Token)
Access Token은 보호된 정보들(사용자의 이메일, 연락처, 사진 등)에 접근할 수 있는 권한부여에 사용한다.
클라이언트가 처음 인증을 받게 될 때(로그인 시), Access Token과 Refresh Token 두 가지를 다 받지만, 실제로 권한을 얻는 데 사용하는 토큰은 Access Token이다.
"그럼 Access Token 만 있으면 되는 것 아닌가요? 🤔"
맞다. 권한을 부여받는 데엔 Access Token만 가지고 있으면 된다.
하지만 Access Token을 만약 악의적인 사용자가 얻어냈다면 어떻게 될까?
이 악의적인 사용자는 자신이 00사용자인 것 처럼 서버에 여러 가지 요청을 보낼 수 있다.
⭐ 그렇기 때문에 Access Token에는 비교적 짧은 유효 기간 을 주어 탈취되더라도 오랫동안 사용할 수 없도록 하는 것이 좋다.
Access Token의 유효기간이 만료된다면 Refresh Token을 사용하여 새로운 Access Token을 발급받습니다. 이때, 사용자는 다시 로그인 인증을 할 필요가 없다.
"Refresh Token 도 탈취 당한다면요? 🤔"
유효기간이 긴 Refresh Token 마저 악의적인 유저가 얻어낸다면 큰 문제가 될 것이다.
Refresh Token을 이용해 Access Token을 다시 발급받으면 사용자에게 피해를 입힐 수 있기 때문이다.
그렇기 때문에 사용자의 편의보다 정보를 지키는 것이 더 중요한 웹 애플리케이션은 Refresh Token을 사용하지 않는 곳이 많다.
세상에 완벽한 보안은 없으므로 (있다면 쿠키, 세션, JWT, OAuth 등 다양한 방법들을 공부하지 않아도 될 것이다.) 각 방법들의 장단점을 참고하며 필요에 맞게 사용하는 것이 좋다.
JWT는 위 그림과 같이 . 으로 나누어진 세 부분이 존재한다.
Header는 이것이 어떤 종류의 토큰인지(지금의 경우엔 JWT), 어떤 알고리즘으로 Sign할지 정의합니다. JSON Web Token이라는 이름에 걸맞게 JSON 포맷 형태로 정의한다는 것을 기억하자.
{
"alg": "HS256",
"typ": "JWT"
}
이 JSON 객체를 base64 방식으로 인코딩하면 JWT의 첫 번째 부분이 완성된다.
Payload에는 서버에서 활용할 수 있는 사용자의 정보가 담겨 있다.
어떤 정보에 접근 가능한지에 대한 권한을 담을 수도 있고, 사용자의 이름 등 필요한 데이터를 담을 수 있다.
Payload는 다음으로 설명할 Signature를 통해 유효성이 검증될 정보이긴 하지만, 민감한 정보는 담지 않는 것이 좋다.
{
"sub": "someInformation",
"name": "phillip",
"iat": 151623391
}
첫 번째 부분과 마찬가지로, 위 JSON 객체를 base64로 인코딩하면 JWT의 두 번째 블록이 완성된다.
base64로 인코딩된 첫 번째, 그리고 두 번째 부분이 완성되었다면, Signature에서는 원하는 비밀 키(Secret Key)와 Header에서 지정한 알고리즘을 사용하여 Header와 Payload에 대해서 단방향 암호화를 수행한다.
이렇게 암호화 된 메시지는 토큰의 위변조 유무를 검증하는데 사용된다.
예를 들어, 만약 HMAC SHA256 알고리즘(암호화 방법 중 하나)을 사용한다면 Signature는 아래와 같은 방식으로 생성된다.
HMACSHA256(base64UrlEncode(header) + '.' +
base64UrlEncode(payload), secret);
JWT는 권한 부여에 매우 유용하다.
새로 다운받은 A라는 앱이 Gmail과 연동되어 이메일을 읽어와야 한다고 생각해보자.
이 경우, 사용자는 Gmail 인증서버에 로그인 정보(아이디, 비밀번호)를 제공한다.
인증에 성공할 경우, JWT를 발급받는다.
A 앱은 JWT를 사용해 해당 사용자의 이메일을 읽거나 사용할 수 있다.
클라이언트가 서버에 아이디/비밀번호를 담아 로그인 요청을 보낸다.
아이디/비밀번호가 일치하는지 확인하고, 클라이언트에게 보낼 암호화 된 토큰을 생성한다.
Access Token과 Refresh Token을 모두 생성한다.
JWT는 일반적으로 다음과 액세스 토큰(Access Token)과 리프레시 토큰(Refresh Token)을 사용자의 자격 증명에 이용한다.
Access Token에는 비교적 짧은 유효 기간 을 주어 탈취 되더라도 오랫 동안 사용할 수 없도록 하는 것이 권장된다.
JWT는 Header.Payload.Signature의 구조로 이루어진다.
Base64로 인코딩되는 Payload는 손쉽게 디코딩이 가능하므로 민감한 정보는 포함하지 않아야 한다.