代码之家  ›  专栏  ›  技术社区  ›  wlh

Express、Create React App和passport twitter

  •  0
  • wlh  · 技术社区  · 8 年前

    我正在我的网站上设置Twitter oauth create-react-app 通过使用助手功能(通过 axios )在前端启动 passport 我后端的oauth进程。我目前正在开发中,所以我在端口上托管我的express服务器 3001 我的前端在左舷 3000 前端有一个代理到端口 3001. 我已通过 cors npm包。

    无论我尝试什么配置,我都无法完成Twitter OAuth过程。我尝试过交换端口,保持相同的端口;我已尝试用代理我的后端 express-http-proxy .

    我用过 http://127.0.0.1 而不是 localhost 在回调函数和初始api调用中,尝试两个端口 3000 3001 .

    我现在不确定自己做错了什么,也不确定是否需要放弃 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.
    

    根据我尝试的配置,我得到的原点为 null http://localhost:3001 http://127.0.0.1 .

    注意,我由于其他原因多次成功调用后端api,例如连接到 Yelp Fusion API . 此外,我正在使用中间件记录我的会话数据,我可以看到我正在成功地获得 oauth_token oauth_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] **********************************************
    

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

    后端代码

    服务器。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')}`);
    });
    

    护照。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);
    }
    

    前端代码

    助手。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应用程序。

    http://127.0.0.1:3001/auth/twittersuccess

    "user": {
        "_id": "redactedbyme",
        "name": "Wesley L Handy",
        "__v": 0,
        "twitterId": "redactedbyme",
        "favorites": [],
        "friends": []
    },
    "isAuth": true
    
    2 回复  |  直到 8 年前
        1
  •  5
  •   wlh    8 年前

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

    然而,根据 this blog , passport-twitter 未针对RESTful API进行优化。这个博客提供了一个有用的教程,可以使用 this passport-twitter-token 策略与 react-twitter-auth 建立 here

    问题在于,使用Create-React应用程序,应用程序运行在两个不同的服务器上,一个用于前端,另一个用于后端。没有前端和后端之间的一系列通信,就无法解决CORS问题,passport不允许这样做。Passport是在单个服务器上处理OAuth的一个很好的工具,但OAuth中需要大量来回操作,这需要更高的复杂性。

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

        2
  •  0
  •   Mejan    5 年前

    如果有人来这里用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 })
    
    推荐文章