Express,Create-React-App,&护照叽叽喳喳

时间:2017-12-06 20:59:44

标签: node.js cors passport.js create-react-app passport-twitter

我正在我的create-react-app应用程序上设置Twitter oauth,在前端使用辅助函数(通过axios)在我的后端启动passport oauth进程。我目前正处于开发阶段,因此我在端口3001上托管我的快速服务器,在端口3000上托管我的前端,前端到端口3001.的代理我已经设置了CORS权限通过cors npm包。

无论我尝试哪种配置,我都无法完成Twitter OAuth流程。我试过切换端口,保持相同的端口;我尝试使用express-http-proxy代理我的后端。

我在回调函数和初始api调用中使用了http://127.0.0.1而不是localhost,尝试了两个端口30003001

我现在不知道自己哪里出错了,或者我是否需要放弃passport-twitter寻求其他解决方案。

在每种情况下,我都会收到以下错误:

Failed to load https://api.twitter.com/oauth/authenticate?
oauth_token=alphanumericcoderedactedherebyme: No 'Access-Control-Allow-Origin' 
header is present on the requested resource. Origin 'http://localhost:3000' is 
therefore not allowed access.

根据我尝试的配置,我的来源为nullhttp://localhost:3001http://127.0.0.1

注意,由于其他原因,我成功地多次调用我的后端api,例如连接到Yelp Fusion API。此外,我使用中间件来记录我的会话数据,我可以看到我从Twitter成功获得oauth_tokenoauth_token_secret。该呼叫在oauth进程的下一阶段失败了:

[0] *************SESSION MIDDLEWARE***************
[0] Session {
[0]   cookie:
[0]    { path: '/',
[0]      _expires: 2018-01-06T20:20:31.913Z,
[0]      originalMaxAge: 2678400000,
[0]      httpOnly: true },
[0]   'oauth:twitter':
[0]    { oauth_token: 'alphanumericcoderedactedherebyme',
[0]      oauth_token_secret: 'alphanumericcoderedactedherebyme' } }
[0]
[0] Logged In:
[0] __________ false
[0] **********************************************

以下是我的代码的相关部分 -

BACKEND CODE

SERVER.JS

// Dependencies

const express = require("express");
const cors = require("cors");
const passport = require('passport');

// Initialize Express Server
const app = express();

// Specify the port.
var port = process.env.PORT || 3001;
app.set('port', port);

app.use(passport.initialize());
app.use(passport.session());

//enable CORS
app.use(cors());

//set up passport for user authentication
const passportConfig = require('./config/passport');

require("./controllers/auth-controller.js")(app);

// Listen on port 3000 or assigned port
const server = app.listen(app.get('port'), function() {
    console.log(`App running on ${app.get('port')}`);
});

PASSPORT.JS

const passport = require('passport');
const TwitterStrategy = require('passport-twitter').Strategy;

passport.use(new TwitterStrategy({
    consumerKey: process.env.TWITTER_CONSUMER_KEY,
    consumerSecret: process.env.TWITTER_CONSUMER_SECRET,
    callbackURL: process.env.NODE_ENV === 'production' ? process.env.TWITTER_CALLBACK_URL : 'http://localhost:3000/auth/twitter/callback'
    },
    function(accessToken, refreshToken, profile, done) {
        ...etc, etc, etc

AUTH-CONTROLLER.JS

const router = require('express').Router();
const passport = require('passport');

module.exports = function(app) {
    router.get('/twitter', passport.authenticate('twitter'));

    router.get('/twitter/callback',
        passport.authenticate('twitter', {
            successRedirect: '/auth/twittersuccess',
            failureRedirect: '/auth/twitterfail'
        })
    );

    router.get('/twittersuccess', function(req, res) {
        // Successful authentication
        res.json({ user: req.user, isAuth: true });
    })

    router.get('/twitterfail', function(req, res) {
        res.statusCode = 503;
        res.json({ err: 'Unable to Validate User Credentials' })
    })

    app.use('/auth', router);
}

FRONTEND CODE

HELPERS.JS

import axios from 'axios';

export function authUser() {
    return new Promise((resolve, reject) => {
        axios.get('/auth/twitter', {
            proxy: {
                host: '127.0.0.1',
                port: 3001
            }
        }).then(response => {
            resolve(response.data);
        }).catch(err => {
            console.error({ twitterAuthErr: err })
            if (err) reject(err);
            else reject({ title: 'Error', message: 'Service Unavailable - Please try again later.' });
        });
    });
}

<小时/> 的更新 我确认Passport身份验证适用于我的后端端口。我直接在浏览器中调用了端点,并被重定向到Twitter身份验证,然后返回到我的回调,保存在我的模式中的新用户保存到会话数据中。

这意味着问题在于在与我的后端不同的端口上使用Create-React-App。

http://127.0.0.1:3001/auth/twittersuccess

"user": {
    "_id": "redactedbyme",
    "name": "Wesley L Handy",
    "__v": 0,
    "twitterId": "redactedbyme",
    "favorites": [],
    "friends": []
},
"isAuth": true

2 个答案:

答案 0 :(得分:3)

在咨询了几位开发人员并在其他论坛上发布此问题后,我找不到解决问题的方法。

但是,根据this blogpassport-twitter未针对RESTful apis进行优化。相同的博客提供了一个有用的教程,可以使用this passport-twitter-token策略以及react-twitter-auth找到here

该问题涉及这样一个事实:使用Create-React-App,应用程序在两个不同的服务器上运行,一个用于前端,另一个用于后端。如果没有前端和后端之间的一系列通信(护照不允许),则无法绕过CORS问题。 Passport是在单服务器上处理OAuth的一个很好的工具,但OAuth需要相当多的来回需要更多的复杂性。

tutorial by Ivan Vasiljevic是理解和解决这种复杂性的有用起点。

答案 1 :(得分:0)

如果有人在使用 Reactjs 从 passport-twitter 策略中获取用户时遇到困难,这是我找到的解决方案。

你所要做的就是allowing credentials

启用凭据可以在前端使用 cookie 或 express-session。阅读 MDN 了解更多详情。

后端:

// cors policy setup
app.use(
  cors({
    origin: "http://localhost:3000", // front end url
    optionsSuccessStatus: 200,
    credentials: true,
  })
);

前端:

axios.get(`${apiURL}/profile`, { withCredentials: true })