Search code examples
node.jsember.jsexpressnode-http-proxy

Authentication and cross domain error from a Node - Express application


I am developing an application using ember.js which is running over node.

Now, I have to call some external webservices and construct my home page accordingly (based on the webservice response).

  • These webservices are running in some external server (different domain). Currently I am running my website from a local environment.
  • Authentication: Only after providing a valid credentials, user can access these webservices. That is, If I try to access this webservice from a browser, first it will ask to provide a username and password. If these credentials are valid (server side validation), it will return a response json.

My app.js code is as follows:

var express = require('express');
var routes = require('./routes');
var http = require('http');
var path = require('path');

var app = express();

// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.cookieParser('your secret here'));
app.use(express.session());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));

// development only
if ('development' == app.get('env')) {
    app.use(express.errorHandler());
}

app.get('/', routes.index);

http.createServer(app).listen(app.get('port'), function(){
    console.log('Express server listening on port ' + app.get('port'));
});

Home page code (for simplicity, I have removed all its view and just calling my external webservice on page load)

<html>
<head>
    <title>Lets think..</title>
    <script src="./javascripts/libs/handlebars-1.0.0.js"></script>
    <script src="./javascripts/libs/jquery-1.9.1.js"></script>
    <script src="./javascripts/libs/ember-1.1.2.js"></script>
    <script>
        window.App = Ember.Application.create();
    </script>

    <script>
        $(window).load(function(){
            $.ajax({
                type: 'GET',
                url: 'http://vpn.domain_name.com/myServer/WebService/json/getInfo',
                data: {username: "user_name",password: "my_password"},
                success: function (data) {
                    console.log('sucess');
                },
                failure: function(error){
                    console.log('error');
                }
            });
        });
    </script>
</head>
<body>

</body>
</html>

As said above, I was able to access the below webservice (http://vpn.domain_name.com/myServer/WebService/json/getInfo) successfully from a browser (after credentials validation).

However, when I try to access it through code, I am retrieving the below error: On debugging through firebug:

"NetworkError: 401 Unauthorized - http://vpn.domain_name.com/myServer/WebService/json/getInfo?username=user_name&password=my_password"

On debugging through Google Chrome console:

XMLHttpRequest cannot load http://vpn.domain_name.com/myServer/WebService/json/getInfo?username=user_name&password=my_password. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access.

I am not sure whether the above errors are due to cross domain access or http basic authentication error.

I tried with solutions suggested in How to allow CORS? and http://nthloop.com/blog/local-dev-with-nodejs-proxy/

However, I was not able to retrieve a proper response from my code. Can anyone please guide me on this.

Thank You.


Solution

  • I have initially used JSONP, because it is really a simply trick to overcome XMLHttpRequest same domain policy. However, the webservices which I am accessing raised few issues with JSONP data type (basic http athentication fails for first time and response throws a strange error SyntaxError: missing ; before statement). As I don't have much control over webservices to work with JSONP, thought to drop JSONP option and proceeded with http-proxy method way of handling the cross domain issue.

    Made following changes in client code and now I was able to access webservices successfully.

    (1) Installed http-proxy npm

    (2) Added following lines in app.js

    var httpProxy = require('http-proxy');
    
    var endpoint  = {
        host:   'IP_ADDRESS_OR_DOMAIN_NAME', //of webservice
        port:   80, 
        prefix: '/myServer/WebService/json'  //all my webservices are accessed through this path
    }
    
    app.use(function(req, res) {
        if (req.url.indexOf(endpoint.prefix) === 0) {
            proxy.proxyRequest(req, res, endpoint);
        }
    });
    

    (3) My ajax call will be:

    $(window).load(function(){
                $.ajax({
                    type: 'GET',
                    url: '/myServer/WebService/json/getInfo',
                    username: "user_name",
                    password: "password",
                    success: function (data) {
                        console.log('sucess');
                        console.log(data);
                    },
                    failure: function(error){
                        console.log('error');
                    }
                });
            });
    

    Here: /getInfo is the webservice (with basic http authentication).

    Hope this helps!

    Thanks.