简体   繁体   English

部署到 Heroku 时无法使用 Google OAuth 登录

[英]Unable to login with Google OAuth when deployed to Heroku

I am unable to login to the app when deployed to Heroku.部署到 Heroku 后,我无法登录该应用程序。 I had a successful build and deployment, but when I launch the app it starts me logged out and upon attempting to login, it hangs and throws an Application error.我有一个成功的构建和部署,但是当我启动应用程序时,它让我退出,并在尝试登录时挂起并抛出应用程序错误。 Express/Passport/MongoDB + create-react-app Express/Passport/MongoDB + create-react-app

I chek my keys several time, everesting match perfect.我多次检查我的钥匙,珠穆朗玛峰匹配完美。 On my localserver everesing working perfect.在我的本地服务器上,everesing 工作完美。 Can it be a problem with "https" response on server?服务器上的“https”响应是否有问题?

app link https://mysterious-thicket-20426.herokuapp.com/应用链接https://mysterious-thicket-20426.herokuapp.com/

git repo https://github.com/detoner777/email-feedback-app git repo https://github.com/detoner777/email-feedback-app

heroku err logs: heroku 错误日志:

2019-08-20T09:44:08.211815+00:00 heroku[router]: at=error code=H12 desc="Request timeout" method=GET path="/auth/google/callback?code=4%2FpAFASjHeS_JuqGKXbEIDY4Jh5zHBJZk-Zyg19q6DHWGVtuipmCKVt1hLpwKltJUHW9XB3EBLcPGorEQUI68uZCE&scope=email+profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile&authuser=0&session_state=330af188f3789437fd21ab099ebe776784cfe500..3fb5&prompt=none" host=mysterious-thicket-20426.herokuapp.com request_id=59b62556-d07c-42ae-8f7f-e89b3ab5b735 fwd="31.134.127.229" dyno=web.1 connect=1ms service=30000ms status=503 bytes=0 protocol=https 2019-08-20T09:52:03.838240+00:00 heroku[router]: at=info method=HEAD path="/" host=mysterious-thicket-20426.herokuapp.com request_id=81a31581-1aa6-478d-98af-68b6c479e32a fwd="217.182.175.162" dyno=web.1 connect=0ms service=1ms status=200 bytes=289 protocol=https 2019-08-20T09:44:08.211815+00:00 heroku[router]: at=error code=H12 desc="Request timeout" method=GET path="/auth/google/callback?code=4%2FpAFASjHeS_JuqGKXbEIDY4Jh5ZDHYBJ1HpXipWQIPWCYpGZeWcLypWcLypWcLypWcLypWcLypWcLypWcLypWcLypZhpWcLypZhbc2019-08-20T09:44:08.211815+00:00 =email+profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile&authuser=0&session_state=330af188f3789437f3789408f3789437fd205bfenfd21bfenc host=mysterious-thicket-20426.herokuapp.com request_id=59b62556-d07c-42ae-8f7f-e89b3ab5b735 fwd="31.134.127.229" dyno=web.1 connect=1ms service=300032ms -08-20T09:52:03.838240+00:00 heroku[router]: at=info method=HEAD path="/" host=mysterious-thicket-20426.herokuapp.com request_id=81a31581-1aa6-478d-984a79eb3 fwd="217.182.175.162" dyno=web.1 connect=0ms service=1ms status=200 bytes=289 protocol=https

//inex.js
const express = require('express');
const mongoose = require('mongoose');
const cookieSession = require('cookie-session');
const passport = require('passport');
const bodyParser = require('body-parser');
const keys = require('./config/keys');
require('./models/User');
require('./services/passport');

mongoose.connect(keys.mongoURI);

const app = express();

app.use(bodyParser.json());
app.use(
    cookieSession({
        maxAge: 30 * 24 * 60 * 60 * 1000,
        keys: [keys.cookieKey]
    })
);


app.use(passport.initialize());
app.use(passport.session());

require('./routes/authRoutes')(app);
require('./routes/billingRoutes')(app);


if (process.env.NODE_ENV === 'production') {
    app.use(express.static('client/build'));
    const path = require('path');
    app.get('*', (req, res) => {
        res.sendFile(path.resolve(__dirname, 'client', 'build', 'index.html'));
    });
}

const PORT = process.env.PORT || 5000;
app.listen(PORT);


// passport.js
const passport = require('passport');
const GoogleStrategy = require('passport-google-oauth20').Strategy;
const mongoose = require('mongoose');
const keys = require('../config/keys');

const User = mongoose.model('users');

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

passport.deserializeUser((id, done) => {
    User.findById(id).then(user => {
        done(null, user);
    });
});

