JWT란?
JWT 사이트 주소 : https://jwt.io/
JWT는 Json Web Token으로 JSON 객체의 정보를 토큰 기반의 인증 시스템을 이용하여 안전하게 정보를 전송하는 방법이다.
JWT는 Base64로 인코딩되는 구조를 갖고 있다. 정리에 앞서 Base64 인코딩에 대해서 다뤄보자.
Base64 인코딩
Base64는 말 그대로 64진법으로, ASCII 문자들을 표시할 수 있는 가장 큰 진법이다. (참고로 ASCII 코드에서 화면에 표시되는 문자는 128개가 되지 않는다.)
즉, Binary 데이터를 Text로 변환하는 인코딩 기능 중 하나로, 공통 ASCII 영역의 문자로 이루어진 문자열로 변환해주는 기능이다.
인코딩된 문자열은 알파벳 대소문자와 숫자, 그리고 기호 64개로 이루어지며 =
는 끝을 알리는 코드로 쓰인다.
Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure.
- 위키백과 슬로건 문장
TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0
aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1
c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0
aGUgY29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdl
LCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4=
- Base64로 인코딩 된 문장
첫 단어인 Man
의 변환 과정은 다음과 같다.
JWT 구조
- JWT의 구조는
Header
,Payload
,Signature
(서명)으로 총 세 가지를 포함하는 구조를 준수한다.
Header
JWT 토큰의 헤더는 alg
와 typ
의 정보로 구성된다. alg는 알고리즘 방식을 지정하는 것으로, 시그니처를 해싱하기 위한 알고리즘을 지정하는 것이다. (SHA256, RSA 등) typ은 토큰의 타입을 지정한다.
Payload
페이로드에는 토큰에서 사용할 정보의 조각인 Claim이 담겨있다. 클레임은 엔티티 및 데이터에 대한 설명으로 등록, 공개, 개인 총 3 가지 타입이 있다.
- 등록 클레임 : 필수는 아니지만 권장되는 클레임 집합으로, 상호 운용 가능한 클레임을 제공한다.
- iss(issuer) : 토큰 발행자
- sub(subject) : 토큰 제목
- aud(audience) : 토큰 대상자
- exp(expiration) : 토큰 만료시간
- nbf(not before) : 토큰 활성 시간
- iat(issued at) : 토큰 발급 시간
- jti(jwt id) : JWT 토큰 식별자
- 공개 클레임 : JWT를 원하는대로 정의할 수 있다. 하지만 충돌 가능성이 있어 이를 방지하기 위해
IANA JSON Web Token Registry
나 네임스페이스를 포함하는 URI를 정의해서 사용해야 한다. - 개인 클레임 : 당사자 간에 개인적으로 정보를 공유하기 위해 만든 사용자 정의 클레임이다.
Signature
시그니처는 토큰을 인코딩하거나 유효성 검증을 할 때 사용하는 고유 암호화 코드이다. 서명은 헤더와 페이로드의 값을 각각 Base64로 인코딩하고, 인코딩한 값을 비밀 키를 이용해 헤더에 정의한 알고리즘으로 해싱하고, 이 값을 다시 Base64로 인코딩하여 생성한다.
쿠키 & 세션 장단점
HTTP/1.1 200
Set-Cookie: JSESSIONID=FJSKDMK20FJFKM213821836DC;
- 쿠키 & 세션 인증 방식은 서버가 클라이언트의 요청에 대한 응답을 작성할 때 인증 정보를 서버에 저장하고 클라이언트 식별자인
JSESSIONID
를 쿠키에 담아 보내서 유효성을 판단한다.
장점
- 쿠키를 포함한 요청이 외부에 노출이 되더라도 세션 ID는 무의미한 정보이다. 다만 해당 ID를 탈취하여 사용자인척 위장할 수 있는 문제는 남아있다.
- 고유 세션 ID를 통해 요청이 들어올때마다 회원정보를 확인할 필요가 없다.
단점
- 서버에서 세션 저장소를 사용하므로, 요청이 많아지면 서버의 부하가 심해진다.
JWT 인증 장단점
{
Authorization: <type> <access-token>
}
- JWT 인증 방식은 클라이언트의 요청이 오면, 정보를 Payload에 담아 암호화할 비밀키를 사용해 Access Token을 발급하여 클라리언트에 전달한다. 이후 클라이언트는 전달받은 토큰을 저장해두고, 서버에 요청할 때마다 토큰을 request header 안에
Authorization
을 포함시켜 전달한다. 이후 서버는 토큰의 시그니쳐를 비밀키로 복호화한 다음, 위변조 및 유효기간을 확인하여 검증이 완료되면 요청에 응답한다.
장점
Header
와Payload
를 가지고Signature
를 생성하므로 데이터 위변조를 막을 수 있다.- 세션과 다르게 인증 정보에 대한 별도의 저장소가 필요하지 않으며 무상태가 된다.
- Base64 URL Safe하기 때문에 범용성이 높다.
- 토큰에 대한 검증 및 전달할 정보를 자체적으로 지니고 있으며, 토큰을 기반으로 oauth 등의 다른 시스템에 접근 및 공유가 가능하다.
단점
- JWT의 토큰의 길이가 길어, 인증 요청이 많아질수록 네트워크 부하가 심해질 수 있다.
- Payload 자체는 암호화되지 않기 때문에 중요한 정보를 담을 수 없다.
- 토큰을 탈취당하면 대처하기 어렵고, 특정 토큰을 강제 만료하기 어렵다.
JWT 단점 보완 전략
짧은 만료 기한 설정
토큰이 탈취되는 경우를 최소화하기 위해 사용한다. 하지만 이 경우 사용자가 자주 로그인해야 하는 불편함도 수반이 된다.
Sliding Session
슬라이딩 세션은 서비스를 지속적으로 이용하는 클라이언트에게 자동으로 토큰 만료 기한을 늘려주는 방법이다. 글 작성 또는 결제 등이 진행 중일 때 새로운 토큰을 발급하여 제공해주는 역할을 한다.
Refresh Token
클라이언트가 로그인 요청을 보내면 서버는 AccessToken 보다 더 긴 만료 기간을 가진 Refresh Token을 발급하는 전략이다.
클라이언트는 Access Token이 만료되었을 때 Refresh Token을 사용하여 Access Token 재발급 요청을 한다. 서버는 DB에 저장된 Refresh Token과 비교하여 유효한 경우 새로운 Access Token을 발급해준다.
이 전략을 사용하면 Access Token의 만료 기한을 짧게 설정할 수 있고, 이로 인해 발생하는 사용자의 잦은 로그인 문제도 해소될 수 있다. 하지만 검증을 위해 서버와 클라이언트 모두 Refresh Token을 별도의 스토리지에 저장해야 한다.
Reference
https://ko.wikipedia.org/wiki/%EB%B2%A0%EC%9D%B4%EC%8A%A464
https://mangkyu.tistory.com/56
https://tech.toktokhan.dev/2021/04/30/JWT/
https://tecoble.techcourse.co.kr/post/2021-05-22-cookie-session-jwt/