Express、Create-React-App 和 passport-twitter

Posted

技术标签:

【中文标题】Express、Create-React-App 和 passport-twitter【英文标题】:Express, Create-React-App, & passport-twitter 【发布时间】:2018-05-20 20:53:05 【问题描述】:

我正在我的 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

注意,由于其他原因,例如连接到Yelp Fusion API,我多次成功调用我的后端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] **********************************************

这是我的代码的相关部分 -

后端代码

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);

前端代码

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 Authentication 在我的后端端口上工作。我直接在浏览器中调用端点并被重定向到 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

【问题讨论】:

@sideshowbarker 没有帮助。这不是客户端调用。这是与使用 localhost 和 create-react-app 相关的问题 【参考方案1】:

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

但是,根据this blog,passport-twitter 并未针对 RESTful api 进行优化。同一博客提供了一个有用的教程,用于使用 this passport-twitter-token 策略和 react-twitter-auth 找到 here

问题与这样一个事实有关,即使用 Create-React-App 应用程序在两台不同的服务器上运行,一台用于前端,另一台用于后端。如果没有前端和后端之间的一系列通信,就无法解决 CORS 问题,而护照是不允许的。 Passport 是在单服务器上处理 OAuth 的绝佳工具,但在 OAuth 中需要大量来回操作,这需要更多复杂性。

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

【讨论】:

【参考方案2】:

如果有人来这里使用 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 )

【讨论】:

以上是关于Express、Create-React-App 和 passport-twitter的主要内容,如果未能解决你的问题,请参考以下文章

Express、Create-React-App 和 passport-twitter

使用 Express 服务器后端的 Create-React-App

使用 Passport + Facebook + Express + create-react-app + React-Router + 代理进行身份验证

使用 node express 的 create-react-app 获取 %PUBLIC_URL%

使用 express 后端将 create-react-app 部署到 heroku 在浏览器中返回无效的主机标头

使用express, create-react-app, mongodb搭建react模拟数据开发环境