Search code examples
apireactjsexpresstwitterproxy

How to contact twitter api with client authentication using express as proxy and xhr as client


request

var xhttp = new XMLHttpRequest();

xhttp.onreadystatechange = function() {
  if (this.readyState == 4 && this.status == 200) {
    console.log(this.response);
    console.log(this.responseText);
  }
};
xhttp.open("GET", "http://localhost:4000/auth/test", true);
xhttp.withCredentials = true;
xhttp.send();

server.js

var express = require('express')
var app = express()
app.get('/auth/test', function (req, res) {
  console.log("hitting /auth/test");
  res.json({ text: "hello world" });
});
// var cors = require('cors');
// app.use(cors());
app.use(function(req, res, next) {
    // Set CORS headers
  res.setHeader('Access-Control-Allow-Origin', '*');
  res.setHeader('Access-Control-Request-Method', '*');
  res.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET');
  res.setHeader('Access-Control-Allow-Headers', '*');
  if ( req.method === 'OPTIONS' ) {
    res.writeHead(200);
    res.end();
    return;
  }
  next();
});
app.listen(4000, function () {
  console.log('Example app listening on port 4000!')
});

error:

dashboard:1 XMLHttpRequest cannot load http://localhost:4000/auth/test. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access.

I can't use a proxy to access my server, my client is a fork of react-boilerplate on github, the loading doesn't support proxy.


Solution

  • This work fine for proxying request to twitter api 1.1.

    var express = require('express');
    var app = express();
    var cors = require('cors');
    app.use(cors());
    var request = require('request');
    
    var ClientOAuth2 = require('client-oauth2');
    
    const twitterAuth = new ClientOAuth2({
      clientId: '***',
      clientSecret: '***',
      accessTokenUri: 'https://api.twitter.com/oauth2/token',
      authorizationUri: 'https://api.twitter.com/oauth/authorize',
      authorizationGrants: ['credentials'],
      redirectUri: 'http://www.domain.com/cb',
    });
    
    app.get('/auth/twitter', function (req, res) {
      twitterAuth.credentials.getToken()
        .then(function (user) {
           res.json(user.data);
        });
    });
    
    app.use('/search/twitter/:search', function (req, res) {
      var search = req.params.search;
      // You need to attach the bearer in Authorization header, it will be reused by our proxy.
      var bearer = req.headers.Authorization;
    
      console.log('search', search);
      console.log('bearer', bearer);
    
      var url = 'https://api.twitter.com/1.1/search/tweets.json?q=' + search;
      var options = {
        url: 'https://api.twitter.com/1.1/search/tweets.json?q=' + search,
        headers: {
          'Authorization': bearer,
          'Accept-Encoding': 'gzip'
        }
      };
    
      req.pipe(request(options)).pipe(res);
    });
    
    app.listen(4000, function () { 
      console.log('Example app listening on port 4000!') 
    });