본문 바로가기

Back-end & Server/Node.js

[Node.js] JWT

728x90
반응형

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.IO

JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties.

jwt.io

확인해보니 제대로 만들어지고 검증도 제대로되었다. 이제 앞으로는 토큰 인증 방식을 사용할 때 JWT를 사용해 웹 서비스를 만들어보자.

728x90
반응형

'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