잡다한 사전

(2023.11.13) Middleware로 사용자 인증하기 본문

프로그래밍 언어/Javascript & firebase

(2023.11.13) Middleware로 사용자 인증하기

잡사전집사 2023. 11. 14. 19:13
반응형

이번에는 Middleware를 이용해서 jwt를 이용하여 발급한 token을 가지고 사용자 인증을 하는 Middleware를 만들어보려고해요. 

 

1. MiddleWare란

//../middleware.js

module.exports = async (req, res, next) => {
const { authorization } = req.headers;

console.log(authorization);
};
// app.js

const middleware = require("../../middleware.js");

app.get("/", middleware, (req,res) => {
	res.send("middleware");
});

 

위 코드에서 "/"를 호출 GET 방식으로 호출을 했을 시 middleware가 실행되게 한 것을 볼 수 있습니다.

middleware는 HTTP 요청과 응답 사이에서 단계별 동작을 수행해주는 함수라고 말씀드릴 수 있습니다. 

 

2. JWT(jsonwebtoken)을 이용하여 로그인을 진행시 토큰을 발급하기

// 본 코드에서는 비밀번호, 아이디 등 유효성 검사는 제외하겠습니다.

// DB Users models 가져오기
const { Users } = require("../models");

// jwt require
const jwt = require("jsonwebtoken") // 사용하기 위해서는 npm i jsonwebtoken으로 설치

router.post("/auth", async (req, res) => {
	//입력받은 아이디와 비밀번호를 req.body에서 가져온다.
    const { email, password } = req.body;
    
    //입력받은 이메일이 DB에 등록되어있는 것을 찾아준다.
    const user = await Users.findOne({
    	where: {
        	email,
            },
        });
   
   const token = jwt.sign(
   	{ userId: user.userId },
    process.env.SECRET_TOKEN, // 시크릿 값은 dotenv를 이용해서 환경변수에 넣어주었습니다. 
    {
    	expiresIn:"12h",  //유효기간은 12시간으로 설정했습니다.
    }
};

res.header("Authorization", `Bearer ${token}` ); // header 부분에 생성받은 토큰 값을 넣어줍니다.

});

 

위 코드에서는 로그인을 위해 이메일과 비밀번호를 입력할 경우 (유효성 검사 코드는 제외하였습니다.)  jwt를 이용하여 토큰을 생성하여 header에 발급받은 토큰을 Authorization으로 넣어주도록 하였습니다.

 

(Authorization에서 `Bearer ${token}`으로 값을 넣어준 것은 Bearer 타입에 토큰인 것을 인증하기 위해서 Bearer 토큰인 것을 인증하기위해서 넣었습니다.)

 

고민..

Bearer 토큰인 것을 cookie 값으로 받으면 Bearer 타입에 토큰인 것을 알 수 있는데 이 부분을 Bearer 토큰이라는 것을 정해두고 토큰을 받아서 인증을 하는 것인지, 아니면 Bearer 토큰만 사용가능한 것을 정하기 위해서 했는지 공부가 필요한 부분..

 

3. Middleware, 발급 받은 token이 정상적인 token인지 검증하기

// jwt require
const jwt = require("jsonwebtoken");
// connect user models
const { Users } = require("../models");

// 환경 변수
require("dotenv").config();

module.exports = async (req, res, next) => {
	const key = process.env.SECRET_TOKEN; // 환경변수에 있는 secret token 비밀값
    const { authorization } = req.headers; // 로그인 시 헤더에 저장한 토큰 값을 가져온다.
    // 헤더에 있는 토큰형식을 확인하기
    const [authType, authToken] = (authorization ?? "").split(" ");
    
    //토큰 형식 및 확인
    if (!authToken || authType !== "Bearer") {
    	res.status(401).send({
        	errorMessage: "토큰의 형식이 정상적이지 않습니다.",
        });
        return;
    }
    
    try {
    // 요청한 토큰형식이 정상적으로 인증이 되었을 때
    const { userId } = jwt.verify(authToken, proccess.env.SECRET_TOKEN);
    // 요청한 토큰이 정상적인 토큰으로 인증이 되었을 때 res.locals.user로 담습니다.
    Users.findByPk(userId).then((user) => {
    	res.locals.user = user;
        next();
        });
    } catch (error) { 
    console.log(error); // 에러 확인
    }

 

요청한 middleware에서 정상적인 토큰 값으로 인증이 되었을 때는 요청한 응답이 정상적으로 출력 되는 것을 확인 할 수 있습니다.

 

4. "users/me"에서 middleware 실행하기

FrontEnd를 같이 작업한다면 필요없는 작업이지만, api 구현을 하고 있는 상황이라면 발급받은 토큰 값을 user/me를 호출할 때 토큰 값을 헤더 부분에 넣어서 확인을 하는 작업을 해주어야합니다. 

 

// middleware
const authMiddleware = require("../middlewares/auth-middleware.js");

router.get("/users/me", authMiddleware, async (req, res) => {
  const { email, nickname } = res.locals.user;

  return res.status(200).json({
    code: 200,
    message: "토큰이 정상입니다.",
    data: { email, nickname }, // 정상적으로 res.locals.user에 정보가 담겨있는 확인
  });
});

 

위 코드를 실행할 때 VS Code에서 사용가능한 Thunder Client에서 Requests headers 부분에 Authorization을 추가하여 발급 받은 Token 값을 넣어주어야 정상적으로 동작을 확인 할 수 있습니다. 

 

 

느낀점...

위 작업을 해보면서 토큰 값을 미들웨어로 전달하여 비밀번호를 입력받아서 사용자를 인증받는 것 뿐만 아니라 좀 더 안전하게 인증을 할 수 있는 방법이 있다는 것을 알았다. 

반응형