[英]passport google oauth2 causes “internal server error” when deployed live on Heroku
I am connected to mongoDB via mongoose and there is no error when using my app on localhost, however when I deployed it onto Heroku I am getting an internal server error.我通过 mongoose 连接到 mongoDB 并且在本地主机上使用我的应用程序时没有错误,但是当我将它部署到 Heroku 时,我收到了内部服务器错误。
Here are my js codes:这是我的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 passportLocalMongoose = 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.use(bodyParser.urlencoded({extended: true}));
app.set("view engine", "ejs");
app.use(session({
secret: varkey,
resave: false,
saveUninitialized: false
}));
app.use(passport.initialize());
app.use(passport.session());
mongoose.connect("mongodb+srv://admin-name:password@cluster0-7monv.mongodb.net/userDB?retryWrites=true&w=majority", {useNewUrlParser: true, useUnifiedTopology: true});
mongoose.set("useCreateIndex", true);
const userSchema = new mongoose.Schema({
email: String,
password: String,
googleId: String
});
userSchema.plugin(passportLocalMongoose);
userSchema.plugin(findOrCreate);
const User = new mongoose.model("User", userSchema);
passport.use(User.createStrategy());
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user) {
done(err, user);
});
});
passport.use(new GoogleStrategy({
clientID: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
callbackURL: "https://herokudomain.herokuapp.com/auth/google/callback",
},
function(accessToken, refreshToken, profile, cb) {
User.findOrCreate({ googleId: profile.id }, function (err, user) {
return cb(err, user);
});
}
));
app.get("/auth/google", passport.authenticate("google", {scope : ["profile", "email"]}));
app.get("/auth/google/callback",
passport.authenticate("google", { failureRedirect: "/login" }),
function(req, res) {
res.redirect("/");
});
And these are my html codes:这些是我的 html 代码:
<a class="btn" href="/auth/google" role="button">Sign Up with Google</a>
The Heroku log shows this in their error log: Heroku 日志在他们的错误日志中显示了这一点:
2020-06-09T04:05:10.523711+00:00 app[web.1]: MongoError: E11000 duplicate key error collection: userDB.users index: username_1 dup key: { username: null }
2020-06-09T04:05:10.523722+00:00 app[web.1]: at Function.create (/app/node_modules/mongodb/lib/core/error.js:51:12)
2020-06-09T04:05:10.523722+00:00 app[web.1]: at toError (/app/node_modules/mongodb/lib/utils.js:149:22)
2020-06-09T04:05:10.523723+00:00 app[web.1]: at /app/node_modules/mongodb/lib/operations/common_functions.js:265:39
2020-06-09T04:05:10.523723+00:00 app[web.1]: at handler (/app/node_modules/mongodb/lib/core/sdam/topology.js:913:24)
2020-06-09T04:05:10.523724+00:00 app[web.1]: at /app/node_modules/mongodb/lib/cmap/connection_pool.js:356:13
2020-06-09T04:05:10.523724+00:00 app[web.1]: at handleOperationResult (/app/node_modules/mongodb/lib/core/sdam/server.js:489:5)
2020-06-09T04:05:10.523725+00:00 app[web.1]: at MessageStream.messageHandler (/app/node_modules/mongodb/lib/cmap/connection.js:270:5)
2020-06-09T04:05:10.523726+00:00 app[web.1]: at MessageStream.emit (events.js:315:20)
2020-06-09T04:05:10.523726+00:00 app[web.1]: at processIncomingData (/app/node_modules/mongodb/lib/cmap/message_stream.js:144:12)
2020-06-09T04:05:10.523726+00:00 app[web.1]: at MessageStream._write (/app/node_modules/mongodb/lib/cmap/message_stream.js:42:5)
2020-06-09T04:05:10.523727+00:00 app[web.1]: at writeOrBuffer (_stream_writable.js:352:12)
2020-06-09T04:05:10.523727+00:00 app[web.1]: at MessageStream.Writable.write (_stream_writable.js:303:10)
2020-06-09T04:05:10.523728+00:00 app[web.1]: at TLSSocket.ondata (_stream_readable.js:712:22)
2020-06-09T04:05:10.523728+00:00 app[web.1]: at TLSSocket.emit (events.js:315:20)
2020-06-09T04:05:10.523729+00:00 app[web.1]: at addChunk (_stream_readable.js:302:12)
2020-06-09T04:05:10.523729+00:00 app[web.1]: at readableAddChunk (_stream_readable.js:278:9)
While the web app returns an "internal server error" page.而 web 应用程序返回“内部服务器错误”页面。 It seems like they are saying that my database has a duplicate but I've cleared out my database and there is nothing in there anymore.
似乎他们在说我的数据库有重复,但我已经清除了我的数据库并且那里没有任何内容了。
Please help me, I'm rather new to programming so I'm still learning how to read error codes and understand them so that I can debug myself.请帮助我,我对编程很陌生,所以我仍在学习如何阅读错误代码并理解它们,以便我自己调试。
I've seen similar questions and tried solutions that were offered but none of them work in my case that is why I decided to open this question.我已经看到了类似的问题并尝试了提供的解决方案,但它们都不适用于我的情况,这就是我决定提出这个问题的原因。
Why you are having the error:为什么你有错误:
From the error logs:从错误日志中:
2020-06-09T04:05:10.523711+00:00 app[web.1]: MongoError: E11000 duplicate key error collection: userDB.users index: username_1 dup key: { username: null }
...
I can deduce that you have a unique index on a username
field in the users
collection and because you have an existing document where the username
field is empty(null), MongoDB is preventing you from inserting another document with empty username
value.我可以推断您在
users
集合中的username
名字段上有一个唯一索引,并且因为您有一个username
名字段为空(null)的现有文档,MongoDB 阻止您插入另一个username
值为空的文档。
From the code you posted, I can see the User schema does not include a username
field, perhaps you used to have it in the schema before.从您发布的代码中,我可以看到 User 架构不包含
username
段,也许您以前曾经在架构中拥有它。 You should note that depending on how you clear the data in the database, the indexes might or might not be cleared, in this case, the index on the username
field wasn't cleared.您应该注意,根据您清除数据库中数据的方式,索引可能会或可能不会被清除,在这种情况下,
username
名字段上的索引没有被清除。
The fix:修复:
Drop the index on the username
property.删除
username
属性上的索引。 Run db.users.dropIndex("username_1")
in the mongo CLI to do that.在 mongo CLI 中运行
db.users.dropIndex("username_1")
来做到这一点。 You can run db.users.getIndexes()
afterwards to be sure that indexes only exist where you need them.您可以在之后运行
db.users.getIndexes()
以确保索引只存在于您需要的地方。
Since according to MongoDB it thinks that username is unique not letting null value get into the database second time.由于根据 MongoDB 它认为用户名是唯一的,因此不会让 null 值第二次进入数据库。 You need to send the username when you fetch profile from google.
当您从谷歌获取个人资料时,您需要发送用户名。 My code is the following
我的代码如下
(accessToken, refreshToken, profile, cb) => {
console.log(profile);
//install and require find or create to make following function work
User.findOrCreate({
googleId: profile.id,
username: profile.emails[0].value
}, (err, user) => {
return cb(err, user);
});
}
));
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.