JWT와 토큰 기반 인증 방식에 대해 알아보겠습니다.
정의
JWT(Json Web Token) 는 RFC 7519 에 명세되어 있는 국제 표준으로써, 통신 양자간의 정보를 JSON 형식을 사용하여 안전하게 전송하기 위한 방법입니다. 이는 정보가 토큰 자체에 포함된 (Self-Contained) 토큰입니다.
구성요소
JWT는 '.' 구분자를 사용하여 Header, Payload, Signature 의 3부분으로 구분되며, 각 부분은 Base64 로 인코딩 되어 표현됩니다. (Base64 은 Binary Data 를 6 bit 씩 자른 뒤 6 bit 에 해당하는 문자를 색인표에서 찾아 Text 로 변경하는 인코딩 방법입니다. )
1. 헤더(HEADER)는 해싱 알고리즘(alg) 과 토큰 타입 (typ) 의 정보를 지니고 있습니다.
- alg : 기본적으로 HMAC, SHA256, RSA 가 사용되며 토큰을 검증할 때 사용되는 signature 부분에서 사용됩니다.
- typ : JWT 이기 때문에 "JWT" 라는 값이 들어갑니다.
2. 내용(PAYLOAD)는 사용자의 데이터가 담겨져 있습니다. JSON 형태(key-value) 의 한쌍으로 이루어진 정보의 한 조각을 클레임(claim)이라고 부릅니다.
클레임은 세 종류가 있습니다. : 등록된 클레임(Registered Claims), 공개 클래임(Public Claims), 비공개 클레임(Private Claims)
2-1. 등록된 클레임(REGISTERED CLAIMS)은 서비스에서 필요한 정보들이 아닌, 토큰에 대한 정보들을 담기 위하여 이름이 이미 정해진 클레임들입니다. 등록된 클레임의 사용은 모두 선택적이며, 이에 포함된 클레임들은 다음과 같습니다.
2-2. 공개 클레임(PUBLIC CLAIMS) 은 JWT 를 사용하는 사람들에 의해 정의되는 클레임으로, 충돌이 방지된 이름을 가지고 있어야 하므로 URI 형식으로 짓거나, IANA JSON Web Token Claims Registery 라는 곳에 직접 클레임을 등록해야 합니다. 아래처럼 등록된 공개 클레임인 email, profile 등을 사용할 수 있고, URI 형태로도 사용할 수 있습니다.
{
"email": "sample@domain.com",
"profile": "http://domain.com/image.png",
"http://domain.com/xxx/yyy/is_admin": true
}
2-3. 비공개 클레임(PRIVATE CLAIMS)은 클라이언트와 서버 사이에 사용되는 클레임 이름들입니다. 공개 클레임과 충돌에 주의해야 합니다.
{
"user_id": "123456790",
"user_age": 25
}
3. 서명(SIGNATURE) 는 header 에 명시된 특정 암호화 알고리즘을 사용하여 Base64 인코딩 된 header 와 Base 64 인코딩 된 payload 그리고 비밀키를 사용하여 암호화합니다. 서명을 통해 헤더 혹은 페이로드가 누군가에 의해 변조되었지 그 무결성을 검증하고 보증할 수 있습니다.
토큰 기반 인증 방식
JWT 는 인증과 인가에 사용되는 것이 일반적입니다. JWT 를 사용하는 인증 방식을 토큰 기반 인증 방식이라고 합니다.
토큰 기반 인증 시스템은 다음과 같은 동작을 합니다.
1. 사용자가 로그인을 하게 되면, 서버에서는 JWT 를 생성해서 Set-Cookie 를 통해 클라이언트에게 제공합니다.
2. 클라이언트는 전달받는 JWT 를 로컬 스토리지에 저장해두고, 인증이 필요한 요청마다 HTTP header 에 담아서 보냅니다.
3. 서버에서는 암호화된 JWT 를 복호화 하여 올바른 요청인지 확인합니다.
4. 인증이 완료되고 서버는 요청에 응답합니다.
장점은 다음과 같습니다.
- 인증에 필요한 모든 정보를 갖고 있기 때문에 인증을 위한 별도의 저장소가 없어도 됩니다.
- 토큰 기반으로 다른 로그인 시스템에 접근이 가능해서 확장성이 우수합니다. (쿠키 기반 인증 시스템은 불가능합니다.)
단점은 다음과 같습니다.
- 쿠키/세션과 달리 토큰의 길이가 길어 인증 요청이 많아질수록 네트워크 부하가 심해집니다.
- 무상태(Stateless)한 특징을 가지고 있습니다. 서버에서는 아무런 정보도 가지고 있지 않으며, 토큰 자체의 만료일까지 토큰이 가지고 있습니다. 해당 토큰이 탈취해간다면, 서버에서는 JWT 가 만료될 때까지 아무런 조치도 취할 수 없습니다. 이런 취약점을 막기 위해서 Access Token 과 Refresh Token 을 함께 사용하는 방식을 채택합니다. 해당 방식은 Access Token 으로 사용자를 인가하지만, 그 만료기간을 매우 짧게 설정합니다. 그리고 클라이언트는 Refresh Token 을 이용하여 서버에 Access Token 재발급을 요청합니다. Refresh Token 은 약 2주 가량 만료 기간을 길게 잡습니다.