JWT 토큰을 이용해 로그인된 사용자를 확인하는 기능 개발이 필요해서 정리!
먼저, JWT가 뭔지 알아야 할 것 같아 정리 해 봤다
JWT는
Json Web Token
의 약자로 일반적으로 클라이언트와 서버 사이에서 통신할 때 권한을 위해 사용하는 토큰이다. 웹 상에서 정보를 Json형태로 주고 받기 위해 표준규약에 따라 생성한 암호화된 토큰으로 복잡하고 읽을 수 없는 string 형태로 저장되어있다.
JWT에 대해서는 나중에 자세히 정리를 해 봐야 할 것 같음
일단 토큰 발급 기능을 구현하기 위해,
다음과 같은 모듈을 다운받아줬다.
npm i jsonwebtoken
JWT 토큰 방식을 사용하기 위해서는 해당 모듈을 설치 해 줘야 한다~~~
(JWT 토큰 방식 활용을 위해서는 시크릿키를 선언 해 줘야 하니, dotenv 모듈도 설치 해 줘야 한다.)
이제 다음으로는 토큰사용을 위한 middleware를 개발 해 줬다.
나는 middleware 파일 생성 후, auth.js 라는 파일을 추가해서 토큰 검증 코드를 넣어줬다.
const jwt = require('jsonwebtoken');
require("dotenv").config();
exports.verifyToken = async (req, res, next) => {
try {
const token = req.headers.authorization.split('Bearer ')[1];
let jwtSecret = process.env.JWT_SECRET_KEY;
const jwtValue = jwt.verify(token, jwtSecret);
req.decoded = jwtValue;
req.decoded.success = true;
req.userId = jwtValue.used_id;
return next();
} catch (err) {
console.error(err);
// sendError(err);
if (err.name == 'TokenExpiredError') {
return res.status(419).json({success: false, code: "E01", message : "token 만료"});
}
return res.status(401).json({success: false, code: "E01", message : "token이 유효하지 않습니다."});
}
}
일단 jsonwebtoken 모듈
사용을 위해 선언 해 줬고,
JWT 토큰 방식을 이용하기 위해서는 .env
파일 내에 JWT_SECRET_KEY
를 선언 해 줘야 한다.
나는 JWT_SECRET_KEY 형식에 맞춰 직접 선언 해 줬다.
일단 해당 방식을 이용해서 토큰 검증 코드를 심어줬으니,
이제 토큰 발급 코드부터 차례로 만들어서 토큰 검증 테스트까지 해주면 된다.
exports.memberLogin = async function (req, res, next) {
let result = {};
try {
const token = jwt.sign({
user_id: "user_id",
email: "email"
}, process.env.JWT_SECRET_KEY, {
expiresIn: '15m', // 유효기간 15분 => 15분 이후 토큰이 재발급 됨
issuer: 'test',
});
return res.status(200).json({
resultCode: 200,
message: "토큰 발행, 로그인 성공",
token, // 발행된 jwt 토큰
})
}catch (err) {
console.error("memberLogin error:", err);
return res.status(400).json(err);
}
};
사용자가 로그인 할 경우 토큰생성을 하는 기능 구현을 위해, controller에 다음과 같은 소스코드를 추가했다.
route에는 post 방식으로 따로 선언해줌!
일단 지금은 테스트를 위해 하드코딩으로 선언 해 줬지만,
추후에는 user_id와 email을 직접 입력 받아서 토큰을 생성 해 주도록 수정해야한다.
일단 테스트를 위해 user_id와 email을 임의로 선언 해 주고,
토큰 유효기간을 15분으로 설정 후 토큰 발급을 진행해줌
이걸 postman으로 테스트 해 주면
이런식으로 토큰 발행이 성공 했다는 return 값과 함께
token값을 떨어트려준다 ㅎㅎ
이제 이 값을 이용해서 인증을 해 주면 됨!
router.js 코드
const { verifyToken } = require("../middleware/auth");
router.get("/verifyMember", verifyToken, loginControllerV1.verifyMember);
controller.js 코드
exports.verifyMember = async function (req, res, next) {
let result = {};
const user_id = 'user_id';
try {
if (user_id == req.decoded.user_id) {
res.status(200).json({
resultCode: 200,
message: "인증 성공"
});
}
}catch (err) {
console.error("verifyToken error:", err);
return res.status(400).json(err);
}
};
contoller와 router에 코드를 다음과 같이 추가 해줬다.
auth.js라는 미들웨어를 사용하고 있기 때문에 router에는 위와 같이 선언도 필요하다!
이제 verifyMember 코드를 보면,
일단 지금은 테스트를 위해 user_id를 하드코딩 해 줬지만
나중에는 직접 입력 받은 값으로 처리해줘야함!!
그리고 verifyToken 소스코드 부분인
const token = req.headers.authorization.split('Bearer ')[1];
이 부분도 token은 일단 하드코딩으로 넣어줬다.
이제 테스트를 해 보면
이건 정상 상태고
유효기간으로 설정해둔 15분이 만료되면 이렇게 나온다
참고로 나는 토큰 인증을 하려 하는데,
다음과 같은 에러가 계속 떨어졌다.
Right-hand side of 'instanceof' is not an object
확인 해 보니 jsonwebtoken
패키지의 버전 9.0.0이 노드버전 11 이하를 지원하지 않는다고 한다.
내 노드 버전을 확인 해 보니 10버전대로 설정되어있어서,
16버전으로 노드 버전을 올려주니 정상적으로 작동되었다.
참고로, 노드 버전 업데이트가 어려운 상황일 경우 jsonwebtoken
버전을 다운그레이드해서 해결하는 경우도 있는 것 같다.
하지만 계속 이렇게 할 수는 없으니 노드버전을 올려주는게 좋을 것 같음!!