JWT(JSON Web Token) 개요
두 개체에서 JSON 객체를 사용하여 가볍고 자가수용적인(self-contained) 방식으로 정보를 안전성 있게 전달해준다.
회원인증, 정보 교류와 같은 상황에서 사용된다.
JWT는 .을 구분자로 3가지 문자열로 되어있다.
헤더(Header)
헤더는 두 가지 정보를 가지고 있다.
- typ : 토큰의 타입을 지정한다.
- alg : 해싱 알고리즘을 지정한다. 일반적으로 HMAC SHA256 또는 RSA가 사용되며, 토큰 검증 시 signature 부분에서 사용된다.
ex. 예제 헤더
const header = {
"typ": "JWT",
"alg": "HS256"
};
정보(payload)
payload 부분에는 토큰에 담을 정보가 들어 있다.
여기에 담는 정보의 한 '조각'을 클레임(claim) 이라고 부르고, 이는 name/value의 한 쌍으로 이뤄져 있다.
클레임의 종류는 크게 세가지가 있다.
등록된(registered) 클레임 : 서비스에 필요한 정보가 아닌, 토큰에 대한 정보를 담기위해 이름이 이미 정해진 클레임들이다.
- iss : 토큰 발급자(issuer)
- sub : 토큰 제목(subject)
- aud : 토큰 대상자(audience)
- exp : 토큰 만료시간(expiration), 시간은 NumericDate 형식으로 되어 있어야한다.
- nbf : Not Before를 의미, 이 날짜가 지나기 전까지는 토큰이 처리되지 않는다. NumericDate 형식으로 되어 있어야한다.
- iat : 토큰이 발급된 시간(issued at), 이 값을 사용하여 토큰의 age가 얼마가 되었는지 판단할 수 있다.
- jti : JWT의 고유 식별자로서, 주로 중복적인 처리를 방지하기 위하여 사용된다. 일회용 토큰에 사용하면 유용하다.
공개(public) 클레임 : 충돌이 방지된(collision-resistant) 이름을 가지고 있어야하고 URI 형식으로 이름을 짓는다.
{
"https://pupbani.com/jwt_claims/is_admin": true
}
비공개(private) 클레임 : 양 측간에 협의하에 사용되는 클레임 이름들이다. 이름이 중복되거나 충돌이 될 수 있으니 사용할 때 유의해야한다.
{
"username" : "pupbani"
}
ex. 예제 Payload
const payload = {
"iss": "pupbani.com",
"exp": "1485270000000",
"https://pupbani.com/jwt_claims/is_admin": true,
"userId": "11028373727102",
"username": "pupbani"
}
서명(signature)
헤더의 인코딩값과, 정보의 인코딩값을 합친후 주어진 비밀키로 해쉬를 하여 생성한다.
서명 부분을 만드는 슈도코드(pseudocode)의 구조는 다음과 같다.
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
이렇게 만든 해쉬를, base64 형태로 나타내면 된다.(hex -> base64 인코딩을 해야한다.)
ex. Node.js에서 인코딩하기
const header = {
typ: "JWT",
alg: "HS256",
};
// encode to base64
const encodedHeader = Buffer.from(JSON.stringify(header))
.toString("base64")
.replace("=", "");
console.log(encodedHeader, "\n");
const payload = {
iss: "pupbani.com",
exp: "1485270000000",
"https://pupbani.com/jwt_claims/is_admin": true,
userId: "11028373727102",
username: "pupbani",
};
// encode to base64
const encodedPayload = Buffer.from(JSON.stringify(payload))
.toString("base64")
.replace("=", "");
console.log(encodedPayload, "\n");
// Hash
const crypto = require("crypto");
const signature = crypto
.createHmac("sha256", "secret")
.update(encodedHeader + "." + encodedPayload)
.digest("base64")
.replace("=", "");
console.log(signature, "\n");
console.log("JWT : " + encodedHeader + "." + encodedPayload + "." + signature);
jwt 디버거로 한번 확인해보자.
확인해보니 제대로 만들어지고 검증도 제대로되었다. 이제 앞으로는 토큰 인증 방식을 사용할 때 JWT를 사용해 웹 서비스를 만들어보자.
'Back-end & Server > Node.js' 카테고리의 다른 글
[Node.js] 토큰(Token) 기반 인증 (0) | 2023.08.01 |
---|---|
[Node.js] 자주 쓰는 의존성 패키지 (0) | 2023.07.31 |
[Node.js] Express.js (0) | 2023.07.31 |
[Node.js] 클라이언트 (0) | 2023.07.30 |
[Node.js] Event Loop (0) | 2023.07.29 |