Javascript Heroku Google OAuth错误

Javascript Heroku Google OAuth错误,javascript,reactjs,heroku,google-oauth,status,Javascript,Reactjs,Heroku,Google Oauth,Status,我犯了一个非常令人沮丧的错误。当我在本地开发环境中提出GoogleOAuth请求时,它工作得非常好。(使用护照验证)。推到Heroku,我得到的状态是200,而我在开发中得到的状态是302,它将我重定向到GoogleOAuth登录页面。屏幕显示为空白,没有错误。我曾试图故意在客户端ID中输入错误,但它甚至根本没有注册请求。 把我带到heroku的一个空白屏幕上,根本没有注册任何请求。 请帮忙 服务器端通行证: // .use is generic register passport.use(

我犯了一个非常令人沮丧的错误。当我在本地开发环境中提出GoogleOAuth请求时,它工作得非常好。(使用护照验证)。推到Heroku,我得到的状态是200,而我在开发中得到的状态是302,它将我重定向到GoogleOAuth登录页面。屏幕显示为空白,没有错误。我曾试图故意在客户端ID中输入错误,但它甚至根本没有注册请求。 把我带到heroku的一个空白屏幕上,根本没有注册任何请求。 请帮忙

服务器端通行证:

 // .use is generic register
passport.use(
  new GoogleStrategy(
    {
      clientID: keys.googleClientID,
      clientSecret: keys.googleClientSecret,
      // need url for where user should go on callback after they grant permission to our application on google auth page
      callbackURL: "/auth/google/callback",
      // have to authorize this callback url in the google oauth console.developors screen because of security reasons
      proxy: true // trust the proxy our request runs through so heroku callbacks to the correct url
    },
    async (accessToken, refreshToken, profile, done) => {
      // after authenticated on the next get request to google it will call this with the accessToken, aka callback function
      // console.log("access token", accessToken);
      // console.log("refresh token", refreshToken);
      // console.log("profile", profile);

      // check to see if user id already exists before saving it to DB so it does not overlap...mongoose query...asynchronous operation
      // using async await
      const existingUser = await User.findOne({
        googleId: profile.id
      });
      // get promise response
      if (existingUser) {
        // already have record
        // finish passport auth function
        return done(null, existingUser); // passes to serialize user so serialize can pull that user id
      }
      // we don't have a new record so make one
      const user = await new User({
        // creates new model instance of user
        googleId: profile.id
      }).save(); // have to save it to DB
      // get promise from save since asynchronize, then finish with response
      done(null, user); // passes to serialize user so serialize can get that id
    }
  )
); // create new instance of GoogleStrategy
服务器端API:

    app.get(
    "/auth/google", // passport, attempt to authenticate the user coming in on this route
    passport.authenticate("google", {
      // google strategy has internal code, that is 'google', so passport will know to find the google passport authenticator
      scope: ["profile", "email"] // options object
      // specifies to google we want access to this users profile and email information from their account, these are premade strings in the google oauth process not made up
    })
  );

  // in this callback route they are going to have the code, and google will see that and it will handle it differnetly by exchanging the code for an actual profile, it will call the next part of the GoogleStrategy, aka the accessToken to be saved to Database

  // @route GET auth/google/callback
  // @desc  Get callback data from google to redirect user if signed in
  // @access Private can only access this after signed in

  app.get(
    "/auth/google/callback",
    passport.authenticate("google"),
    // after authenticate process is done, send user to correct route
    (req, res) => {
      // redirect to dashboard route after sign-in
      res.redirect("/surveys");
      // full HTTP requrest, so it reloads versus AJAX request which uses react and redux and is much faster
    }
  );
客户端

<div
            className="collapse navbar-collapse nav-positioning"
            id="navbarNav"
          >
            <ul className="navbar-nav">
              <li className="nav-item google-link">
                <a className="nav-link" href="/auth/google">
                  Google Login
                </a>
              </li>
            </ul>
          </div>

请看看这个。看来您的范围参数需要修改才能让google auth正常工作。

我也有同样的问题。我通过在配置键上定义一个绝对URI来解决这个问题。因为google在https://上查看url回调,heroku路径是http://当您添加代理时,它应该被修复:true,但它不是

在配置键上添加

dev:absoluteURI:localhost:5000

产品:绝对URI:


我相信问题在于你在heroku上的应用程序只监听http请求。如果您指向OAuth页面的链接格式为“”,那么您的应用程序的路由将与该路由不匹配(因为https),因此您的应用程序将显示一个空白页面,就像它将显示任何未侦听的路由一样

解决此问题并仍然使用https(因此仍然在url旁边显示安全徽标)的一种方法是对除此OAuth链接之外的每个链接使用https。应用程序中的get和post请求将使用http,但url上可见的任何链接都将使用https。类似这样的方法会奏效:

app.use(function(req, res, next) {
        if (process.env.NODE_ENV === "production") {
            const reqType = req.headers["x-forwarded-proto"];
            // if not https redirect to https unless logging in using OAuth
            if (reqType !== "https") {
                req.url.indexOf("auth/google") !== -1
                  ? next()
                  : res.redirect("https://" + req.headers.host + req.url);
            } 
        } else {
            next();
        }
    });  

任何指向OAuth登录页面的前端链接都应该是http链接

您可以发布
/auth/google
的客户端代码和服务器端API吗,Posteda您是否将google客户端密钥配置为与heroku域一起工作?是的,它们是…即使它们不是,我也会收到授权错误?它只是把我带到了一个空白屏幕。同样,这在本地服务器上正常工作,但在heroku服务器上不正常。我可能缺少生产设置吗?您需要进入浏览器devtools并查看“网络”选项卡以查看发生了什么情况请参见该答案下面的注释,这是设置范围的另一种方法。我将测试这个方法,可能他们在开发中工作,但在heroku中不工作。仍然不工作,我不确定发生了什么,因为没有显示错误。几乎看起来它甚至没有达到我的api请求
// .use is generic register
passport.use(
  new GoogleStrategy(
    {
      clientID: keys.googleClientID,
      clientSecret: keys.googleClientSecret,
      callbackURL: absoluteURI + "/auth/google/callback",
      proxy: true 
    },
app.use(function(req, res, next) {
        if (process.env.NODE_ENV === "production") {
            const reqType = req.headers["x-forwarded-proto"];
            // if not https redirect to https unless logging in using OAuth
            if (reqType !== "https") {
                req.url.indexOf("auth/google") !== -1
                  ? next()
                  : res.redirect("https://" + req.headers.host + req.url);
            } 
        } else {
            next();
        }
    });