하나의 디렉토리를 만들고 먼저, npm init -y를 해줍니다.
npm init -y
● 깔아야하는 라이브러리
- devdependency : morgan, nodemon
- dependency : express, cors, cookie-parser, dotenv, jsonwebtoken
npm i -D nodemon morgan
npm i express cors cookie-parser dotenv jsonwebtoken
express는 프레임워크지만 ㅎ;;
● 파일 설정
mkdir controllers db
touch index.js .env
명령어를 쳐주고 package.json은 아래와 같이 설정하면된다.
test는 지워도되고 남겨도 상관없음
먼저, index.js 부터 열어서 코드를 적어주자.
index.js
const express = require('express');
const cors = require('cors');
const logger = require('morgan');
const cookieParser = require('cookie-parser');
const controllers = require('./controllers');
const app = express();
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
const corsOptions = {
origin: 'http://localhost:3000',
methods: ['GET', 'POST', 'OPTIONS'],
credentials: true,
}
app.use(cors(corsOptions));
app.post('/login', controllers.login);
app.post('/logout', controllers.logout);
app.get('/userinfo', controllers.userInfo);
app.listen(4000, ()=>{
console.log('server is on listening on')
})
- morgan 미들웨어는 서버 로거에 메서드 요청시 로그가 남고, 에러가 뜨면 에러도 로거가 남는다.
- cookie-parser는 쿠키 데이터를 객체로 형태로 알아서 파싱해줌
- cors는 cors설정을 해준다.
- express는 뭐..
.env
ACCESS_SECRET=hello
REFRESH_SECRET=world
위와같이 환경변수 설정해준다.
그다음 controllers 파일에 들어가서
- helper와 users라는 디렉토리를 만들어준다.
- controllers 안에 index.js 파일을 만들어준다.
- controllers > helper(폴더), users(폴더), index.js 이렇게 있어야됨
그다음 helper에는 tokenFunction.js 파일을 만들어주고 users에는 3개의 파일 (login.js, logout.js, userInfo.js) 을 만들어준다.
- helper > tokenFunction.js
- users > login.js, logout.js, userinfo.js 이렇게 파일이 있어야됨
먼저 controllers 파일 안에 있는 index.js
index.js
module.exports = {
login : require('./users/login'),
logout : require('./users/logout'),
userInfo : require('./users/userInfo'),
}
tokenFunction.js
require('dotenv').config();
const { sign, verify } = require('jsonwebtoken');
module.exports = {
generateToken: (user, checkedKeepLogin) => {
const payload = {
id: user.id,
email: user.email,
};
let result = {
accessToken: sign(payload, process.env.ACCESS_SECRET, {
expiresIn: '1d', // 1일간 유효한 토큰을 발행합니다.
}),
};
if (checkedKeepLogin) {
result.refreshToken = sign(payload, process.env.REFRESH_SECRET, {
expiresIn: '7d', // 일주일간 유효한 토큰을 발행합니다.
});
}
return result;
},
verifyToken: (type, token) => {
let secretKey, decoded;
switch (type) {
case 'access':
secretKey = process.env.ACCESS_SECRET;
break;
case 'refresh':
secretKey = process.env.REFRESH_SECRET;
break;
default:
return null;
}
try {
decoded = verify(token, secretKey);
} catch (err) {
console.log(`JWT Error: ${err.message}`);
return null;
}
return decoded;
},
};
- jsonwebtoken라이브러리는 sign과 verify 함수가 내장되어있다.
- sign은 넣어줄 payload와 salt 를 넣어주면 암호화된다.
- verify 같은 경우 넣어줄 token과 salt를 넣으면 복호화된다.
login.js
const { USER_DATA } = require('../../db/data');
const { generateToken } = require('../helper/tokenFunctions');
module.exports = (req, res) => {
const { userId, password } = req.body.loginInfo;
const { checkedKeepLogin } = req.body;
const userInfo = {...USER_DATA.filter(user => user.userId === userId && user.password === password)[0], };
let cookieOptions = {
domain : 'localhost',
path : '/',
secure : true,
httpOnly : true,
sameSite : true,
}
const { accessToken, refreshToken } = generateToken(userInfo, checkedKeepLogin);
if ( !userInfo.id ){
return res.status(401).send('Not Authorized');
}
if (refreshToken){
let exCookieOptions = {...cookieOptions, expires : new Date(Date.now() + 24 * 3600 * 1000 * 7)};
res.cookie('refresh_jwt', refreshToken, exCookieOptions);
}
res.cookie('access_jwt', accessToken, cookieOptions);
return res.redirect('/userInfo');
}
logout.js
module.exports = (req, res) => {
const refreshToken = req.cookies['refresh_jwt'];
let cookieOptions = {
domain : 'localhost',
path : '/',
secure : true,
httpOnly : true,
sameSite : true,
}
if ( refreshToken ){
res.clearCookie('refresh_jwt', cookieOptions)
}
res.clearCookie('access_jwt', cookieOptions);
return res.status(205).send('Logged Out Successfully');
}
userInfo.js
const { USER_DATA } = require('../../db/data');
const { generateToken, verifyToken } = require('../helper/tokenFunctions');
module.exports = (req, res) => {
const accessToken = req.cookies['access_jwt'];
const refreshToken = req.cookies['refresh_jwt'];
const accessPayload = verifyToken('access', accessToken);
const cookieOptions = {
domain: 'localhost',
path: '/',
sameSite: 'strict',
httpOnly: true,
secure: true,
}
if (accessPayload){
const userInfo = {...USER_DATA.filter(user => user.id === accessPayload.id)[0]};
if(!userInfo) return res.status(401).send('Not Authorized');
return res.json({...userInfo, password : undefined });
} else if (refreshToken){
const refreshPayload = verifyToken('refresh', refreshToken);
if (!refreshPayload) return res.status(401).send('Not Authorized');
const userInfo = {...USER_DATA.filter((user) => user.id === refreshPayload.id)[0]};
if(!userInfo.id) return res.status(401).send('Not Authorized');
const { accessToken } = generateToken(userInfo);
res.cookies('access_jwt', accessToken, cookieOptions);
return res.json({...userInfo , password : undefined });
}
return res.status(401).send('Not Authorized');
}