我正在使用节点开发简单的webapp并使用facebook身份验证做出反应。我还关注了这个主题的一些教程,但在这些实现中,客户端和后端位于同一台服务器上。在这里,我的后端服务器可以在localhost:5000上工作,并在localhost:3000上做出反应。在react package.json中有后端代理,因此客户端知道如何调用api。
当我点击“使用Facebook登录”按钮时,我将重定向到Facebook页面,在那里我授权应用程序并接收到我的客户端应用程序个人资料ID和其他请求的用户iformation。 Hovewer,当我将用户信息发送到我的后端服务器时,我可以在控制台中看到这个错误:
阻止跨源请求:同源策略禁止在https://www.facebook.com/dialog/oauth?response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A5000%2Fapi%2Fauth%2Ffacebook%2Fcallback&client_id=1617633901657669读取远程资源。 (原因:缺少CORS标题'Access-Control-Allow-Origin'。
在下面你可以看到:
TypeError:尝试获取资源时出现NetworkError。 [了解更多]
Facebook应用设置:
OAuth路由器:
const router = require('express').Router();
const passport = require('../config/facebook-passport');
router.get('/facebook', passport.authenticate('facebook'));
router.get('/facebook/callback',
passport.authenticate('facebook', { failureRedirect: '/login' }),
function(req, res) {
console.log('Successful authentication, redirect home');
res.redirect('/');
});
module.exports = router;
护照Facebook的:
const passport = require('passport');
const FacebookStrategy = require('passport-facebook').Strategy;
passport.use(new FacebookStrategy({
clientID: process.env.CLIENTID,
clientSecret: process.env.CLIENTSECRET,
callbackURL: "/api/auth/facebook/callback"
},
function(accessToken, refreshToken, profile, done) {
console.log(accessToken, refreshToken, profile)
}
));
module.exports = passport;
app.js:
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(session({
secret: '3cr3ts#tr',
resave: true,
saveUninitialized: true
}));
app.use(passport.initialize());
app.use(passport.session());
app.use('/api/users', users);
app.use('/api/oauth', oauth);
app.get('/api/hello', ensureAuthenticated, function(req, res, next) {
res.send({express: 'Hello there'})
});
app.listen(5000);
function ensureAuthenticated(req, res, next) {
if (req.isAuthenticated()) {
return next();
}
res.status(401);
res.send({express: "you need to authenticate"})
}
登录反应组件:
import FacebookLogin from 'react-facebook-login';
class Login extends Component {
sendFacebookResponse(response) {
fetch(`/api/oauth/facebook?${Object.keys(response).map(k => k+'='+response[k]).join('&')}`)
}
render() {
return (
<FacebookLogin
appId="1617633901657669"
autoLoad={true}
fields="name,email,picture"
callback={this.sendFacebookResponse} />
);
}
}
我的应用是否配置正确?如何摆脱CORS错误?任何帮助或建议将不胜感激。
答案 0 :(得分:0)
首先,我从passport-facebook切换到passport-facebook-token。
然后,我添加了2个护照策略。 Facebook被用作身份验证提供程序和用于授权请求的jwt。
const FacebookStrategy = require('passport-facebook-token');
const passportJWT = require('passport-jwt');
passport.use(new FacebookStrategy({
clientID: <FB CLIENT ID>,
clientSecret: <FB CLIENT SECRET>
},
(token, refreshToken, profile, done) => {
// here there should be code responsible for fetching user from database based on facebook profile, saving user if it doesn't exist yet etc.
done(null, user);
}
));
// this will parse jwtPayload (sent as header; "Authorization: Bearer <JWT TOKEN>") into user object, which will be added to request objects in express router endpoints handlers
passport.use('jwt', new passportJWT.Strategy({
jwtFromRequest: passportJWT.ExtractJWT.fromAuthHeaderAsBearerToken(),
secretOrKey: "secret salt"
}, (jwtPayload, done) => {
done(null, jwtPayload);
}));
然后,我添加了用于用户身份验证的端点。 Passport-facebook-token库希望从客户端应用程序发送的Facebook访问令牌作为查询参数access_token = FACEBOOK_ACCESS_TOKEN。使用fb成功授权后,可以生成jwt令牌,并将其发送到客户端应用程序并用于请求授权。
const { sign } = require('jsonwebtoken');
router.get(
'/facebook-token',
passport.authenticate('facebook-token', {session: false}),
(req, res, next) => {
res
.send({
token: sign(req.user, "secret salt" /* the same value that was used to configure jwt passport above */, {})
})
});
现在应该对用户进行身份验证,换句话说,应该在上述端点上生成一个jwt令牌。客户端应用程序在下一个请求中应添加授权标头,前面已经提到。
可以通过护照库提供的中间件功能来保护端点,在这种情况下,passport.authenticate('jwt',{session:false})返回使用jwt策略的功能。
router.get('/secured-endpoint', passport.authenticate('jwt', {session: false}), (req, res, next) => {
res.send("hello world")
// there is req.user object that can be used for user specific actions
});