๐ ๊ณต๋ถํ๋ ์ง์ง์ํ์นด๋ ์ฒ์์ด์ง?
[E-Commerce App with REST API] (7) logout ์ ์ฟ ํค ์ญ์ ๋ณธ๋ฌธ
๐ฉ๐ป ๋ฐฑ์๋(Back-End)/Node js
[E-Commerce App with REST API] (7) logout ์ ์ฟ ํค ์ญ์
์ง์ง์ํ์นด 2023. 3. 23. 00:32728x90
๋ฐ์ํ
<๋ณธ ๋ธ๋ก๊ทธ๋ Developers Corner ์ ์ ํ๋ธ๋ฅผ ์ฐธ๊ณ ํด์ ๊ณต๋ถํ๋ฉฐ ์์ฑํ์์ต๋๋ค :-)>
=> Node.js E-Commerce App with REST API: Let's Build a Real-Life Example!
๐ท logout ์ ์ฟ ํค ์ญ์ ํ๊ธฐ
์ฌ์ฉ์๊ฐ ๋ก๊ทธ์์์ ํ๋ฉด ์๋ฒ์์ ์ธ์ ์ ํ๊ดดํ๊ณ ์ฟ ํค๋ฅผ ์ญ์
// ์ฟ ํค ์ญ์
res.clearCookie("refreshToken", {
httpOnly : true, // ์น ์๋ฒ๋ฅผ ํตํด์๋ง cookie์ ์ ๊ทผ
secure : true, // HTTPS์์๋ง cookie๋ฅผ ์ฌ์ฉ
});
์ต์ | ์ค๋ช |
maxAge | ํ์ฌ ์๊ฐ์ผ๋ก๋ถํฐ ๋ง๋ฃ ์๊ฐ์ ๋ฐ๋ฆฌ์ด(millisecond) ๋จ์๋ก ์ค์ |
expires | Cookie์ ๋ง๋ฃ ๋ ์ง๋ฅผ GMT ์๊ฐ์ผ๋ก ์ค์ ์ง์ ๋์ด ์์ง ์๊ฑฐ๋ 0์ผ๋ก ์ง์ ๋์ด ์๋ ๊ฒฝ์ฐ session cookie๋ฅผ ์์ฑ |
path | Cookie์ ๊ฒฝ๋ก. ๊ธฐ๋ณธ ๊ฒฝ๋ก๋ “/” |
domain | Cookie์ domain name (๊ธฐ๋ณธ domain name์ loaded) |
secure | HTTPS์์๋ง cookie๋ฅผ ์ฌ์ฉ |
httpOnly | ์น ์๋ฒ๋ฅผ ํตํด์๋ง cookie์ ์ ๊ทผ |
signed | cookie๊ฐ ์๋ช ๋์ด์ผ ํ ์ง๋ฅผ ๊ฒฐ์ |
๐ท ์ฝ๋
โ controllers/userCtrl.js
const User = require("../models/User");
const bcrypt = require("bcrypt");
const asyncHandler = require("express-async-handler");
const { generateToken } = require("../config/jwtToken");
const { validateMongodbID } = require("../utils/validateMongodbID");
const { generateRefreshToken } = require("../config/refreshToken");
const jwt = require("jsonwebtoken");
// create a user
const createUser = asyncHandler(async (req, res) => {
const { firstname, lastname, email, mobile, password } = req.body;
const findUser = await User.findOne({ email: email });
// email์ด db์ ์๋ค๋ฉด
if (!findUser) {
// Create a new User
// 1) ์ฐ์ ๋น๋ฐ๋ฒํธ ํด์ฌํ(์ํธํ)
const hashedPassword = await bcrypt.hash(password, 10);
// 2) ์ User ์ ๋ณด ๋ง๋ค๊ธฐ
const newUser = await User.create({
firstname, lastname, email, mobile, password: hashedPassword
});
res.json(newUser);
} else {
// User already exists
throw new Error("User already exists");
}
});
// login a user
const loginCheck = asyncHandler(async (req, res) => {
const { email, password } = req.body;
// check if user exists or not
const findUser = await User.findOne({ email: email });
// user ๊ฐ ์๋ค๋ฉด done
if (!findUser) {
throw new Error("That email is not registered!");
}
// Match password (๊ธฐ์กด ๋น๋ฐ๋ฒํธ์ ์
๋ ฅํ ๋น๋ฐ๋ฒํธ ์ฒดํฌ)
bcrypt.compare(password, findUser.password, async (err, isMatch) => {
const refreshToken = await generateRefreshToken(findUser?._id);
const updateUser = await User.findByIdAndUpdate(
findUser._id, {
refreshToken: refreshToken,
}, {
new: true
}
);
res.cookie("refreshToken", refreshToken, {
httpOnly: true, // ์น ์๋ฒ๋ฅผ ํตํด์๋ง cookie์ ์ ๊ทผ
maxAge: 72 * 60 * 60 * 1000, // ํ์ฌ ์๊ฐ์ผ๋ก๋ถํฐ ๋ง๋ฃ ์๊ฐ์ ๋ฐ๋ฆฌ์ด(millisecond) ๋จ์๋ก ์ค์
});
if (isMatch) {
res.json({
_id: findUser?._id,
firstname: findUser?.firstname,
lastname: findUser?.lastname,
email: findUser?.email,
mobile: findUser?.mobile,
token: generateToken(findUser?._id)
});
} else {
throw new Error("Email or Password is incorrect!");
}
});
});
// Handle refresh token
const handleRefreshToken = asyncHandler(async (req, res) => {
try {
const cookie = req.cookies;
// refresh token ์์!
if (!cookie?.refreshToken) {
throw new Error("No Refresh Token in cookies");
}
// refresh token ์์ฑ!
const refreshToken = cookie.refreshToken;
const user = await User.findOne({ refreshToken });
if (!user) {
throw new Error("No Refresh token present in db or not matched");
}
// refresh token์ secret key ๊ธฐ๋ฐ์ผ๋ก ์์ฑ
jwt.verify(refreshToken, process.env.SECRET, (err, decoded) => {
if (err || user.id !== decoded.id) {
throw new Error("There is something wrong with refresh token");
}
// access Token ๋ฐ๊ธ
const accessToken = generateToken(user?._id);
res.json({ accessToken });
});
} catch (error) {
throw new Error(error);
}
});
// logout
const logout = asyncHandler(async (req, res) => {
const cookie = req.cookies;
// refresh token ์์!
if (!cookie?.refreshToken) {
throw new Error("No Refresh Token in cookies");
}
const refreshToken = cookie.refreshToken;
const user = await User.findOne({refreshToken});
if (!user) {
res.clearCookie("refreshToken", {
httpOnly : true, // ์น ์๋ฒ๋ฅผ ํตํด์๋ง cookie์ ์ ๊ทผ
secure : true, // HTTPS์์๋ง cookie๋ฅผ ์ฌ์ฉ
});
return res.sendStatus(204); // forbidden
}
// token ์ญ์
await User.findOneAndUpdate(refreshToken, {
refreshToken : "",
});
// ์ฟ ํค ์ญ์
res.clearCookie("refreshToken", {
httpOnly : true, // ์น ์๋ฒ๋ฅผ ํตํด์๋ง cookie์ ์ ๊ทผ
secure : true, // HTTPS์์๋ง cookie๋ฅผ ์ฌ์ฉ
});
return res.sendStatus(204) // forbidden
});
// Update a user
const updateUser = asyncHandler(async (req, res) => {
const { _id } = req.user;
validateMongodbID(_id);
try {
const updateUser = await User.findByIdAndUpdate(
_id,
{
firstname: req?.body?.firstname,
lastname: req?.body?.lastname,
email: req?.body?.email,
mobile: req?.body?.mobile,
}, {
new: true,
}
);
res.json(updateUser);
} catch (error) {
throw new Error(error);
}
});
// get all users
const getAllUsers = asyncHandler(async (req, res) => {
try {
const getUser = await User.find();
res.json({ getUser });
} catch (error) {
throw new Error(error);
}
});
// get a single users
const getAUsers = asyncHandler(async (req, res) => {
const { id } = req.params;
validateMongodbID(id);
try {
const getUser = await User.findById(id);
res.json({ getUser });
} catch (error) {
throw new Error(error);
}
});
// delete a user
const deleteAUser = asyncHandler(async (req, res) => {
const { id } = req.params;
validateMongodbID(id);
try {
const deleteAUser = await User.findByIdAndDelete(id);
res.json({ deleteAUser });
} catch (error) {
throw new Error(error);
}
});
// block user
const blockUser = asyncHandler(async (req, res) => {
const { id } = req.params;
validateMongodbID(id);
try {
const block = await User.findByIdAndUpdate(
id,
{
isBlocked: true,
},
{
new: true,
}
);
res.json(block);
// res.json({
// message : "User blocked"
// });
} catch (error) {
throw new Error(error);
}
});
const unblockUser = asyncHandler(async (req, res) => {
const { id } = req.params;
validateMongodbID(id);
try {
const unblock = await User.findByIdAndUpdate(
id,
{
isBlocked: false,
},
{
new: true,
}
);
res.json({
message: "User unblocked"
});
} catch (error) {
throw new Error(error);
}
});
module.exports = {
createUser,
loginCheck,
getAllUsers,
getAUsers,
deleteAUser,
updateUser,
blockUser,
unblockUser,
handleRefreshToken,
logout
};
โ routes/authRoute.js
const express = require("express");
const router = express.Router();
const { createUser, loginCheck, getAllUsers, getAUsers, deleteAUser, updateUser, blockUser, unblockUser, handleRefreshToken, logout } = require("../controllers/userCtrl");
const { authMiddleware, isAdmin } = require("../middlewares/authMiddleware");
router.post("/register", createUser);
router.post("/login", loginCheck);
router.get("/all-users", getAllUsers);
router.get("/refresh", handleRefreshToken);
router.get("/logout", logout);
router.get("/:id", authMiddleware, isAdmin, getAUsers);
router.delete("/:id", deleteAUser);
router.put("/edit-user", authMiddleware, updateUser);
router.put("/block-user/:id", authMiddleware, isAdmin, blockUser);
router.put("/unblock-user/:id", authMiddleware, isAdmin, unblockUser);
module.exports = router;
728x90
๋ฐ์ํ
'๐ฉโ๐ป ๋ฐฑ์๋(Back-End) > Node js' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
Comments