Droide
Droide

Reputation: 9

How can I get Nodejs twitter-passport behind proxy?

I'm testing twitter auth using passport-twitter's nodejs module. I already created my Twitter app and configured everything like especified by tutorials. The problem is that i'm behind a corporative proxy and as far as i know, node doesn't have any global proxy configuration and do not respect system proxy configuration. This is the output i get when i try to authenticate using twitter-passport:

InternalOAuthError: Failed to obtain request token at Strategy.OAuthStrategy._createOAuthError (/home/droid/WebstormProjects/passport-social-master/node_modules/passport-oauth1/lib/strategy.js:390:13) at /home/droid/WebstormProjects/passport-social-master/node_modules/passport-oauth1/lib/strategy.js:244:40 at /home/droid/WebstormProjects/passport-social-master/node_modules/oauth/lib/oauth.js:543:17 at ClientRequest. (/home/droid/WebstormProjects/passport-social-master/node_modules/oauth/lib/oauth.js:421:9) at emitOne (events.js:77:13) at ClientRequest.emit (events.js:169:7) at TLSSocket.socketErrorListener (_http_client.js:265:9) at emitOne (events.js:77:13) at TLSSocket.emit (events.js:169:7) at connectErrorNT (net.js:996:8) at doNTCallback2 (node.js:452:9) at process._tickCallback (node.js:366:17)

So far, i have tried to set a global tunnel using this:

var globalTunnel = require('global-tunnel');
globalTunnel.initialize({
  host: 'proxy.example.com',
  port: 8080
});

In this case, all I get is this message:

TypeError: Request path contains unescaped characters. at new ClientRequest (_http_client.js:54:11) at exports.request (http.js:31:10) at TunnelingAgent.http.request (/home/droid/WebstormProjects/passport-social-master/http-proxy.js:36:15) at TunnelingAgent.createSocket (/home/droid/WebstormProjects/passport-social-master/node_modules/tunnel/lib/tunnel.js:116:25) at TunnelingAgent.createSecureSocket [as createSocket] (/home/droid/WebstormProjects/passport-social-master/node_modules/tunnel/lib/tunnel.js:188:41) at TunnelingAgent.addRequest (/home/droid/WebstormProjects/passport-social-master/node_modules/tunnel/lib/tunnel.js:80:8) at new ClientRequest (_http_client.js:139:16) at exports.request (http.js:31:10) at Object.http.request (/home/droid/WebstormProjects/passport-social-master/http-proxy.js:36:15) at Object.globalTunnel._defaultedAgentRequest (/home/droid/WebstormProjects/passport-social-master/node_modules/global-tunnel/index.js:211:38) at Object.exports.request (https.js:173:15) at Object.globalTunnel._defaultedAgentRequest (/home/droid/WebstormProjects/passport-social-master/node_modules/global-tunnel/index.js:211:38) at exports.OAuth._createClient (/home/droid/WebstormProjects/passport-social-master/node_modules/oauth/lib/oauth.js:256:20) at exports.OAuth._performSecureRequest (/home/droid/WebstormProjects/passport-social-master/node_modules/oauth/lib/oauth.js:371:19) at exports.OAuth.getOAuthRequestToken (/home/droid/WebstormProjects/passport-social-master/node_modules/oauth/lib/oauth.js:542:8) at Strategy.OAuthStrategy.authenticate (/home/droid/WebstormProjects/passport-social-master/node_modules/passport-oauth1/lib/strategy.js:242:21)

I tried too the semi-global proxy(http://blog.shaunxu.me/archive/2013/09/05/semi-global-proxy-setting-for-node.js.aspx) by Shaun Xu. I imported the modified require.js everywhere but nothing is working. So i'm getting without options...

Upvotes: 1

Views: 692

Answers (1)

BlouBlou
BlouBlou

Reputation: 630

Your problem :

An old dependence in global-tunnel. see global-tunnel Issue #13

Quick solution : updating node-tunnel dependency to 0.0.4 does not seems to work at the end since using it will redirect all requests to internet proxy vs only authentication requests.


It's an 'old' post but if someone has a similar problem:

Use case :

  • Server is behind an internet proxy
  • Server access local resources via http/https, for example an elasticsearch server that must not be requested via proxy
  • You are using passportJs with Authentication module witch requires an external token validation, for exemple google on https://accounts.google.com

Problem :

  • By default NodeJs does not take into account any system proxy setting
  • Company proxy does not forward internal request via internet proxy (eg: if proxy is set, all requests are going to internet proxy, not anymore in intranet or localhost)

Solution not working :

Setting system env HTTP_PROXY or HTTPS_PROXY does not works for 2 reasons:

  • NodeJs ignore them
  • Proxy is set for all requests, and you want only one specific request to go through proxy

Using a global proxy (global-tunnel or similar) will fails because they redirect all requests adding their own Agent (request.options.agent) and thus will forward all your traffic to your proxy. Not desired.

A Solution :

Use a similar code as global-tunnel, adding a whitelist to proxy only some hostnames.

I ve implemented and tested this solution with success : see https://github.com/bloublou2014/httpx-proxy-agent-config

Usage example :

var proxy = require('httpx-proxy-agent-config');

proxy.install({
http_proxy: 'http://yourProxy:3128',
https_proxy: 'http://yourHttpsProxy:3218',
// example for passportjs Google OAuth2 + Google+
whitelist: ['www.google.com','accounts.google.com', '173.194.66.95', '74.125.192.95', '209.85.201.95', 'www.googleapis.com']
});

// try to access a page via http request :
var http = require('http');
http.get('http://www.google.com', function (response) { 
    var body = '';
    response.on('data', function (d) {
        body += d;
    });
    response.on('end', function () {
        console.log("Body=", body);
    });
});

// try to access a page via https request
var https = require('https');
https.get('https://www.google.com', function (response) {   
    var body = '';
    response.on('data', function (d) {
        body += d;
    });
    response.on('end', function () {
        console.log("Body=", body);
    });
});

Upvotes: 1

Related Questions