[node.js] JWT(JSON Web Token)을 jsonwebtoken 라이브러리로 사용하기
2023년 01월 27일
JWT(JSON Web Token) 설명
JWT(JSON Web Token)는 당사자 간에 정보를 JSON 개체로 안전하게 전송하기 위한 간결하고
독립적인 방법을 정의하는 개방형 표준( RFC 7519 )입니다. 이 정보는 디지털 서명되어 있으므로 확인하고
신뢰할 수 있습니다. JWT는 비밀( HMAC 알고리즘 포함) 또는 RSA 또는 ECDSA 를 사용하는
공개/개인 키 쌍을 사용 하여 서명할 수 있습니다.
JWT와 비슷한 세션이 있는데 세션은 서버에서 제어되기 때문에 서버에 부담이 갈수 있습니다.
하지만 JWT는 클라이언트가 토큰을 가지고 있다가 요청시 HTTP 헤더에 토큰을 첨부함으로
해당 유저가 권한을 가지고 있다고 판단을 내릴수가 있습니다.
토큰의 구성 요소
또한 JWT의 토큰은 3가지로 구성이 되어있습니다. Header / PayLoad / Signature
Header에는 암호화 알고리즘 정보와 해당 토큰의 타입이 들어있습니다.
PayLoad에는 토큰을 생성할 당시에 집어넣은 문자열 or 객체 or Buffer 정보가 들어있습니다.
Signature에는 개인 키로 서명한 전자서명이 담겨있습니다.
JWT사용 흐름
-
클라이언트에서 유저가 email, password로 서버로 요청을 보냅니다.
-
서버가 JWT 토큰을 생성 한 후 클라이언트한테 응답을 돌려줍니다.
-
클라이언트가 서버에 요청을 보낼 때 Header에 토큰을 포함합니다.
-
서버가 토큰을 검증 성공 시에만 요청을 처리합니다.
node.js에서의 JWT구현
설치
npm i jsonwebtoken
Encoded(암호화)
const jwt = require("jsonwebtoken");
const token = jwt.sign(
{ userId: "12345", email: "kagrin97@gmail.com" },
"secret_key",
{ expiresIn: "1h" }
);
sign
메소드로 토큰을 생성하는데 첫 번쨰 인자는 페이로드에 넣을 문자열, 객체, 버퍼 중 하나입니다.
두 번쨰 인자는 개인 키로 나중에 복호화 할 때도 필요한 중요한 정보입니다.
세 번쨰 인자는 옵션으로 여러 가지가 있지만 expiresIn은 토큰 만료 시간을 설정할 수 있습니다.
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiIxMjM0NSIsImVtYWlsIjoia2FncmluOTdAZ21haWwuY29tIiwiaWF0IjoxNjc0Nzg1Mjk5LCJleHAiOjE2NzQ3ODg4OTl9.SVuZVyO0PmOUqDTY6otf1z5rpmpBpAn6oGtH1eMhkRA
생성된 토큰으로 .을 기점으로 3가지의 정보인 Header / PayLoad / Signature가
Base64로 암호화되어있습니다.
Decoded(복호화)
jwt.verify(token, "secret_key", function (err, decoded) {
console.log(decoded);
// {
// userId: '12345',
// email: 'kagrin97@gmail.com',
// iat: 1674784695, 시작 시간 (issued at)
// exp: 1674788295 만료 시간 (Expiration)
// }
});
verify
메소드로 복호화를 진행합니다. 첫 번째 인자는 토큰이며 두 번째 인자는 개인 키입니다.
세 번째 인자로 콜백함수를 사용할 수 있는데 err, decoded가 순서대로 가져올 수 있습니다.
저의 경우 토큰 생성 시 1시간을 만료 시간으로 잡았기 때문에 iat + 3600초를 더하면
exp 값이 됩니다. decoded에 해당 정보가 들어있고요.
토큰을 Header에 포함할 때
요청 시 header에 포함할 때도 사람들이 정한 protocol이 존재합니다.
Authorization: <type> <credentials>
타입과 해당 타입에 맞는 증명입니다.
토큰은 종류가 많아서 다양한 토큰을 처리하기 위해서 type에도 종류가 많습니다.
토큰을 Header에 포함할 때의 type
-
Basic : 사용자 아이디와 암호를 Base64로 인코딩한 값을 토큰으로 사용합니다. (RFC 7617)
-
Bearer : JWT 혹은 OAuth에 대한 토큰을 사용합니다. (RFC 6750)
-
Digest : 서버에서 난수 데이터 문자열을 클라이언트에 보냅니다. 클라이언트는 사용자 정보와 nonce를 포함하는 해시값을 사용하여 응답합니다. (RFC 7616)
-
HOBA : 전자 서명 기반 인증방식입니다. (RFC 7486)
-
Mutual : 암호를 이용한 클라이언트-서버 상호 인증입니다.
JWT에는 Bearer를 사용하며 credentials에는 토큰 자체를 포함하는 방법을 사용합니다.
Authorization: Bearer <token>
참고 문서
https://jwt.io/introduction/
https://jwt.io/#debugger-io