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

Express中Google OAuth 2.0异常:点击谷歌注册按钮服务器无响应

Google OAuth 2.0登录挂起问题排查

我尝试通过Google OAuth 2.0实现登录功能,点击“Sign up with Google”按钮后,服务器出现挂起状态,无法跳转到Google授权同意屏幕。我已经检查过代码的语法和拼写,仍无法定位问题。以下是我的app.js代码:

require('dotenv').config()
const express = require("express")
const bodyParser = require("body-parser")
const ejs = require("ejs")
const mongoose = require("mongoose")
const session = require("express-session")
const passport = require("passport")
const passportLoacalMongoose = require("passport-local-mongoose")
const GoogleStrategy = require("passport-google-oauth20").Strategy
const findOrCreate = require("mongoose-findorcreate")

const app = express()

app.use(express.static("public"))
app.set("view engine", "ejs")
app.use(bodyParser.urlencoded({ extended: true }))
app.use(session({
    secret: "Our little secret"
    , resave: false
    , saveUninitialized: false
}))
app.use(passport.initialize())
app.use(passport.session())

mongoose.connect("mongodb://127.0.0.1:27017/userDB")

const userSchema = new mongoose.Schema({
    email: String
    , password: String
})

userSchema.plugin(passportLoacalMongoose)
userSchema.plugin(findOrCreate)

const User = new mongoose.model("User", userSchema)

passport.use(User.createStrategy())
passport.serializeUser(User.serializeUser())
passport.deserializeUser(User.deserializeUser())

passport.use(new GoogleStrategy({
    clientID: process.env.CLIENT_ID,
    clientSecret: process.env.CLIENT_SECRET,
    callbackURL: "http://localhost:3000/auth/google/secrets"
},
    function (accessToken, refreshToken, profile, cb) {
        User.findOrCreate({ googleId: profile.id }, function (err, user) {
            return cb(err, user);
        });
    }
));

app.route("/")
    .get((req, res) => {
        res.render("home")
    })

app.route("/auth/google")
    .get((req, res) => {
        passport.authenticate("google", { scope: ["profile"] })
    })

app.route("/register")
    .get((req, res) => {
        res.render("register")
    })
    .post((req, res) => {
        User.register({ username: req.body.username }, req.body.password, (err, user) => {
            if (err) {
                console.log(err)
                res.redirect("/register")
            } else {
                passport.authenticate("local")(req, res, () => {
                    res.redirect("/secrets")
                })
            }
        })
    })

app.route("/login")
    .get((req, res) => {
        res.render("login")
    })
    .post((req, res) => {
        const user = new User({
            username: req.body.username
            , password: req.body.password
        })

        req.login(user, (err) => {
            if (err) {
                console.log(err)
            } else {
                passport.authenticate("local")(req, res, () => {
                    res.redirect("/secrets")
                })
            }
        })
    })

app.route("/secrets")
    .get((req, res) => {
        if (req.isAuthenticated) {
            res.render("secrets")
        } else {
            res.redirect("/login")
        }
    })

app.route("/logout")
    .get((req, res) => {
        req.logout((err) => {
            if (err) {
                console.log(err)
            }
        })
        res.redirect("/")
    })

app.listen(3000, () => {
    console.log("Server started on port 3000.")
})

问题截图:
注册页面


问题原因及修复方案

  • /auth/google路由未正确执行认证逻辑
    当前路由仅创建了认证中间件,但未将其绑定到请求响应链上,导致请求无处理流程,服务器挂起。修改为直接返回中间件执行结果:

    app.route("/auth/google")
        .get(passport.authenticate("google", { scope: ["profile"] }))
    
  • User Schema缺少googleId字段
    使用findOrCreate时依赖googleId匹配用户,但你的Schema未声明该字段,虽然Mongoose允许隐式存储,但明确声明可避免潜在异常:

    const userSchema = new mongoose.Schema({
        email: String,
        password: String,
        googleId: String // 添加此字段
    })
    
  • req.isAuthenticated需作为方法调用
    /secrets路由中,req.isAuthenticated是函数,需加括号调用才能获取认证状态:

    app.route("/secrets")
        .get((req, res) => {
            if (req.isAuthenticated()) { // 补充括号
                res.render("secrets")
            } else {
                res.redirect("/login")
            }
        })
    
  • 缺少Google OAuth回调路由
    配置的callbackURL对应路由未定义,用户授权后无法回调到服务器,需添加:

    app.route("/auth/google/secrets")
        .get(passport.authenticate("google", { failureRedirect: "/login" }), (req, res) => {
            res.redirect("/secrets")
        })
    
  • Mongoose连接无错误处理
    当前数据库连接未捕获异常,可能导致后续操作静默失败,建议添加:

    mongoose.connect("mongodb://127.0.0.1:27017/userDB")
        .then(() => console.log("Connected to MongoDB"))
        .catch(err => console.log("MongoDB connection error:", err))
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 20:14:55