강의

멘토링

커뮤니티

인프런 커뮤니티 질문&답변

tlgjawl0130님의 프로필 이미지
tlgjawl0130

작성한 질문수

[리뉴얼] React로 NodeBird SNS 만들기

쿠키/세션과 전체 로그인 흐름.

로그인시 401 Unauthorized 오류가 뜹니다

작성

·

26

0

 

image.png

로그인시 401 Unauthorized 오류가 떠서

image.png

리덕스 액션을 봤더니 LOG_IN_FAILURE에 error 내용이 비어 있었습니다.

routes/user.js

const express = require("express");
const bcrypt = require("bcrypt");
const { User, Post } = require("../models");
const passport = require("passport");

const router = express.Router();

router.post("/login", (req, res, next) => {
  console.log("🧾 req.body:", req.body);
  passport.authenticate("local", (err, user, info) => {
    if (err) {
      console.error(err);
      return next(err);
    }
    if (info) {
      return res.status(401).send(info.reason);
    }
    return req.login(user, async (loginerr) => {
      if (loginerr) {
        console.error(loginerr);
        return next(loginerr);
      }
      const fullUserWithoutPassword = await User.findOne({
        where: { id: user.id },
        attributes: {
          exclude: ["password"],
        },
        include: [
          {
            model: Post,
          },
          {
            model: User,
            as: "Followings",
          },
          {
            model: User,
            as: "Followers",
          },
        ],
      });
      return res.status(200).json(fullUserWithoutPassword);
    });
  })(req, res, next);
});

router.post("/", async (req, res, next) => {
  try {
    const exUser = await User.findOne({
      where: {
        email: req.body.email,
      },
    });
    if (exUser) {
      return res.status(403).send("이미 사용중인 아이디입니다.");
    }
    const hashedPassword = await bcrypt.hash(req.body.password, 12);
    await User.create({
      email: req.body.email,
      nickname: req.body.nickname,
      password: hashedPassword,
    });
    res.status(201).send("ok");
  } catch (error) {
    console.error(error);
    next(error);
  }
});

module.exports = router;

세션 쿠키가 잘 전달이 안된건가 싶어서 req.body를 서버 터미널로 찍었더니
req.body: undefined 로 나왔습니다.

로그인 폼에서 데이터를 잘못 넘겨준건가 해서 확인해봤더니
loginForm.js

  const onSubmitForm = useCallback(() => {
    console.log(email, password);
    dispatch(loginRequestAction({ email, password }));
  }, [email, password]);

데이터도 잘 넘겨준 것 같고

sagas/user.js

function logInAPI(data) {
  return axios.post("/user/login", data);
}

function* logIn(action) {
  try {
    const result = yield call(logInAPI, action.data);
    yield put({
      type: LOG_IN_SUCCESS,
      data: result.data,
    });
  } catch (err) {
    console.error(err);
    yield put({
      type: LOG_IN_FAILURE,
      error: err.response.data,
    });
  }
}

사가쪽도 문제가 없어보여서 프론트 쪽 문제는 아닌 것 같고 백엔드쪽 문제 같은데 도저히 어디서 문제가 생긴건지 모르겠습니다.

app.js

const express = require("express");
const cors = require("cors");
const session = require("express-session");
const cookieParser = require("cookie-parser");
const postRouter = require("./routes/post");
const userRouter = require("./routes/user");
const db = require("./models");
const passportConfig = require("./passport");
const passport = require("passport");
const dotenv = require("dotenv");

dotenv.config();
const app = express();

db.sequelize
  .sync()
  .then(() => {
    console.log("db 연결성공");
  })
  .catch(console.error);
passportConfig();
app.use(
  cors({
    origin: "*",
    credentials: false,
  })
);
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(cookieParser(process.env.COOKIE_SECRET));
app.use(
  session({
    saveUninitialized: false,
    resave: false,
    secret: process.env.COOKIE_SECRET,
  })
);
app.use(passport.initialize());
app.use(passport.session());

app.get("/", (req, res) => {
  res.send("hello express");
});

app.get("/api", (req, res) => {
  res.json([
    {
      id: 1,
      content: "hello",
    },
    {
      id: 2,
      content: "hello2",
    },
    {
      id: 3,
      content: "hello3",
    },
  ]);
});

app.get("/api/posts", (req, res) => {
  res.json([
    {
      id: 1,
      content: "hello",
    },
    {
      id: 2,
      content: "hello2",
    },
    {
      id: 3,
      content: "hello3",
    },
  ]);
});

app.use("/post", postRouter);
app.use("/user", userRouter);

app.listen(3065, () => {
  console.log("서버 실행 중!");
});


passport/local.js

const passport = require("passport");
const { Strategy: LocalStrategy } = require("passport-local");
const { User } = require("../models");
const bcrypt = require("bcrypt");

module.exports = () => {
  passport.use(
    new LocalStrategy(
      {
        usernameField: "email",
        passwordField: "password",
      },
      async (email, password, done) => {
        try {
          console.log("입력값:", email, password);
          const user = await User.findOne({
            where: { email },
          });
          console.log("찾은 유저:", user && user.email);
          if (!user) {
            return done(null, false, { reason: "존재하지 않는 이메일입니다!" });
          }
          const result = await bcrypt.compare(password, user.password);
          if (result) {
            return done(null, user);
          }
          return done(null, false, { reason: "비밀번호가 틀렸습니다." });
        } catch (error) {
          console.log(error);
          return done(error);
        }
      }
    )
  );
};


passport/index.js

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

module.exports = () => {
  passport.serializeUser((user, done) => {
    done(null, user.id);
  });

  passport.deserializeUser(async (id, done) => {
    try {
      const user = await User.findOne({ where: { id } });
      done(null, user);
    } catch (error) {
      console.error(error);
      done(error);
    }
  });

  local();
};


백엔드 코드를 첨부하였습니다.

image.png


터미널에 나온 콘솔 내용입니다.
local.js파일에서도 콘솔("입력값:","찾은 유저:" )을 찍었는데 터미널에 찍힌 콘솔은 req.body만 찍혔습니다..

답변 1

0

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

개발자도구 네트워크탭쪽에서 확인을 하면 프론트문제인지 백엔드 문제인지 좀 더 알기 쉬워집니다.

네트워크탭에 POST /user/login 요청을 찾아서 payload 부분에 데이터가 들어있는지 확인해보세요. 들어있다면 백엔드쪽 문제이고 안 들어있으면 프론트 문제입니다.

tlgjawl0130님의 프로필 이미지
tlgjawl0130

작성한 질문수

질문하기