大家好,我过去2天一直在研究这个问题而没有运气。
这是我尝试使用我的React app @localhost:3000中的Google Oauth2 Passport策略进行身份验证时遇到的错误。我在localhost: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 =代码&安培; REDIRECT_URI = HTTP%3A%2F%2Flocalhost%3A3001%2Fapi%2Fauth%2Fgoogle%2Fcallback&安培;范围= HTTPS%3A% 2F%2Fmail.google.com&安培; CLIENT_ID = *** apps.googleusercontent.com&#39。 被CORS政策阻止:No' Access-Control-Allow-Origin' 标头出现在请求的资源上。起源 ' HTTP:本地主机:3000'因此不允许访问。
createError.js:16
未捕获(承诺)错误:网络错误 at createError(createError.js:16) 在XMLHttpRequest.handleError(xhr.js:87)
这是我在客户端尝试从我的某个组件登录的代码:
// BUTTON
<div>
<button className="btn btn-danger" onClick={props.googleAuth}>
Login With Google
</button>
</div>
//状态组件方法
googleAuth() {
axios.get("http:localhost:3001/api/auth/google/login").then(res => {
console.log("GOOGLE OAUTH 2 RES", res);
});
}
// CONTROLLER
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)
}
);
我已经采取尝试解决的步骤:
还有很多其他的修补和绝望......
根据错误,Google阻止我从我的服务器发出下游请求并抛出错误(我认为)......
我的目标是什么:
这是否可能?还应该注意我有一个开发环境设置:
使用Concurrently启动服务器(同时启动客户端和nodemon服务器 - client @ localhost:3000向server @ localhost:3001发出代理请求) - 不确定这是否会导致任何问题?
非常感谢任何帮助!
答案 0 :(得分:2)
所以我能够解决这个问题。问题是你使用passport.js
进行社交认证,当你可以使用简单的类似
https://www.npmjs.com/package/react-social-login
但我会告诉你如何使你当前的项目有效。
https://github.com/j-mcfarlane/Reactjs-SocialAuth-RESTAPI
您需要重定向到UI而不是api。所以你的配置会改变如下
googleCallbackURL: 'http://localhost:3000/api/auth/google/callback'
接下来在回调中,您将返回如下所示的重定向
,而不是返回数据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
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
位于
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
我改为
<button onClick={this.googleAuth}>Signin With Google</button>
返回评论
<a href="/api/auth/google">Log in with google</a>
您需要重定向才能正常工作,您不应该使用AJAX进行Google认证调用,否则将如何使用选择帐户?
现在经过所有这些修复后,我可以获得如下所示的令牌