passport.use(
    new GoogleStrategy(
        {
            clientID: keys.googleClientID,
            clientSecret: keys.googleClientSecret,
            callbackURL: '/auth/google/callback',
            proxy: true
        },
        async (accessToken, refreshToken, profile, done) => {
            const existingUser = await User.findOne({ googleId: profile.id });

            if (existingUser) {
                return done(null, existingUser);
            }

            const user = await User({ googleID: profile.id }).save()
            done(null, user);
        }
    )
);

Solved it, here's what worked for me:解决了它,这对我有用:

Please check that your user/password for the Mongodb Atlas prod database correctly match the MONGO_URI variable that you set in Heroku, that was causing this issue for me.请检查您的 Mongodb Atlas prod 数据库的用户/密码是否与您在 Heroku 中设置的 MONGO_URI 变量正确匹配,这对我来说是导致此问题的原因。 I think it's easy to make a typo here since you cannot see the password for the database user after you create it.我认为这里很容易打错字,因为在创建数据库用户后您看不到它的密码。 Also note that the user should not be "read-only", and that this is not the same user/password combination that you use to log in to Mongodb Atlas.另请注意,用户不应为“只读”,并且这与您用于登录 Mongodb Atlas 的用户/密码组合不同。

I found that the reason why the authentication callback was failing with a timeout error was that the Google Strategy's callback defined in the file passport.js never called the method done().我发现身份验证回调失败并出现超时错误的原因是文件passport.js 中定义的Google Strategy 回调从未调用方法done()。 This, in turn, happened because the query to find a user in the MongoDB never completed because Mongoose couldn't connect to the mlab.com database.反过来,发生这种情况是因为在 MongoDB 中查找用户的查询从未完成,因为 Mongoose 无法连接到 mlab.com 数据库。 I tried creating a new user for the prod database in mlab and updating that in the Heroku environment variables and it worked!我尝试在 mlab 中为 prod 数据库创建一个新用户并在 Heroku 环境变量中更新它,并且成功了!

Try adding full url of server as callback url, check the documentation http://www.passportjs.org/docs/google/ , so your callback尝试添加服务器的完整 url 作为回调 url,检查文档http://www.passportjs.org/docs/google/ ,以便您的回调

URL will be https://mysterious-thicket-20426.herokuapp.com/auth/google/callback URL 将是https://mysterious-thicket-20426.herokuapp.com/auth/google/callback

Had the exact same problem as you with the same setup and everything.使用相同的设置和所有内容遇到与您完全相同的问题。

I checked everything and noticed the my cluster on MongoDB had no activity and was paused.我检查了所有内容并注意到我在 MongoDB 上的集群没有活动并被暂停。 The cluster pauses when there are no connection made to it after a while.集群在一段时间后没有连接时暂停。 This meant the backend wasn't able to properly to the database, hence the timeout to /auth/google/callback .这意味着后端无法正确访问数据库,因此/auth/google/callback超时。

Here's what happened:这是发生的事情:

After you've go through the OAuth credential on /auth/google page, google redirects you back to /auth/google/callback .在您通过/auth/google页面上的 OAuth 凭据后,google 会将您重定向回/auth/google/callback

The route handler for /auth/google/callback endpoint picks up the request and uses the passport.authenticate('google') middleware (to verify the authentication) /auth/google/callback端点的路由处理程序接收请求并使用passport.authenticate('google')中间件(以验证身份验证)

Your passport.authenticate('google') middleware uses the Google Strategy and its configurations you've set up inside passport.js您的passport.authenticate('google')中间件使用您在passport.js设置的Google 策略及其配置

Going back on the no connections made to your database issue, this means there will be an authentication problem within the Google Strategy.回到没有连接到您的数据库的问题,这意味着 Google 策略中将存在身份验证问题。 Specifically, in its callback function:具体来说,在其回调函数中:

 async (accessToken, refreshToken, profile, done) => { const existingUser = await User.findOne({ googleId: profile.id }); if (existingUser) { return done(null, existingUser); } const user = await User({ googleID: profile.id }).save() done(null, user); }

Express app wasn't able to make a connection to the MongoDB earlier, and now it attempts to execute a promise: await User.findOne({ googleId: profile.id }) with no error handling . Express 应用程序之前无法连接到 MongoDB,现在它尝试执行承诺: await User.findOne({ googleId: profile.id })没有错误处理 This means there should an unhandled promise rejection error appearing in your console and your app crashing down.这意味着您的控制台中应该出现unhandled promise rejection error并且您的应用程序崩溃。

Like @Agasthian Rathinavel mentioned, do double check on your MongoDB credentials and the environmental variables so you're certain the backend is able to connect to the database.就像@Agasthian Rathinavel 提到的那样,请仔细检查您的 MongoDB 凭据和环境变量,以确保后端能够连接到数据库。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM