[Node.js] JWT를 이용해 토큰 발급하기

이애옹·2024년 7월 3일
0
post-thumbnail
post-custom-banner

JWT 토큰을 이용해 로그인된 사용자를 확인하는 기능 개발이 필요해서 정리!

📌 JWT란?

먼저, JWT가 뭔지 알아야 할 것 같아 정리 해 봤다

JWT는 Json Web Token의 약자로 일반적으로 클라이언트와 서버 사이에서 통신할 때 권한을 위해 사용하는 토큰이다. 웹 상에서 정보를 Json형태로 주고 받기 위해 표준규약에 따라 생성한 암호화된 토큰으로 복잡하고 읽을 수 없는 string 형태로 저장되어있다.

JWT에 대해서는 나중에 자세히 정리를 해 봐야 할 것 같음

📌 JWT 토큰 인증 기능 구현하기

📝 모듈 설치하기

일단 토큰 발급 기능을 구현하기 위해,
다음과 같은 모듈을 다운받아줬다.

npm i jsonwebtoken

JWT 토큰 방식을 사용하기 위해서는 해당 모듈을 설치 해 줘야 한다~~~
(JWT 토큰 방식 활용을 위해서는 시크릿키를 선언 해 줘야 하니, dotenv 모듈도 설치 해 줘야 한다.)

📝 토큰 인증 middleware 생성하기

이제 다음으로는 토큰사용을 위한 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 에러 발생

참고로 나는 토큰 인증을 하려 하는데,
다음과 같은 에러가 계속 떨어졌다.

Right-hand side of 'instanceof' is not an object

확인 해 보니 jsonwebtoken 패키지의 버전 9.0.0이 노드버전 11 이하를 지원하지 않는다고 한다.
내 노드 버전을 확인 해 보니 10버전대로 설정되어있어서,
16버전으로 노드 버전을 올려주니 정상적으로 작동되었다.

참고로, 노드 버전 업데이트가 어려운 상황일 경우 jsonwebtoken 버전을 다운그레이드해서 해결하는 경우도 있는 것 같다.
하지만 계속 이렇게 할 수는 없으니 노드버전을 올려주는게 좋을 것 같음!!

👀 참고자료

profile
안녕하세요
post-custom-banner

0개의 댓글