JWT(Json Web Token)을 생성하고 검증할 수 있는 기능을 제공하는 라이브러리이다.
npm install jsonwebtoken
const jwt = require("jsonwebtoken");
const payload = {
nickname: "cloudcoke",
email: "cloudcoke.dev@gmail.com",
};
const salt = "cloudcoke";
const token = jwt.sign(payload, salt);
console.log(token);
// eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuaWNrbmFtZSI6ImNsb3VkY29rZSIsImVtYWlsIjoiY2xvdWRjb2tlLmRldkBnbWFpbC5jb20iLCJpYXQiOjE2Nzg0NTEwMzZ9.S81V0lN6cnqPAMpQFr40Mmn4r0BlrNNF5Y6RUY4z-9Y
키파일 생성
const crypto = require("crypto");
const fs = require("fs");
// Generate RSA key pair
const { privateKey, publicKey } = crypto.generateKeyPairSync("rsa", {
modulusLength: 2048,
publicKeyEncoding: {
type: "spki",
format: "pem",
},
privateKeyEncoding: {
type: "pkcs8",
format: "pem",
},
});
fs.writeFileSync("private.pem", privateKey);
fs.writeFileSync("public.pem", publicKey);
JWT 생성
const fs = require("fs");
const privateKey = fs.readFileSync("private.pem");
const token = jwt.sign(payload, privateKey, { algorithm: "RS256" });
console.log(token);
// eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJuaWNrbmFtZSI6ImNsb3VkY29rZSIsImVtYWlsIjoiY2xvdWRjb2tlLmRldkBnbWFpbC5jb20iLCJpYXQiOjE2Nzg0NTYxMjN9.cP6Rs1sjc63QkGltv8AIuaCzLpy2_vdNudxkLXC2C9gcTCFli6yIgEHa_glegmuIbF4kriZEC627dGe5m8qlUovbo34QyWTpljdOnB18wrPgs1khP2iK0YKObYRr00gacTl6zQemaGLx4H6HwY9XlAtqG8oHEskJwhbyaLvm6HniR46FtxmllnmZPXYIsX87IqGoS9KvwOFwnTpjOQCccFeDb4iY5RfmVbvtyC4HlGGbH8rwXe7uuJn95IeoFR6P6XOM05Po5RiWX0VfmarjkiiwafFwU46u1Dzvbj81pZ3CN0n_NZPF9xRstc87wTZ6MpQAqCnQodVCtQ0_KG33TA
const token = jwt.sign({ ...payload, exp: Math.floor(Date().now / 1000) + 60 * 60 }, salt);
const token = jwt.sign(payload, salt, { expiresIn: 60 * 60 });
const token = jwt.sign(payload, salt, { expiresIn: "1h" });
expiresIn
60
: 60초 후, '2 days'
/ '2d'
: 2일 뒤, '10h'
: 10시간 뒤issuer
: 토큰 발급자를 의미한다. (iss)subject
: 토큰 제목을 의미한다. (sub)audience
: 토큰 수신자를 의미한다. (aud)expiresIn
: 토큰 만료 시간을 의미한다. (exp)notBefore
: 토큰 활성 날짜를 의미한다. [이 날짜 이전의 토큰은 승인되어서는 안됨 ] (nbf)iat
: 토큰 발급 시간을 의미한다.jwtid
: JWT 토큰 고유 식별자를 의미한다. [issuer가 여러명일 때 구분하기 위해] (jti)const token = jwt.sign(payload, salt, { subject: "sample" });
// eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuaWNrbmFtZSI6ImNsb3VkY29rZSIsImVtYWlsIjoiY2xvdWRjb2tlLmRldkBnbWFpbC5jb20iLCJpYXQiOjE2Nzg0NzE0MTAsInN1YiI6InNhbXBsZSJ9.i-4evt7oSORHlnS08Hf9p3jCVxO8WP3F_U28heIrJX0
const jwt = require("jsonwebtoken");
const payload = {
nickname: "cloudcoke",
email: "cloudcoke.dev@gmail.com",
};
const salt = "cloudcoke";
const token = jwt.sign(payload, salt);
const decode = jwt.verify(token, salt);
console.log(decode);
/*
{
nickname: 'cloudcoke',
email: 'cloudcoke.dev@gmail.com',
iat: 1678465847
}
*/
const token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuaWNrbmFtZSI6ImNsb3VkY29rZSIsImVtYWlsIjoiY2xvdWRjb2tlLmRldkBnbWFpbC5jb20iLCJpYXQiOjE2Nzg0NTY3OTUsImV4cCI6MTY3ODQ2MDM5NX0.9LsHQ1427UjYQAEg7K_DMOKayR6VAw52HNdPolhFfmE";
try {
const decode = jwt.verify(token, salt);
console.log(decode);
} catch (e) {
console.log(e.name);
console.log(e.message);
console.log(e.expiredAt);
}
/*
TokenExpiredError
jwt expired
2023-03-10T14:59:55.000Z
*/
jwt expired
오류를 반환해 준다.const decode = jwt.verify(token, salt, { complete: true });
console.log(decode);
/*
{
header: { alg: 'HS256', typ: 'JWT' },
payload: {
nickname: 'cloudcoke',
email: 'cloudcoke.dev@gmail.com',
iat: 1678469386
},
signature: 'dahdXOrj2BEO_hOegr-oMOUz_KKIPQCAdv8fYlDSgas'
}
*/
header
, payload
, signature
를 모두 복호화해서 반환해 준다.const fs = require("fs");
const privateKey = fs.readFileSync("private.pem");
const publicKey = fs.readFileSync("public.pem");
// const token = jwt.sign(payload, salt);
const token = jwt.sign(payload, privateKey, { algorithm: "RS256" });
// 인증을 할 때 공개키를 사용
const decode = jwt.verify(token, publicKey, { algorithms: "RS256" });
console.log(decode);
{ algorithms: ["RS256", "RS384"] }
처럼 배열로 작성해주면 된다.const token = jwt.sign(payload, salt, { subject: "sample" });
try {
const decode = jwt.verify(token, salt, { subject: "sample" });
console.log(decode);
} catch (e) {
console.log(e.name);
console.log(e.message);
}
// subject 값이 'sample'이라면
/*
{
nickname: 'cloudcoke',
email: 'cloudcoke.dev@gmail.com',
iat: 1678473285,
sub: 'sample'
}
*/
// subject 값이 'sample'이 아니라면
/*
JsonWebTokenError
jwt subject invalid. expected: sample
*/
const decoded = jwt.decode(token);
console.log(decoded);
/*
{
nickname: 'cloudcoke',
email: 'cloudcoke.dev@gmail.com',
iat: 1678473708
}
*/
const decoded = jwt.decode(token, { complete: true });
console.log(decoded);
/*
{
header: { alg: 'HS256', typ: 'JWT' },
payload: {
nickname: 'cloudcoke',
email: 'cloudcoke.dev@gmail.com',
iat: 1678474857
},
signature: '7ATHWfzG2LglV4eR7InYxfJOXECia0BKbRv2u7Ua92A'
}
*/
header
, payload
, signature
를 모두 반환한다.jwt expired
: 토큰의 만료되었을 경우 발생한다.invalid token
: 토큰의 header 또는 payload 값을 분석할 수 없을 경우 발생한다. JWT 토큰이 올바른지 비밀 키가 올바른지 확인해 봐야 한다.jwt malformed
: 토큰 형식이 올바르지 않을 경우 발생한다. 토큰에 header, payload, signature가 존재하는지와 .
으로 구분되어 있는 되어 있는지 확인해 봐야 한다.jwt signature is required
: verify() 메서드를 사용 시 토큰에 signature가 존재하지 않거나 잘못되었을 경우 발생한다. 토큰에 signature가 존재하는지 또는 올바른지 확인해 봐야 한다.invalid signature
: 토큰의 signature가 올바르지 않을 경우 발생한다.jwt audience invalid. expected: [OPTIONS AUDIENCE]
: verify() 메서드 사용시 토큰의 payload에 audience claim 값이 없거나 옵션에 지정한 값과 일치하지 않을 경우 발생한다.jwt issuer invalid. expected: [OPTIONS ISSUER]
: verify() 메서드 사용시 토큰의 payload에 iss claim 값이 없거나 옵션에 지정한 값과 일치하지 않을 경우 발생한다.jwt id invalid. expected: [OPTIONS JWT ID]
: verify() 메서드 사용시 토큰의 payload에 jti claim 값이 없거나 옵션에 지정한 값과 일치하지 않을 경우 발생한다.jwt subject invalid. expected: [OPTIONS SUBJECT]
: verify() 메서드 사용시 토큰의 payload에 sub claim 값이 없거나 옵션에 지정한 값과 일치하지 않을 경우 발생한다.jwt not active
: verify() 메서드 사용시 nbf claim 값이 현재 시간보다 이전인 경우 발생한다.