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环境,保证securecookie正常工作。
内容的提问来源于stack exchange,提问作者oyraddd
相关产品推荐
相关产品推荐

