【问题标题】:CORS error in Node+react app with facebook authentication using passport使用护照进行 Facebook 身份验证的 Node+react 应用程序中的 CORS 错误
【发布时间】:2023-04-04 04:53:01
【问题描述】:

我正在使用 node 开发简单的 webapp,并使用 facebook 身份验证做出反应。我也关注了一些关于这个主题的教程,但在这些实现中,客户端和后端位于同一台服务器上。在这里,我的后端服务器在 localhost:5000 上工作,并在 localhost:3000 上响应应用程序。在 react package.json 中有后端代理,所以客户端知道如何调用 api。

当我单击“使用 facebook 登录”按钮时,我会重定向到 facebook 页面,在该页面我授权应用程序并接收到我的客户端应用程序配置文件 ID 和其他请求的用户信息。然而,当我将用户信息发送到我的后端服务器时,我可以在控制台中看到这个错误:

跨域请求被阻止:同源策略不允许读取位于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;

护照脸书:

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 错误?任何帮助或建议将不胜感激。

【问题讨论】:

标签: node.js reactjs passport.js facebook-oauth passport-facebook


【解决方案1】:

首先,我从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
});

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-04-04
    • 2021-09-05
    • 2013-09-24
    • 2016-10-02
    • 1970-01-01
    • 2013-09-04
    • 2016-01-19
    • 1970-01-01
    相关资源
    最近更新 更多