JWT 적용하기
1. JWT 토큰이 뭐야?
- Json Web Token
- JSON 객체를 사용하여 가볍고 자가수용적인 (self-contained: 필요한 모든 정보를 자체적으로 지님) 방식으로 정보를 안전성 있게 전달하는 Web Token
- 유저 인증을 하는 토큰을 클라이언트의 쿠키에 저장할건데, 쿠키는 노출이 쉬우므로 민감한 데이터가 담겨 있으면 안된다.
- 따라서 jwt 토큰을 활용하여 암호화된 토큰을 발급하는 것✨
JWT 구조
aaaaa.bbbbb.ccccc 세 부분으로 이루어져 있다.
- header : type(토큰의 타입), alg(해싱 알고리즘)
- payload : 토큰에 담을 정보 (iss, sub, exp …)
- signature : 토큰을 인코딩하거나 유효성 검증을 할 때 사용하는 고유한 암호화 코드 signature 는 header와 payload의 값을 각각 BASE64로 인코딩하고,
인코딩한 값을 비밀 키를 이용하여 header에서 정의한 알고리즘으로 해싱한 후,
이 값을 다시 BASE64로 인코딩하여 생성한다.
JWT 단점
- 모든 사용자들의 상태를 기억하고 있지 않다.
- 이미 발급한 토큰을 뺏을 수 없다.
- 따라서 해커에게 토큰이 빼앗겼다면 무효화할 수 없다.
단점 해결법
- accessToken, refreshToken 2개를 발급해준다.
- accessToken : 유효 기간이 짧다. (3h)
- refreshToken : 유효 기간이 길다. (보통 2주)
- 로그인시 accessToken, refreshToken을 발급해주고, accessToken 만료 시, refreshToken이 유효하면 accessToken을 재발급해준다.
2. JWT 적용하기
JWT 설치 및 세팅
npm install --save jsonwebtoken
해당 명령어를 통해 jsonwebtoken 을 설치하자.
config/jwt.js
const jwtConfig = {
secretKey: process.env.JWT_ACCESS_SECRET,
refeshSecretKey: process.env.JWT_REFRESH_SECRET,
option: {
algorithm: 'HS256',
expiresIn: process.env.JWT_ACCESS_TIME,
issuer: 'movester',
},
refeshOption: {
algorithm: 'HS256',
expiresIn: process.env.JWT_REFRESH_TIME,
issuer: 'movester',
}
};
header, payload, signature에 담을 데이터 옵션을 세팅해놓는다.
secretKey는 보안에 직결되므로 env 변수를 활용하였다.
accessToken은 expiresIn을 짧게, refreshToken은 길게 설정한다.
JWT 토큰 발급
modules/jwt.js
const signAccessToken = async user => jwt.sign(user, jwtConfig.secretKey, jwtConfig.option);
jwt 관련 메소드를 재사용하기 위해 modules 폴더에 별도로 분리하였다.
service/admin.js
const jwt = require('../modules/jwt');
//login logic ...
const token = {
accessToken: await jwt.signAccessToken({ idx: admin.admin_idx, email: admin.email }),
refreshToken: await jwt.signRefreshToken({ idx: admin.admin_idx, email: admin.email }),
};
jwt.sign(payload, secretKey, [options])
jwt는 sign 함수로 토큰을 발급받는다.
나는 payload로 idx, email 값을 주었다. (토큰 decode시 유저의 idx, email 얻기 위해)
JWT 토큰 검증
modules/jwt.js
const verifyAccessToken = async token => {
try {
return jwt.verify(token, jwtConfig.secretKey);
} catch (err) {
console.log('token invalid');
}
};
jwt.verify(toekn, secretKey)
jwt는 verify 함수로 토큰을 검증한다.
middleware/auth.js
const accessToken = await jwt.verifyAccessToken(req.cookies.accessToken);
verify되어 나온 결과값을 담은 accessToken은 유효한 토큰이었다면,
{
idx: 8,
email: 'minsung',
iat: 1643200950,
exp: 1643204550,
iss: 'movester'
}
다음과 같이 토큰을 발급할 때 입력한 payload를 준다.
유효하지 않은 토큰이라면, undefined를 준다. (try-catch문에서 err로 평가되므로 주의하자.)
지금까지 jwt 가 무엇이고, node 환경에서 어떻게 토큰을 발급받고 검증하는지를 알아보았다.
다음에는 accessToken과 refreshToken을 활용하는 방법에 대해 알아보자.🏋️♂️