이번에는 JWT 에 대해 써보려고 한다. 익히 들어왔지만 뭔지 설명하라고 하면 쉽지않은..
JWT 공식 문서인
https://jwt.io/introduction
이 글을 번역하는 식으로 포스팅 해보려고 한다. 더듬더듬...
- JWT 정의
- 언제 JWT를 사용할까?
- JWT 구조
- JWT 작동 방식
- 우리가 JWT를 사용해야하는 이유
JWT는 JSON Web Token 의 준말로 정보를 JSON 객체로 안전하게 전송하기 위한 표준 방식이다. JWT 정보는 디지털로 서명되어 신뢰할 수 있다. 인증 및 권한 부여 목적으로 사용되는 일종의 토큰이다.
가장 많이 사용하는 경우이다. 사용자가 로그인하면 이후 각 요청에 JWT가 포함되어 해당 토큰으로 허용된 경로, 서비스 및 리소스에 엑세스 할 수 있다.
최근에는 오버헤드가 적고 다양한 도메인에서 쉽게 사용할 수 있는 단일로그인(Single Sign On) 기능이 자주 사용된다.
오버헤드란?
: (프로그램 실행 흐름 도중 동떨어진 위치의 코드를 실행시켜야 할 때 추가적으로 시간,메모리,자원이 사용되는 현상 즉, 특정 기능을 수행하는데 드는 간접적인 자원)
JWT를 이용하여 회원 정보를 주고받게 되면 유저의 정보를 세션에 유지할 필요가 없게된다. 즉 stateless 한 서버를 만들 수 있도록 도와준다. 이전 방식은 브라우저와 서버의 세션 영역에 로그인 정보가 저장되어있는 statefull한 서버였다.
JWT 는 당사자간에 정보를 안전하게 전송하는 좋은 방법이다. 예를들면 JWT는 공개/개인 키쌍 을 사용하여 서명할 수 있기 때문에 보낸사람이 실제 당사자가 맞는지 확신할 수 있다. 또한 서명은 header 와 payload를 사용하여 계산되기 때무에 내용 변경 유무도 확인할 수 있다.
JWT는 헤더, 페이로드 및 서명의 세 부분으로 구성된다.
따라서 JWT는 일반적으로 xxxxx.yyyyy.zzzzz
와 같은 형식을 갖고있다.
Header 에는 일반적으로 토큰 유형과 사용중인 서명 해싱 알고리즘 이렇게 두 부분으로 구성된다.
{
"alg": "HS256",
"typ": "JWT"
}
이후 이 JSON 은 BASE64Url
로 인코딩되어서 Header 부분을 형성한다.'
Base 64인코딩이란?
: Binary 데이터를 텍스트(String)로 바꾸는 인코딩방식으로 char-set 에 영향받지 않는 ASCII 문자열로만 되어있는 텍스트로 바꾸는 일을 한다. (64진법)그리고 여기서 나온게
Base64Url
=> Url에는 path를 구분짓는 / 와 space를 의미하는 +문자가 있다. 이를 _ 기호와 - 기호로 수정하여 url에서 Base64 를 사용해도 문제가 발생하지 않게 된다.
두번째 파트는 Payload이다. 이 부분은 클레임, 데이터를 포함한다. 이 클레임은 Entity(일반적으로 사용자) 및 추가 데이터에 대한 설명이다. 이 클레임은 또 registered, public, private 세가지로 나뉜다. 전달하고자 하는 데이터라고 생각하면 편함.
필수사항은 아니지만 유용하고 상호간에 사용 가능한 클레임을 제공하기 위해 권장되는 사전에 정의된 클레임 집합이다. ex)iss(issuer), exp(expiration time), sub(subject), aud(audience) 등등..
사용하는 사람에 의해 맘대로 정의될 수 있다. 하지만 충돌을 방지하기 위해서는 IANA JSON Web Token Registry에 정의하거나 충돌을 방지하는 네임스페이스를 포함하는 url로 정의되어야한다.
사용에 동의하는 당사자간 정보를 교환하기 위해 공유되는 커스텀 클레임이다. (Registered도 아니고 Public 도 아님)
Payload 는 이런식으로 정의된다는 예시
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
signature 부분을 생성하려면 인코딩된 Header와 Payload, Header에 지정된 알고리즘이 필요하다.
예를들어 HMAC SHA256 알고리즘을 사용하기 위해서는 아래와 같은 방식으로 생성할 수 있다.
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
이러한 signature 은 전송 중에 토큰이 변조되지 않았는지 확인하는 데 사용된다. private key 로 서명된 토큰의 경우 JWT를 보낸 사람이 누구인지도 알 수 있다.
이런식의 암호화된 토큰 정보가 생성된다. 이를 풀면
요런식으로 정보를 알 수 있다.
보통 인증과정에서 사용자가 성공적으로 로그인하면 JSON 웹 토큰이 반환된다. 이렇게 반환된 토큰은 보안을 위해 필요한 것보다 오래 보관하면 안된다. 그리고 중요한 세션데이터를 로컬스토리지와 같은 브라우저 저장소에 저장하면 안된다.
사용자가 보호된 경로나 리소스에 접근할 때 일반적으로 Bearer
를 이용하여 Authorization header로 JWT를 전송한다.
Authorization: Bearer <token>
Path는 이러한 헤더에서 유효한 JWT인지 확인하고 유효한 경우 사용자는 무사히 접근할 수 있다. HTTP 헤더를 통해 JWT 토큰을 보내는 경우에는 크기가 너무 커지지 않게 주의해야한다. (일부 서버는 8KB를 초과할 수 없음)
JWT를 가져와 API 또는 정보에 접근하는 방식
- 어플리케이션이나 사용자가 Auth 서버에 권한을 요청한다.
- 권한요청이 승인되면 authorization 서버는 접근 토큰을 반환한다.
- 사용자는 이 토큰을 갖고 보호된 리소스에 접근할 수 있다.(ex. API)
다른 예시
1. 브라우저의 로그인 과정에서 회원 정보를 입력한다(id,pw ...)
2. 서버는 JWT를 생성한다.
3. 서버가 브라우저에게 JWT를 보낸다.
4. 브라우저는 JWT를 갖고 서버에게 데이터를 요청한다.
5. 서버는 서명을 확인하고 유저 정보를 클라이언트에게 제공한다.
결론적으로 JWT가 다른 방식(SWT, SAML 등)보다 편한 이유
- JSON은 XML보다 복잡하지 않기 때문에 인코딩할 크기도 작아지기 때문에 훨씬 컴팩트하다는 것에 있다.
- 2.보안적측면에서도 다른 방식보다 우수하고 간편하다.
- JSON 파서(parsers)는 객체에 직접 매핑되는 만큼 가장 많은 프로그래밍 언어에서 사용된다.
SAML방식과 비교해서 훨씬 보기편하고 간편함..
JWT 공식문서를 번역한 것이기 때문에 JWT가 왜 짱짱인지 나열한 것 같지만 결론적으로는 JWT는 독립형으로 설계되었으며 세션 데이터의 서버 측 스토리지가 필요하지 않으므로 분산 시스템에서 보다 확장 가능하고 사용하기 쉽다는 장점이 있다.
JWT는 일반적으로 웹 애플리케이션 및 API에서 클라이언트와 서버 간에 사용자 데이터를 안전하게 전송하는 수단으로 사용된다. 토큰은 서버에서 생성되어 저장되는 클라이언트로 전송되고 그런 다음 클라이언트는 각 후속 요청과 함께 토큰을 전송하여 서버가 사용자 이름과 암호를 계속 확인하지 않고도 사용자를 인증하고 권한을 부여할 수 있도록 도와준다.
JWT는 클라이언트와 서버가 통신할 때 권한부여를 위해서 사용하는 토큰이다.