首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >CORS从React app > Node server >重定向到Google OAuth2 auth发出AJAX请求。

CORS从React app > Node server >重定向到Google OAuth2 auth发出AJAX请求。
EN

Stack Overflow用户
提问于 2017-08-24 20:38:55
回答 1查看 2.5K关注 0票数 4

嗨,过去的两天里,我一直在拼命研究这个问题,但没有运气。

这就是我尝试使用@localhost:3000的Oauth2护照策略时所犯的错误。我正在本地主机上运行一个带有节点/快速服务器的单独应用程序:3001。

XMLHttpRequest无法加载http:localhost:3001/api/auth/google/login。从'http:localhost:3001/api/auth/google/login‘重定向到'https:accounts.google.com/o/oauth2/v2/auth?response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A3001%2Fapi%2Fauth%2Fgoogle%2Fcallback&scope=https%3A%2F%2Fmail.google.com&client_id=***.apps.googleusercontent.com’已被CORS策略阻止:请求的资源上不存在“访问-控制-允许-原产地”标题。原产地'http:localhost:3000‘因此不允许访问。

代码语言:javascript
运行
复制
createError.js:16 

未知(承诺)错误: createError (createError.js:16)在XMLHttpRequest.handleError (xhr.js:87)的网络错误

这是我在客户端使用的代码,用于尝试从我的组件中登录:

//按钮

代码语言:javascript
运行
复制
<div>
   <button className="btn btn-danger" onClick={props.googleAuth}>
      Login With Google
   </button>
</div>

//有状态组件方法

代码语言:javascript
运行
复制
googleAuth() {
    axios.get("http:localhost:3001/api/auth/google/login").then(res => {
      console.log("GOOGLE OAUTH 2 RES", res);
    });
  }

//控制器

代码语言:javascript
运行
复制
passport.use(
  new GoogleStrategy(
    {
      clientID: process.env.GOOGLE_CLIENT_ID,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET,
      callbackURL: "/api/auth/google/callback",
      accessType: "offline"
    },
    (accessToken, refreshToken, profile, done) => {
      const info = {
        googleUsername: profile.displayName,
        googleAccessToken: accessToken,
        googleRefreshToken: refreshToken,
        googleEmail: profile.emails[0].value
      };

      User.findOrCreate({
        where: {
          googleId: profile.id
        },
        defaults: info
      })
        .spread(user => {
          if (user) return done(null, user.toAuthJSON); 
          // this is method that returns a signed JWT off user DB instance. 
          return done(null, false);
        })
        .catch(done);
    }
  )
);

// GOOGLE LOGIN

router.get(
  "/login",
  passport.authenticate("google", {
    scope: [
      "https://mail.google.com/",
      "https://www.google.com/m8/feeds/",
      "email",
      "profile"
    ]
  })
);

// GOOGLE CALLBACK
router.get(
  "/callback",
  passport.authenticate("google", {
    session: false,
  }), (req, res) => {
    res.json(req.user.token)
  }
);

我已经采取了一些步骤来尝试和解决:

  • 我在浏览器上禁用了CORS。
  • 我在服务器端的路由/ api上尝试了cors npm模块,但似乎没有什么效果。
  • 还有很多其他的修补和绝望..。
  • 基于错误,Google阻止我从服务器发出下游请求并抛出错误(我认为).

我的目标是:

  • 我希望Google返回一个用户对象,然后将其存储在我的DB中(已经对此进行了编码逻辑)。
  • 与服务器res.redirect()不同,我希望res.json()是一个签名的JWT (我已经正确地连接了它)。
  • 我不想使用基于我的服务器的会话,并且保持干净和无状态。

这可能吗?还应该注意,我有一个dev环境设置:

同时启动服务器(同时启动客户端和nodemon服务器- client@localhost:3000向Server @localhost:3001发出代理请求)--不确定这是否会导致任何问题?

任何帮助都将不胜感激!

EN

回答 1

Stack Overflow用户

发布于 2018-05-24 08:04:27

所以我解决了这个问题。问题是,您正在使用passport.js进行社交活动,而您本来可以简单地使用以下内容

https://www.npmjs.com/package/react-social-login

但无论如何,我都会告诉你如何让你目前的项目工作。

https://github.com/j-mcfarlane/Reactjs-SocialAuth-RESTAPI

您需要重定向到UI,而不是api。因此,您的配置将更改如下

代码语言:javascript
运行
复制
googleCallbackURL: 'http://localhost:3000/api/auth/google/callback'

在回调中,您将返回一个重定向,而不是返回数据,如下所示

代码语言:javascript
运行
复制
jwt.sign(payload, secret, { expiresIn: 220000 }, (err, token) => {
    if (err) return console.log(err)

    res.redirect("http://localhost:3000/login?token=" + token);
})

我已经对localhost:3000进行了硬编码,但是您应该从请求中获取host,然后使用它。

接下来,您将更新App.js以添加另一条用于/login的路由,该路由将调用组件SocialLogin

代码语言:javascript
运行
复制
import React, { Component, Fragment } from 'react'
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom'

import PrivateRoute from '../util/PrivateRoute'

// Components
import Navbar from './layout/Navbar'

import Landing from './Landing'
import SocialLogin from './SocialLogin'
import Dashboard from './Dashboard'

class App extends Component {
    render() {
        return (
            <Router>
                <Fragment>
                    <Navbar /><br />

                    <Route exact path="/" component={Landing} />
                    <Route exact path="/login" component={SocialLogin} />

                    <Switch>
                        <PrivateRoute path="/dashboard" component={Dashboard} />
                    </Switch>
                </Fragment>
            </Router>

        )
    }
}

export default App

我编写的最简单的SocialLogin如下

代码语言:javascript
运行
复制
import React from 'react'
import qs from 'query-string'

const SocialLogin = (props) => {
    console.log(props.location.search)
    let params = qs.parse(props.location.search)
    window.localStorage.setItem('token', params['token'])
    return (<div>Landing Page - {params.token} </div>)
}

export default SocialLogin

在这里,您有令牌,您可以按照您喜欢的方式继续运行。同样在Google.js中,我更改了下面的内容

代码语言:javascript
运行
复制
<button onClick={this.googleAuth}>Signin With Google</button>

回到你的评论

代码语言:javascript
运行
复制
<a href="/api/auth/google">Log in with google</a>

您需要重定向才能工作,而不应该AJAX您的google auth调用,否则将如何使用select帐户?

现在,在进行了所有这些修复之后,我可以获得如下所示的令牌

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45870488

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档