일개미 : 일상과 개발의 미학
JWT는 무엇인가? 어떻게, 왜 사용하는가? 본문
🎟️ JWT 란?
JSON Web Token의 약자로 JSON 형식의 데이터를 인코딩하여 직렬화한 것이며, 토큰 내부에는 위변조 방지를 위해 개인키를 통한 전자서명도 들어있다. 서버 - 클라이언트 간에 정보를 주고 받을 때 HTTP 요청 Header에 JSON 형식의 토큰을 실어 인증 및 식별하는 방식이다. 이 때 사용되는 JSON 데이터는 Base64 URL-safe Encode 를 통해 인코딩한다.
JWT는 HMAC 알고리즘을 사용하여 '비밀키' 또는 RSA를 이용한 '공개키', '개인키' 를 쌍으로 서명할 수 있다.
전자서명에는 비대칭 암호화 알고리즘을 사용하므로 암호화를 위한 키와 복호화를 위한 키가 다르다. 암호화(전자서명)에는 개인키를, 복호화(검증)에는 공개키를 사용한다.
💡 여기서 잠깐, 인코딩과 암호화를 혼동하는 경우가 상당한데 둘은 엄연히 다르다는 사실을 인지하자.
둘을 비교하여 설명하기엔 주제를 벗어날 수 있으니 추후에 따로 포스팅하도록 하겠다.
⛓️ JWT의 구조
인코딩된 JWT는 . 을 구분자로 나뉘는 세가지의 문자열로 구성되어 있다. 디코딩된 정보는 각 Header, Payload, Signature 를 나타낸다. 구조를 좀 더 살펴보자.
Header
- alg : 서명 암호화 알고리즘(ex: HMAC SHA256, RSA)
- typ : 토큰 유형
Payload
페이로드에는 토큰에서 사용되는 정보가 들어있다. 여기에 담긴 정보의 한 ‘조각’ 을 클레임(claim) 이라고 부르고, 클레임은 key-value를 한 쌍으로 이루어져있다. 토큰에는 여러개의 클레임 들을 넣을 수 있다.
클레임의 종류는 (혹은 그의 집합체인 페이로드) 정해진 형식은 따로 없지만, 대표적으로 다음과 같이 크게 세 분류로 나뉘어 사용된다.
Registered claims(등록된 클레임) / Public claims(공개 클레임) / Private claims(비공개 클레임)
- Registed claims
- 등록된 클레임들은 서비스에서 필요한 정보들이 아니라 토큰에 대한 정보들을 담기위하여 이미 정해진 클레임들이다. 등록된 클레임의 사용은 모두 선택적으로 가능하며, 이에 포함된 클레임들은 대표적으로 다음과 같으며, 나머지는 IANA JSON 웹 토큰 레지스트리를 참고하도록 하자.
iss: 발행자 (issuer)
sub: 제목 (subject)
aud: 대상자 (audience)
exp: 만료시간 (expiraton)
* 시간은 NumericDate 형식이며 현재시간보다 이후로, 재사용될 수 없도록 하는 기준이다.
nbf: 활성화 이전 시점 (not before)
* 이 또한 NumericDate 형식이며, 이 날짜가 지나기 전의 토큰은 활성화되지 않음.
iat: 발행 시간 (issued at)
* 이 정보를 통해 토큰의 경과시간을 알 수 있다.
jti: JWT 식별자 (JWT identity)
* 중복처리를 방지하기 위함, 주로 일회용 토큰(Access Token)에 사용된다.
* not before는 정확한 해석 명칭이 없다. 이해가 쉽도록 작성자가 임의로 해석한 단어임을 참고할 것.
- Public claims
- 사용자 정의 클레임으로, 공개용 정보를 위해 사용된다. 충돌 방지를 위해 IANA JSON 웹 토큰 레지스트리에 등록된 클레임들을 활용하거나 충돌 방지 네임스페이스를 포함하는 URI로 정의해야 한다.
- 사용자 정의 클레임으로, 공개용 정보를 위해 사용된다. 충돌 방지를 위해 IANA JSON 웹 토큰 레지스트리에 등록된 클레임들을 활용하거나 충돌 방지 네임스페이스를 포함하는 URI로 정의해야 한다.
❓ 네임스페이스란? 내부 식별자(형식, 함수, 변수 등의 이름)에 범위를 제공하는 선언적 영역
▼ URI 형식예시
{
"https://glow28.tistory.com": true
}
- Private claims
- 마찬가지로 사용자 정의 클레임으로, 외부에 공개되어도 상관은 없지만 해당 유저(클라이언트)를 특정하는 정보들을 담는다.
❗️주의할 점
서명된 토큰의 경우 이 정보는 변조로부터 보호되지만 누구나 읽을 수 있다. 암호화되지 않은 경우 JWT의 Payload 또는 Header 요소에 비밀 정보를 입력하지 않도록 한다.
Signature
서명(Signature)은 토큰을 인코딩하거나 유효성 검증을 할 때 사용하는 고유한 암호화된 코드로, 헤더와 페이로드를 각각 BASE64Url로 인코딩하고, 인코딩된 값을 비밀키를 이용해 헤더에서 정의한 알고리즘으로 해싱하고, 이 값을 다시 BASE64Url로 인코딩하여 생성한다.
Header와 Payload는 단순히 인코딩된 값이기 때문에 제 3자가 복호화 및 조작할 수 있지만, Signature는 서버에서 관리하는 비밀키 없이 복호화할 수 없으므로 토큰의 위변조 여부를 확인하는데 사용된다.
따라서, 비밀키가 외부로 유출되지 않도록 주의해야한다.
🔍 JWT 작동 원리
인증에서 사용자가 자격 증명(회원 정보 등)을 사용하여 성공적으로 로그인하면 서버에서 클라이언트로 토큰이 반환된다. 토큰은 자격 증명이므로 보안 문제를 방지하기 위해 주의해야 한다. 일반적으로 필요 이상으로 토큰을 보관해서는 안된다.
웹 서비스에 회원이 있다고 가정하고, 이 회원이 자격 증명을 거쳐야하는 리소스(회원 권한이 필요한 페이지 등 서버로부터 보호된 경로 혹은 자원)에 접근하려고 하는 이 때,
일반적으로 Bearer 스키마 를 사용하여 Authorization 헤더에서 JWT를 클라이언트로부터 서버로 다음과 같은 형식으로 보내야한다.
Authorization: Bearer <token>
이를 통해 서버로부터 보호된 경로는 헤더에서 유효한 JWT를 확인하여 해당 JWT가 있는 경우 사용자가 접근할 수 있도록 한다. 또한 JWT에 필요한 데이터가 포함되어 있으면 항상 그런 것은 아니지만 특정 작업에 대해 데이터베이스를 쿼리해야 할 필요성이 줄어들 수 있다.
💬 JWT를 사용하는 이유와 단점
JWT를 사용하는 이유는 여러 면에서 인터넷 환경에 SWT(Simple Web Token)과 SAML(Security Assertion Markup Language Tokens)보다 더 적합하기 때문이라고 한다.
JSON 형식은 XML보다 단순하기 때문에 용량도 작고 간편하므로 XML 기반의 SAML 방식보다 크기가 작다. 보안 측면에서는 SWT방식은 대칭키 방식인 HMAC 방식으로 해싱하지만 JWT와 SAML토큰은 x.509인증서 형식의 공개키/개인키 방식을 사용할 수 있다.
인증 과정에서 대칭키 방식은 인증 확인자가 같은 키로 데이터를 만들어 다른 인증 확인자에게 잘못 사용할 수 있는 문제가 있다. 또한 인증 과정은 확인자가 데이터를 생성할 필요 없이 확인만 하면 되기 때문에 공개키/개인키 방식이 적합하다. 또한 JSON 형식은 구조상 대부분 언어에서 객체로 바로 변환될 수 있기 때문에 대부분의 언어에서 지원한다는 장점이 있다. XML로는 JSON처럼 대부분 언어에서 바로 객체에 매핑되기 어렵다는 점에서 JWT이 주목받고 있는 이유이다.
그렇지만, JWT가 완벽한 인증 방식이 될 수는 없는 이유도 있다.
암호화되어 나타나지만, 정보가 클라이언트에 있으므로 제3자로부터 복호화될 경우 문제가 생길 수 있다. 따라서 위에서 한번 주의점으로 언급했듯이 민감하거나 비밀 정보는 노출되지 않도록 조심해야한다.
또한, 토큰의 길이가 세션쿠키에 비해 길어질 수 있어 네트워크의 속도 저하를 일으킬 수 있고, 길이에 제한이 있다.
용이성이 좋아 현재 대부분의 서비스에서 사용되지만, 이를 보완하기 위해 Access Token과 Refresh Token을 따로 발급하는 등의 방식도 사용되므로 단점들을 잘 이해하고 사용할 수 있도록 하자.
* 참고 문헌
JWT.IO
JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties.
jwt.io
[WEB] 📚 JWT 토큰 인증 이란? - 💯 이해하기 쉽게 정리
인증 방식 종류 (Cookie & Session & Token) 보통 서버가 클라이언트 인증을 확인하는 방식은 대표적으로 쿠키, 세션, 토큰 3가지 방식이 있다. JWT를 배우기 앞서 우선 쿠키와 세션의 통신 방식을 복습해
inpa.tistory.com
[Server] JWT(Json Web Token)란?
현대 웹서비스에서는 토큰을 사용하여 사용자들의 인증 작업을 처리하는 것이 가장 좋은 방법이다. 이번에는 토큰 기반의 인증 시스템에서 주로 사용하는 JWT(Json Web Token)에 대해 알아보도록 하
mangkyu.tistory.com
JWT에 대해 알아보자
Oauth에 많이 쓰이는 JWT에 대해 알아보자
velog.io
'Developments > CS' 카테고리의 다른 글
RDBMS? NoSQL? DB의 세계 - (1)🧐 (0) | 2022.12.03 |
---|---|
데이터 포맷(Data Format) : XML / JSON / CSV 의 특징 및 비교 (0) | 2022.12.03 |
SOAP API 와 REST API 의 장단점 및 차이 (0) | 2022.11.22 |