📌 Json Web Token (JWT)
인증에 필요한 정보들을 암호화시킨 토큰
JSON Web Token (JWT) 은 웹 표준 (RFC 7519)으로서 두 개체에서 JSON 객체를 사용하여 가볍고 자가 수용적인 (self-contained) 방식으로 정보를 안전성 있게 전달하기 위한 방법이다.
self-contained (자가 수용적)
→ JWT는 필요한 모든 정보를 자체적으로 지니고 있다. 토큰에 대한 기본정보, 전달할 정보(유저 인증의 경우 유저 정보), 검증된 토큰임을 증명하는 signature를 포함하고 있다.
→ JWT는 자가 수용적이기 때문에 두 개체 사이에 손쉽게 전달할 수 있다. HTTP 통신에서 헤더에 넣어서 전달하거나, URL의 파라미터(쿼리), body 등 다양한 방식으로 전달할 수 있다.
ex. 유저 정보가 그대로 URL 파라미터로 전달된다면 안정성이 떨어지는 방법이다.
📌 JWT는 언제 사용할까?
1️⃣ 유저 인증
유저가 로그인하면, 서버는 유저의 정보에 기반한 토큰을 발급하여 유저에게 전달한다. 그 후, 유저가 서버에 요청할 때마다 JWT를 포함하여 전송한다. 요청을 받은 서버는 유효한 토큰인지 검증하고 유저가 해당 토큰으로 경로, 서비스, 리소스에 접근할 수 있다.
2️⃣ 정보 교환
JWT는 정보가 sign 되어있기 때문에 전달되는 데이터가 위, 변조되었는지 검증할 수 있어 두 개체 사이에서 안정성 있게 정보를 교환하기에 좋은 방법이다. (sign 되었다는 건 해당 토큰이 서버에서 정상적으로 발급된 토큰임을 증명하는 signature를 지니고 있다는 뜻)
📌 JWT 구조
JWT는 세 부분으로 나누어지며, 각 부분은 점( . )을 구분자로 xxxxx.yyyyy.zzzzz 이런 식으로 표현된다. 순서대로 헤더(Header), 페이로드(Payload), 서명(Sinature)으로 구성된다.
Base64 인코딩의 경우 “+”, “/”, “=”이 포함되지만 JWT는 URI에서 파라미터로 사용할 수 있도록 URL-Safe 한 Base64url 인코딩을 사용한다.
1️⃣ 헤더 (Header)
Header는 토큰의 타입과 해시 암호화 알고리즘으로 구성되어 있다.
{
"alg" : "HS256", // 해쉬 암호화 알고리즘
"typ" : "JWT" // 토큰의 타입
}
2️⃣ 페이로드 (Payload)
Payload는 토큰에 담을 클레임(claim) 정보를 포함하고 있다. 여기에 담는 정보의 한 ‘조각’을 클레임이라고 부르고, 이는 name / value의 한 쌍으로 이루어져 있다. 토큰에는 여러 개의 클레임 들을 넣을 수 있다.
클레임의 정보는 등록된 (registered) 클레임, 공개 (public) 클레임, 비공개 (private) 클레임으로 세 종류가 있다.
2-1 등록된 (registered) 클레임
서비스에 필요한 정보들이 아닌 토큰에 대한 정보들을 담기 위하여이미 정의된 클레임들로 필수는 아니지만 권장한다. 등록된 클레임의 사용은 모두 선택적 (optional)
iss (토큰 발급자), sub (토큰 제목), aud (토큰 대상자), iat (토큰 발급 시간), exp (토큰 만료시간) 등이 있다.
2-2 공개 (public) 클레임
JWT를 사용하는 사람들에 의해 정의되는 클레임이다. 충돌을 방지하기 위해 URI , UUID, 이메일 형식으로 정의한다.
2-3 비공개 (private) 클레임
두 개체 간에 정보를 공유하기 위해 사용되는 클레임, key가 중복될 수 있으니 유의해야 한다.
{
"sub": "1234567890", // registered
"https://hanwoo.com": true, // public
"name": "Hanwoo", // private
"admin": true // private
}
3️⃣ 서명 (Signature)
Signature는 Base64 방식으로 인코딩한 Header, payload 그리고 SECRET KEY로 해시를 하여 생성한다.
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
JWT는 서명에 의해 변조되지 않았음을 증명할 수 있지만, Header와 Payload는 인코딩 될 뿐(16진수로 변경), 따로 암호화되지 않는다. 따라서 JWT 토큰의 header와 payload를 디코딩하여 데이터를 확인할 수 있기 때문에 비밀번호와 같은 민감한 정보를 넣지 않도록 주의해야 한다.
그러나 Signature는 SECRET KEY를 알지 못하면 복호화할 수 없다.
예를 들어, A 사용자가 B 사용자의 토큰 payload 부분을 수정하고 서버로 전송하면 서버는 기존의 Verify Signature와 다른 payload를 기반으로 서명이 됐음을 감지하고 유효하지 않은 토큰으로 간주한다. 때문에 A 사용자는 SECRET KEY를 알지 못하면 토큰을 조작할 수 없다.
생성된 토큰은 HTTP 통신을 할 때 Authorization이라는 key의 value로 사용된다. 일반적으로 value에는 Bearer이 앞에 붙여진다.
{
"Authorization": "Bearer <token>",
}
JWT 장점
stateless 적합 : 토큰은 클라이언트 사이드에 저장되므로 stateless 기반 서비스에 적합하다.
참고
https://tansfil.tistory.com/58?category=475681
'TIL' 카테고리의 다른 글
REST API + RESTful API (0) | 2023.05.02 |
---|---|
'module' is not defined. eslint (0) | 2023.05.01 |
[TIL] git remote update (0) | 2021.10.24 |
[TIL] npm package의 @ 접두사는 뭐지..? (0) | 2021.10.22 |
[TIL] cookie와 session (0) | 2021.10.04 |