wlsdk
wlsdk

Reputation: 1

node.js passport deserializeUser not being called

In localhost, deserializeUser is being called, and there was no problem. But after we deploy our app to ec2 using nginx(react), deserializeUser is never called.

const express = require("express");
const cors = require("cors");
const path = require("path");
const morgan = require("morgan");
const bodyParser = require("body-parser");
const dotenv = require("dotenv");
const cookieParser = require("cookie-parser");
const session = require("express-session");
const passport = require("passport");
const flash = require("connect-flash");

const authRouter = require("./routes/auth");
const calendarRouter = require("./routes/calendar");
const healthPillRouter = require("./routes/healthPill");
const { sequelize } = require("./models");
const passportConfig = require("./passport");

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

sequelize
  .sync()
  .then(() => {
    console.log("db 연결 성공");
  })
  .catch(console.error);
passportConfig(passport);
app.set("view engine", "pug");

app.use(morgan("combined"));
app.use(cors({ origin: "http://13.124.67.98", credentials: true }));
app.use("/", express.static(path.join(__dirname, "public")));
app.use(express.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(
  session({
    resave: false,
    saveUninitialized: false,
    secret: process.env.COOKIE_SECRET,
    cookie: {
      httpOnly: true,
      secure: false,
    },
  })
);
app.use(passport.initialize());
app.use(passport.session());
app.use("/", authRouter);
app.use("/", calendarRouter);
app.use("/", healthPillRouter);

app.listen(4000, () => {
  console.log("실행중");
});
app.set("port", process.env.PORT || 8001);

// if (process.env.NODE_ENV === "production") {
//   app.use(morgan("combined"));
// } else {
//   app.use(morgan("dev"));
// }

app.use(express.static(path.join(__dirname, "public")));
app.use(cookieParser(process.env.COOKIE_SECRET));
const sessionOption = {
  resave: false,
  saveUninitialized: false,
  secret: process.env.COOKIE_SECRET,
  cookie: {
    httpOnly: true,
    secure: false,
  },
};

// if (process.env.NODE_ENV === "production") {
//   sessionOption.proxy = true;
//   sessionOption.cookie.secure = true;
// }

app.use(session(sessionOption));
app.use(flash());

this is our app.js

and the bottom is our router code.

<auth.js>

const express = require("express");
const passport = require("passport");
const bcrypt = require("bcrypt");
const { isLoggedIn, isNotLoggedIn } = require("./middlewares");
const { User, Cycle } = require("../models");
const router = express.Router();

//회원가입
router.post("/api/auth/register", isNotLoggedIn, async (req, res) => {
  const {
    userName,
    userEmail,
    userPassword,
    userBirth,
    userWeight,
    userHeight,
    firCycleStart,
    firCycleEnd,
    meanCycle,
    meanPeriod,
    userAlcohol,
  } = req.body;
  try {
    //exUser 존재 시
    const exUser = await User.findOne({ where: { userEmail } });
    if (exUser) {
      return res.send("이미 가입된 이메일입니다");
    }
    //비밀번호 암호화
    const hash = await bcrypt.hash(userPassword, 12);
    //users 테이블에 사용자 정보 저장
    await User.create({
      userName: userName,
      userEmail: userEmail,
      userPassword: hash,
      userBirth: userBirth,
      userWeight: userWeight,
      userHeight: userHeight,
      meanCycle: meanCycle,
      meanPeriod: meanPeriod,
      userAlcohol: userAlcohol,
    });
    const loginUser = await User.findOne({
      attributes: ["id"],
      where: {
        userEmail: userEmail,
      },
    });
    //시작일 정보를 입력했을 때만 주기정보 저장
    if (firCycleStart) {
      await Cycle.create({
        bleedStart: firCycleStart,
        bleedEnd: firCycleEnd,
        userId: loginUser.id,
      });
    }
    return res.status(201).json({ completed: true });
  } catch (error) {
    console.error(error);
    return next(error);
  }
});

//로그인 성공 시 json 형식으로 사용자 이름 send
router.post("/api/auth/login", isNotLoggedIn, async (req, res, next) => {
  passport.authenticate("local", (authError, user, info) => {
    if (authError) {
      console.log(authError);
      return next(authError);
    }
    if (!user) {
      return res.send(info.message);
    }
    return req.login(user, (loginError) => {
      if (loginError) {
        console.error(loginError);
        return next(loginError);
      }
      return res.json({id: user.id, name: user.userName});
    });
  })(req, res, next);
});

//로그아웃
router.get("/api/auth/logout", isLoggedIn, async (req, res) => {
  console.log(req.user.id);
  req.logout();
  req.session.destroy();
  console.log("로그아웃");
  return res.status(200).send("로그아웃 되었습니다");
});

module.exports = router;

<calendar.js>

const express = require("express");
const { isLoggedIn } = require("./middlewares");
const { User, Date, Cycle } = require("../models");
const router = express.Router();
const moment = require("moment");
const Sequelize = require("sequelize");
const Op = Sequelize.Op;

//캘린더 디테일 페이지 POST
//로그인한 사용자의 id는 req.user.id로 가져올 수 있다
router.post("/api/main/date", isLoggedIn, async (req, res) => {
  const {
    date,
    cycleStart,
    cycleEnd,
    isSex,
    isProtection,
    isControl,
    dateMood,
    //★ 프런트 처리 미완 ★
    dateCondition,
    dateMemo,
  } = req.body;
  try {
    //사용자가 입력한 정보를 dates 테이블에 입력
    //upsert 기준이 (date+userId)여야하는데 sequelize는 FK를 composite key로 사용 불가... if문 쓰는 수 밖에?
    const exDate = await Date.findOne({
      where: { date: date, userId: req.user.id },
    });
    //이미 존재하던 날짜 정보면 update
    if (exDate) {
      await Date.update(
        {
          date: date,
          isSex: isSex,
          isProtection: isProtection,
          isControl: isControl,
          dateMood: dateMood,
          dateCondition1: dateCondition,
          //★ 프런트 처리 미완 ★
          dateCondition2: 0,
          dateCondition3: 0,
          dateMemo: dateMemo,
          userId: req.user.id,
        },
        {
          where: { date: date, userId: req.user.id },
        }
      );
    } else {
      //새로운 날짜 정보면 create
      await Date.create({
        date: date,
        isSex: isSex,
        isProtection: isProtection,
        isControl: isControl,
        dateMood: dateMood,
        dateCondition1: dateCondition,
        //★ 프런트 처리 미완 ★
        dateCondition2: 0,
        dateCondition3: 0,
        dateMemo: dateMemo,
        userId: req.user.id,
      });
    }
    //사용자가 입력한 정보를 cycles 테이블에 입력
    //cycleStart cycleEnd 동시에 존재하는 경우는 없게 프런트에서 처리 완료
    const exCycle = await Cycle.findOne({
      where: {
        bleedStart: { [Op.ne]: null },
        bleedEnd: null,
        userId: req.user.id,
      },
    });
    //bleedStart만 있고 bleedEnd는 없는 이전 기록이 존재하는 경우
    if (exCycle) {
      if (cycleStart) {
        //잘못된 입력. 이전 기록의 cycleEnd를 미리 설정해야 함.
        res.send("최근 생리 종료일을 먼저 입력해야 합니다.");
      } else if (cycleEnd) {
        //사용자가 cycleEnd를 설정: cycles 테이블 bleedEnd 업데이트
        await Cycle.update(
          {
            bleedEnd: cycleEnd,
          },
          {
            where: {
              bleedStart: { [Op.ne]: null },
              bleedEnd: null,
              userId: req.user.id,
            },
          }
        );
        return res.status(200).json({ completed: true });
      }
    } else {
      //이전 기록이 존재하지 않는 경우
      if (cycleStart) {
        //사용자가 cycleStart를 설정: cycles 테이블 bleedStart 저장
        await Cycle.create({
          bleedStart: cycleStart,
          userId: req.user.id,
        });
        return res.status(200).json({ completed: true });
      } else if (cycleEnd) {
        //사용자가 cycleEnd를 설정: cycles 테이블 bleedEnd 저장, bleedStart = bleedEnd - cycles.meanPeriod로 계산 후 저장
        const userInfo = await User.findOne({
          attributes: ["meanPeriod"],
          where: { id: req.user.id },
        });
        await Cycle.create({
          //★ meanPeriod를 입력 안 한 사용자일때? ★
          bleedStart: moment(cycleEnd, "YYYY-MM-DD")
            .subtract(userInfo.meanPeriod, "d")
            .format("YYYY-MM-DD"),
          bleedEnd: cycleEnd,
          userId: req.user.id,
        });
        return res.status(200).json({ completed: true });
      } else {
        return res.status(200).json({ completed: true });
      }
    }
  } catch (error) {
    console.error(error);
    return next(error);
  }
});

//캘린더 디테일 페이지 GET
//입력된 정보가 있으면 보내주고, 없으면 "입력된 정보가 없습니다."
router.get("/api/main/", isLoggedIn, async (req, res) => {
  //날짜는 req.body로 받아옴
  const date = req.query.Date_send;
  try {
    const exDate = await Date.findOne({
      where: { date: date, userId: req.user.id },
    });
    if (exDate) {
      res.send(exDate);
    } else {
      res.send("입력된 정보가 없습니다.");
    }
  } catch (error) {
    console.error(error);
    return next(error);
  }
});

router.get("/api/main/today", isLoggedIn, async (req, res) => {
  //날짜는 req.body로 받아옴
  const date = req.query.Today_send;
  try {
    const exDate = await Date.findOne({
      where: { date: date, userId: req.user.id },
    });
    if (exDate) {
      res.send(exDate);
    } else {
      res.send("입력된 정보가 없습니다.");
    }
  } catch (error) {
    console.error(error);
    return next(error);
  }
});

module.exports = router;

login and register have no problem, but I couldn't use any functions needed login session or cookies. How I solve this problem?

Upvotes: 0

Views: 208

Answers (1)

ctone
ctone

Reputation: 11

Since the release of Google Chrome 80 on February 4, 2020, the default value of Cookie's SameSite property has been changed from None to Lax.

In other words, if you send an intersection request, not the same domain address, the cookie will not work.

The solution was to change the cookie settings to sameSite none in backend app.js.

But if you change it, you have to put the attribute secure true, and it was only possible in https.

Even if it is not https, if front and backend are using the same domain, there is no problem.

I believe that applying the domain will not result in an error, because eventually you have to have a domain to apply for https

Upvotes: 1

Related Questions