You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Passport.js Google OAuth2本地正常,部署后无法获取用户

MERN应用部署后Passport.js Google OAuth2无法获取用户信息

本地运行正常,部署后req.user始终为undefined。已尝试为cookieSession添加sameSite属性、设置app.set("trust proxy", 1),且确认环境变量和Google重定向URI配置正确。

相关代码

passport.js

const GoogleStrategy = require("passport-google-oauth20").Strategy;

module.exports = function (passport) {
  passport.use(
    new GoogleStrategy(
      {
        clientID: process.env.CLIENT_ID,
        clientSecret: process.env.CLIENT_SECRET,
        callbackURL: process.env.CALLBACK_URL,
        scope: ["profile"],
      },
      async function (accessToken, refreshToken, profile, done) {
        done(null, profile);
      }
    )
  );

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

  passport.deserializeUser((user, done) => {
    done(null, user);
  });
};

auth.js

router.get("/google", passport.authenticate("google", { scope: ["profile"] }));

router.get(
  "/google/callback",
  passport.authenticate("google", {
    successRedirect: process.env.CLIENT_URL,
    failureRedirect: "/login/failed",
  })
);

router.get("/login/success", (req, res) => {
  // 此处req.user为undefined
  if (req.user) {
    res.status(200).json({
      error: false,
      message: "Log in success.",
      user: req.user,
      cookies: req.cookies,
    });
  } else {
    res.status(403).json({ error: true, message: "Not authorized." });
  }
});

router.get("/login/failed", (req, res) => {
  res.status(401).json({
    error: true,
    message: "Failed to log in.",
  });
});

router.get("/logout", (req, res) => {
  req.logout();
  res.redirect(process.env.CLIENT_URL);
});

server.js

const port = process.env.PORT || 4420;

connectDB();
const app = express();

app.use(express.json());
app.use(
  cors({
    origin: process.env.CLIENT_URL,
    methods: ["GET", "POST", "PUT", "DELETE"],
    credentials: true,
  })
);
app.use(
  cookieSession({
    name: "session",
    keys: ["key"],
    maxAge: 24 * 60 * 60 * 100,
  })
);

app.use(passport.initialize());
app.use(passport.session());
app.use(express.urlencoded({ extended: false }));

app.use("/auth", require("./routes/auth"));

app.listen(port, () => console.log(`Server running on port ${port}.`));

前端请求代码

React.useEffect(() => {
    fetch(`${process.env.REACT_APP_SERVER_URL}/auth/login/success`, {
      method: "GET",
      credentials: "include",
      headers: {
        Accept: "application/json",
        "Content-type": "application/json",
        "Access-Control-Allow-Credentials": true,
      },
    })
      .then(...)
  }, []);

排查与解决方案

  • 修正CookieSession生产环境配置
    生产环境下必须启用secure属性,跨域场景需设置sameSite: 'none',同时修正原代码中maxAge的数值错误(应为24 * 60 * 60 * 1000即一天有效期),建议用环境变量存储密钥:

    app.use(
      cookieSession({
        name: "session",
        keys: [process.env.SESSION_SECRET || "fallback-key"],
        maxAge: 24 * 60 * 60 * 1000,
        secure: process.env.NODE_ENV === "production",
        sameSite: process.env.NODE_ENV === "production" ? "none" : "lax",
        httpOnly: true,
      })
    );
    
  • 调整Trust Proxy设置位置
    app.set("trust proxy", 1)必须放在cookieSession初始化之前,否则代理信任配置不会生效:

    const app = express();
    app.set("trust proxy", 1); // 移至中间件配置最顶部
    // 后续cors、cookieSession等配置
    
  • 优化Passport序列化逻辑
    直接序列化完整profile对象可能在生产环境出现序列化失败问题,建议只序列化必要字段:

    passport.serializeUser((user, done) => {
      done(null, user.id); // 仅存储用户唯一标识
    });
    
    passport.deserializeUser((id, done) => {
      // 若连接数据库可在此查询用户,否则直接构造基础用户对象
      done(null, { id });
    });
    
  • 清理前端冗余请求头
    Access-Control-Allow-Credentials是服务端响应头,不需要在请求中设置,移除该字段:

    fetch(`${process.env.REACT_APP_SERVER_URL}/auth/login/success`, {
      method: "GET",
      credentials: "include",
      headers: {
        Accept: "application/json",
        "Content-type": "application/json",
      },
    })
    
  • 确认部署平台代理配置
    如Vercel、Netlify等平台需要确保X-Forwarded-Proto头被正确传递,让服务端识别HTTPS环境,保证secure cookie正常工作。

内容的提问来源于stack exchange,提问作者oyraddd

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 23:20:35