개인 과제 중 쿠키를 검증하는 미들웨어를 작성하였는데, JWT를 이용해 사용자를 조회하도록 구현하였다. 어떤 식으로 사용했는지 작성해보겠다.
우선 로직은 아래와 같다.
- 클라이언트로 부터 쿠키(Cookie)를 전달받음.
- 쿠키(Cookie)가 Bearer 토큰 형식인지 체크.
- 서버에서 발급한 JWT가 맞는지 검증.
- JWT의
userId
를 이용해 사용자를 조회.req.user
에 조회된 사용자 정보를 할당.- 다음 미들웨어를 실행.
사용자는 데이터베이스에 저장되어 있으며 prisma를 사용하여 유저를 확인한다.
쿠키에는 사용자의 userId 정보를 담은 Bearer 토큰 형식의 JWT가 저장되어 있다.
사용자가 어떠한 작업을 하려 할 때 사용자 인증이 필요한 작업이라면,
사용자의 쿠키를 받아와서 이 인증 미들웨어에서 작업 가능한 사용자인지 검증한다.
전체 코드를 보겠다.
import jwt from 'jsonwebtoken';
import { prisma } from '../utils/prisma/index.js';
export default async function (req, res, next) {
try {
const { authorization } = req.cookies;
if (!authorization) throw new Error('토큰이 존재하지 않습니다.');
const [tokenType, token] = authorization.split(' ');
if (tokenType !== 'Bearer')
throw new Error('토큰 타입이 일치하지 않습니다.');
const decodedToken = jwt.verify(token, 'custom-secret-key');
const userId = decodedToken.userId;
const user = await prisma.users.findFirst({
where: { userId: +userId },
});
if (!user) {
res.clearCookie('authorization');
throw new Error('토큰 사용자가 존재하지 않습니다.');
}
// req.user에 사용자 정보를 저장합니다.
req.user = user;
next();
} catch (error) {
res.clearCookie('authorization');
// 토큰이 만료되었거나, 조작되었을 때, 에러 메시지를 다르게 출력합니다.
switch (error.name) {
case 'TokenExpiredError':
return res.status(401).json({ message: '토큰이 만료되었습니다.' });
case 'JsonWebTokenError':
return res.status(401).json({ message: '토큰이 조작되었습니다.' });
default:
return res
.status(401)
.json({ message: error.message ?? '비정상적인 요청입니다.' });
}
}
}
우선 토큰을 authorization에 저장하고, 토큰이 없다면 에러를 발생시킨다.
그리고 받은 쿠키를 공백으로 나누어 앞에 토큰의 형식인 bearer가 tokenType에,
그리고 뒤에 정보가 들어있는 토큰은 token에 저장하고,
tokenType이 Bearer가 아니라면 이 또한 에러를 발생시킨다.
이제 암호화된 토큰을 복호화할 차례이다.
verify 메소드를 사용하여 token을 뒤의 인자인 키값으로 복호화하여주고,
이를 userId라는 변수에 할당해준다.
그리고, 이 userId에 해당하는 유저를 데이터베이스에서 찾아준다.
prisma의 users 테이블에서 findFirst로 하나의 데이터를 찾아준다.
만약 userId가 일치하는 user가 없다면 에러를 발생시킨다.
사용자가 있다면, 해당 유저의 정보를 req.user에 넣어준다.
req.user에 넣은 값은 아래의 next()를 통해 다음 미들웨어를 실행할 때,
함께 전달 되어진다.
user 인증이 되지 않는다면 다음 미들웨어로 넘어가지 못하고 에러를 발생시키고,
인증이 되었다면 다음 미들웨어로 넘어가서 원하는 작업을 할 수 있도록 하는 것이다.
위의 미들웨어가 작성되었다면 사용법은
crud에 어느 곳이든 사용이 가능하여 예시로 들자면,
import authMiddleware from './middlewares/authMiddleware.js';
...
...
router.get('/test', authMiddleware, async (req, res, next) => {
...
});
이런 식으로 미들웨어를 불러오고 해당 미들웨어는 path와 실제 실행되는 함수 사이에 위치하게 된다.
이상으로 jwt를 통해 쿠키로 사용자 인증 미들웨어를 작성하고 사용하는 방법을 알아보았다.