Backend ๐Ÿ“š/Node.js

[Node] Auth ๊ธฐ๋Šฅ, ๋กœ๊ทธ์•„์›ƒ ๋งŒ๋“ค๊ธฐ - JWT Vertify

leejaejae 2024. 8. 6. 15:59

0. ๋“ค์–ด๊ฐ€๊ธฐ ์•ž์„œ!

  • Auth ๊ธฐ๋Šฅ
    • ํŽ˜์ด์ง€ ์ด๋™ ๋•Œ๋งˆ๋‹ค ๋กœ๊ทธ์ธ ๋˜์žˆ๋Š”์ง€ ์•ˆ๋˜์–ด ์žˆ๋Š”์ง€, ๊ด€๋ฆฌ์ž ์œ ์ €์ธ์ง€, ๊ธ€์„ ์“ฐ๊ฑฐ๋‚˜ ์ง€์šธ ๊ถŒํ•œ์ด ์žˆ๋Š” ์ง€, ๊ทธ๋Ÿฐ ๊ฒƒ๋“ค์„ ํ•˜๋‚˜ํ•˜๋‚˜ ๋‹ค ์ฒดํฌํ•˜๊ธฐ ์œ„ํ•ด Auth ๊ธฐ๋Šฅ์„ ๋งŒ๋“œ๋Š” ๊ฑฐ์ž„.

  • Auth ๊ธฐ๋Šฅ ๋งŒ๋“œ๋Š” ๋ฒ•
    • ์‚ฌ์ „์— ์„œ๋ฒ„์—๋Š” DB์— ํด๋ผ์ด์–ธํŠธ์—๋Š” Cookie์— Token์„ ์ €์žฅํ•ด๋’€๋Š”๋ฐ, ์ด ๋‘ Token์ด ์ผ์น˜ํ•˜๋Š” ์ง€ ๊ณ„์† ํ™•์ธํ•˜๋ฉด ๋จ
    • ํด๋ผ์ด์–ธํŠธ Cookie์—์„œ Incode ๋œ Token์„ ์„œ๋ฒ„๋กœ ๋ณด๋‚ด Decode ์‹œํ‚ค๋ฉด ์œ ์ €์˜ ์•„์ด๋””๊ฐ€ ๋‚˜์˜ค๋Š”๋ฐ,
    • DB์—์„œ ํ•ด๋‹น ์œ ์ € ์•„์ด๋””๋ฅผ ๊ฐ€์ง„ token์ด ์กด์žฌํ•˜๋ฉด ๋‘ Token์ด ์ผ์น˜ํ•˜๋‹ค๊ณ  ๊ฐ„์ฃผ(๊ถŒํ•œ์ด ์žˆ๋‹ค๋Š” ๊ฒƒ)

  • ๋กœ๊ทธ์•„์›ƒ ๊ธฐ๋Šฅ ๋งŒ๋“œ๋Š” ๋ฒ•
    • ๋กœ๊ทธ์•„์›ƒ ํ•˜๋ ค๋Š” ์œ ์ €๋ฅผ DB์—์„œ ์ฐพ์•„์„œ ๊ทธ ์œ ์ €์˜ ํ† ํฐ ์ง€์›Œ์ฃผ๊ธฐ
    • Cookie Token ๊ณผ DB Token์„ ์„œ๋กœ ๋น„๊ตํ•ด ์ธ์ฆํ•˜๋Š”๊ฑด๋ฐ, Token์„ ์ง€์›Œ๋ฒ„๋ฆฌ๋ฉด ๋น„๊ตํ•  ์ˆ˜ ์—†์–ด์„œ ์ธ์ฆ์ด ์•ˆ๋˜์„œ ๋กœ๊ทธ์ธ ๊ธฐ๋Šฅ์ด ํ’€๋ฆฌ๋Š” ๊ฑฐ์ž„

 

1. Auth ๊ธฐ๋Šฅ

1) Cookie Token ๋ณตํ˜ธํ™”(Decode)

// User.js

