인증 절차를 통과하면 jwt객체의 sign메서드를 활용해서 인증 정보가 담긴 토큰을 발급함.
해당 토큰 정보를 Bearer 방식으로 묶어 'authorization'이라는 이름의 쿠키에 저장해 response를 보냄
1차 수정
-jwt.sign({}) 안에는 로그인에 필요한 정보가 들어가야 함
-app.js 에 /career 기본 경로가 지정돼있는데, 한번 더 써서 404 에러가 떴었던 거임
('/career/signIn'이 아니라 '/signIn'이었어야 함.)
const accessToken =
<Header>
jwt.sign(
<Payload>
{
userId: user.userId,
email: user.email,
password: user.password,
},
<Signature>
ACCESS_TOKEN_SECRET_KEY,
{ expiresIn: '12h' }
);
res.cookie('accessToken', accessToken);
accessToken
<Header - 토큰의 타입, 어떤 암호화를 사용해 생성된 데이터인지 정의>
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
<Payload: Data,실제 전달하려는 데이터>
eyJ1c2VySWQiOjMsImVtYWlsIjoibWlsa0BuYXZlci5jb20iLCJwYXNzd29yZCI6InBhc3N3b3JkIiwiaWF0IjoxNzA2NjI2NDAzLCJleHAiOjE3MDY2Njk2MDN9.
<Verify Signature - 헤더, 페이로드, 비밀키를 이용해 생성됨/토큰 변조여부 확인>
AJd-yVAXO8YtvovLzv6Lff_bH6xVMpsi_eOM29WNmTc
생각해보니 객체는 index가 명확하지 않고, 대신 프로퍼티의 key로 찾잖아. 근데 내가 지금 쿠키를 생성할 때 key를 accessToken으로 줬는데, authorization key를 가진 프로퍼티를 찾아서 구조분해할당을 하라는 식으로 코딩을 짠거 같은데, 그래서 문제가 생기는거 아닐까?
auth.middleware.js 완성된 코드
이중 셀렉트 문법
-이중 셀렉트 문법처럼 객체의 객체 프로퍼티를 받는 식으로 해볼랬는데 잘안댐
-그래서 요렇게 고쳤는데(위에 api 내부에 userInfos 인스턴스를 불러들이는 코드 있음), auth middleware를 보니까 딱히 필요없는거 같음
const resume = await prisma.resume.findfirst({})라서 그냥 resume.update 하면 먹힐 줄 알았는데 안먹힘
이력서 삭제 api
비밀번호 검사 절차를 한번 더 거치게 해서 삭제하는 api를 구현하고 있는데, 이 에러는 멀까?
req 한번에 res 한번이 국룰인데, 나는 req한번에 res를 두번이나 보내려고 했음, 그래서 문제가 생겼던 거임
원래는 자바스크립트에서(그러니까 프론트엔드) 이벤트를 발생시켜서 처리한 뒤에 삭제만 서버로 넘겨서 하는 거라고 함.
근데 일단 가능은 할 거 같으니 조져보겠음 ㅅㅅ
결론
그렇다고 한다... ㅠ
사용자 : 이력서 = 1: N 관계 구현 중
resume에 @unique 넣으니까 1대1 관계 돼버림, 빼야하는 듯
npx prisma migrate dev << schema 수정하고 prisma orm migrate 함
그러니까 raw query 형태로 migrations 폴더가 생성됨
오 작동 잘됨, 굳!
queryString 적용
queryString 코드를 vsc 작성 단계에서 쓰는게 아니고, 이건 url에 직접 치는 거고 직접 쳐놓은 queryString을 처리하는 로직을 라우터 안에 구축해야 함
모든 이력서 목록 조회 API
orderKey의 userId를 읽지 못하고 있음.
refresh Token의 목적은 사용자가 인증 기능이 필요해 accessToken을 사용해야 하는 api를 추가적인 로그인 절차 없이(왜냐면 보안을 위해 accessToken은 수명이 짧으니까) 이용할 수 있게끔 해주는 기믹임. 그래서 로그인 할때 refresh Token과 access Token을 함께 발급 받는 것
users.router.js
import jwt from 'jsonwebtoken';
import { prisma } from '../utils/prisma/index.js';
import dotenv from 'dotenv';
dotenv.config();
const ACCESS_TOKEN_SECRET_KEY = process.env.ACCESS_TOKEN_SECRET_KEY;
const REFRESH_TOKEN_SECRET_KEY = process.env.REFRESH_TOKEN_SECRET_KEY;
//사용자 인증 미들웨어는 express 의존성이 존재하지 않는다고 함. 무슨 의미인지는 아직 잘 모름
export default async function (req, res, next) {
try {
//발급받은 cookies의 첫번째 프로퍼티를 객체분해할당으로 authorization 식별자에 할당해서 추출함
const { accessToken, refreshToken } = req.cookies;
function validateToken(token, secretKey) {
try {
return jwt.verify(token, secretKey);
} catch (error) {
console.error(error);
return null;
}
}
const decodedToken = validateToken(accessToken, ACCESS_TOKEN_SECRET_KEY);
if (decodedToken) {
//user.router.js의 로그인API에서 생성되어 넘어온 cookies의 userId 정보가 userId 상수에 할당됨
const userId = decodedToken.userId;
if (!userId) throw new Error('로그인을 해주세요!');
//그리고 그 userId와 일치하는 userId를 가진 user를 찾아냄
const user = await prisma.users.findFirst({
where: {
userId: +userId,
},
});
const userInfo = await prisma.userInfos.findFirst({
where: {
userId: +userId,
},
});
if (!user) throw new Error('토큰 사용자가 존재하지 않습니다.');
//이후로 미들웨어에서 req를 통해 전달되는 모든 user는 바로 decodedToken을 타고 와 모든 인증을 거친 userId를 가진 user임
req.user = user;
req.userInfo = userInfo;
next();
}
//accessToken이 존재하지 않거나, 유효하지 않은 경우 refreshToken을 사용해 재발급 받아야 함
else if (!accessToken || !decodedToken) {
//refreshToken 검증
//1. refreshToken의 존재 여부 검증
if (!refreshToken) {
return res
.status(400)
.json({ errorMessage: 'refresh Token이 존재하지 않습니다.' });
}
//2. refreshToken이 존재한다면, 유효여부 검증
const verifiedRefreshToken = validateToken(
refreshToken,
REFRESH_TOKEN_SECRET_KEY
);
if (!verifiedRefreshToken) {
return res
.status(401)
.json({ errorMessage: 'refresh Token이 유효하지 않습니다.' });
}
//3. tokenStorage[refreshToken] 정보가 있는지 여부 확인(어떻게 가져오지...)
//미들웨어에 토큰 스토리지를 들고 오면 안댐(개인정보가 공통적으로 사용되는 미들웨어 상에서 노출돼버림), 필요하면 클라이언트에게 다시 요청하던가, 아니면 그냥 안해야 됨
//accesstoken과 refreshtoken 안에 있는 유저 아이디로 데이터베이스 안에 있는 유저 정보를 가져오도록 설계해야 함
// const userInformation = tokenStorage[refreshToken];
// if (!userInformation)
// return res.status(419).json({
// errorMessage: 'refresh Token의 정보가 서버에 존재하지 않습니다.',
// });
//refreshToken은 이미 jwt 문자열이라서 newAccessToken은 찍어봤자 아무것도 안나옴
//jwt.verify >> 인증기능만 있는 줄 알았는데 복호화 기능이 같이 있었다!
const newAccessToken = jwt.sign(
{
userId: verifiedRefreshToken.userId,
email: verifiedRefreshToken.email,
password: verifiedRefreshToken.password,
},
ACCESS_TOKEN_SECRET_KEY,
{ expiresIn: '10s' }
);
//user.router.js의 로그인API에서 생성되어 넘어온 cookies의 userId 정보가 userId 상수에 할당됨
const userId = jwt.verify(newAccessToken, ACCESS_TOKEN_SECRET_KEY).userId;
if (!userId) throw new Error('로그인을 해주세요!');
//그리고 그 userId와 일치하는 userId를 가진 user를 찾아냄
const user = await prisma.users.findFirst({
where: {
userId: +userId,
},
});
const userInfo = await prisma.userInfos.findFirst({
where: {
userId: +userId,
},
});
if (!user) throw new Error('토큰 사용자가 존재하지 않습니다.');
//이후로 미들웨어에서 req를 통해 전달되는 모든 user는 바로 decodedToken을 타고 와 모든 인증을 거친 userId를 가진 user임
req.user = user;
req.userInfo = userInfo;
next();
}
} catch (error) {
console.error(error);
res.status(404).json({ message: error.name });
}
}