// JWT ํ† ํฐ ๊ฒ€์ฆ ๋ฐ ์‚ฌ์šฉ์ž ์ฐพ๊ธฐ ๋ฉ”์„œ๋“œ
userSchema.statics.findByToken = function (token) {
  const user = this;

  return new Promise((resolve, reject) => {
    jwt.verify(token, "secretToken", (err, decoded) => {
      if (err) {
        reject(err);
      }

      // user id๋ฅผ ์ด์šฉํ•ด User๋ฅผ ์ฐพ๊ณ 
      // ํด๋ผ์ด์–ธํŠธ์—์„œ ๊ฐ€์ ธ์˜จ Token๊ณผ DB์— ์žˆ๋Š” Token์ด ์„œ๋กœ ์ผ์น˜ํ•˜๋Š”์ง€ ํ™•์ธ
      User.findOne({ _id: decoded.userId, token: token })
        .then((user) => {
          resolve(user);
        })
        .catch((err) => {
          reject(err);
        });
    });
  });
};

 

2) Cookie Token ๊ณผ DB Token ๋น„๊ต

- Auth Route ๋งŒ๋“ค๊ธฐ

// auth.js

const { User } = require("../models/User");

const auth = async (req, res, next) => {
  // ์ธ์ฆ ์ฒ˜๋ฆฌ ํ•˜๋Š” ๊ณณ
  // ํด๋ผ์ด์–ธํŠธ cookie์—์„œ Token์„ ๊ฐ€์ ธ์˜ด -> cookie-parser ์ด์šฉ
  try {
    const token = req.cookies.user_auth;

    if (!token) {
      return res.json({ isAuth: false, error: true });
    }

    // ๊ฐ€์ ธ์˜จ Token Decode ํ•œ ํ›„ User ์ฐพ๊ธฐ
    const user = await User.findByToken(token);
    if (!user) {
      return res.json({ isAuth: false, error: true });
    }

    // index.js์—์„œ req๋ฅผ ์„ ์–ธํ–ˆ์„ ๋•Œ ์ •๋ณด ๋ถˆ๋Ÿฌ์˜ค๊ธฐ ์œ„ํ•ด req์— token๊ณผ user๋ฅผ ๋„ฃ๊ธฐ
    req.token = token;
    req.user = user;
    next(); // middleware์—์„œ ๋‹ค๋ฅธ ๊ฒƒ๋„ ํ•  ์ˆ˜ ์žˆ๊ฒŒ next() ์‚ฌ์šฉ
  } catch (err) {
    throw err;
  }
};

module.exports = { auth };

 

3) Token ์ผ์น˜ํ•˜๋ฉด ์ •๋ณด ๋„˜๊ฒจ ์ฃผ๊ธฐ

// index.js

app.get("/api/users/auth", auth, (req, res) => {

  //์—ฌ๊ธฐ๊นŒ์ง€ middleware๋ฅผ ํ†ต๊ณผํ•ด ์™”๋‹ค๋Š” ์–˜๊ธฐ๋Š” Authentication์ด True๋ผ๋Š” ๋ง
  res.status(200).json({
    _id: req.user._id, 
    isAdmin: req.user.role === 0 ? true : false,
    isAuth: true,
    email: req.user.email,
    name: req.user.name,
    role: req.user.role,
    image: req.user.image
  })

});

 

2. ๋กœ๊ทธ์•„์›ƒ ๊ธฐ๋Šฅ

- Logout Route ๋งŒ๋“ค๊ธฐ

// index.js

app.get("/api/users/logout", auth, async (req, res) => {
  try {
    await User.findOneAndUpdate({ id: req.user._id }, { token: "" });
    return res.status(200).send({
      success: true,
    });
  } catch (err) {
    return res.json({ success: false, err });
  }
});

 

3. ๊ฒฐ๊ณผ ๐ŸŽ‰


โ˜… ๋”ฐ๋ผํ•˜๋ฉฐ ๋ฐฐ์šฐ๋Š” ๋…ธ๋“œ, ๋ฆฌ์•กํŠธ ์‹œ๋ฆฌ์ฆˆ - ๊ธฐ๋ณธ๊ฐ•์˜ ํด๋ก ์ฝ”๋”ฉ ์ž…๋‹ˆ๋‹ค.