2

I have written webservice using NodeJS and Express. Service is running on port 8090. Also I wrote frontend in AngularJS and running on port 8080.

Mongo has username and password stored of all users

When I login via HTML5/AngularJS frontend, the AngularJS app in turn calls the http post request of express. User is authenticated. And I set req.session.email = the email address of the user.

I even am able to return and check in console log of AngularJS that req.session.email was set correct in express

The problem is that I created an authentication function called "restrict" in Express to act as middleware function to give access to other get/post requests only if req.session.email is not undefined.

But even after session has been set, when this other get/post request of Express are calling by AngularJS app, this "restrict" function blocks the calls because it receives req.session.email as undefined

Both AngularJS and Express are on the same machine. But I don't think this is the problem.

Express Code Snippet

var url = 'mongodb://127.0.0.1:5555/contacts?maxPoolSize=2';
var mongojs = require('mongojs');
var db = mongojs(url,['data']);
var dbauth = mongojs(url,['users']);
// var request = require('request');
var http = require('http');

var express = require('express');
var cookieparser = require('cookie-parser');
var app = express();



var bodyParser = require('body-parser');
var session = require('express-session');

app.use(cookieparser());
app.use(session({secret:'v3ryc0mpl!c@t3dk3y', resave: false, saveUninitialized: true}));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));

var user_session;

app.all('*',function(req, res, next){

    res.header('Access-Control-Allow-Origin', '*');
    res.header('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS');
    res.header('Access-Control-Allow-Headers', 'Content-Type');
    next();

});

function restrict(req,res,next){


try{

    if(req.session.email){

        next();

    }
    else{

        res.send('failed');
        res.end();
    }

}
catch(err){

    res.send('failed');
    res.end();

}

};



app.post('/login',function(req,res){

//removed DB function from here to make the code look simple

        req.session.email = req.body.email;
        req.session.password = req.body.password;

});


app.get('/loggedin',restrict,function(req,res){


res.send(true);

});

AngularJS Function that calls the Express function to check session status

var resolveFactory = function ($q, $http, $location,LoginDetails) {

var deferred = $q.defer();


$http.get("http://127.0.0.1:8090/loggedin")
    .success(function (response) {
        if(response == true){
            deferred.resolve(true);
        }
        else
        {
            deferred.reject();
            LoginDetails.setemail('');
            LoginDetails.setpassword('');
            $location.path("/");

        }
    })
    .error(function (err) {
        deferred.reject();
        $location.path("/");
     });

return deferred.promise;

};

Fundamentally the AngularJS Resolve Function that I created should be successful but it is not. It is failing. Am using live-server to run HTML/AngularJS on my laptop and nodemon to run Express app

12
  • 1
    Can you share your express-session code please? Commented Nov 8, 2015 at 17:19
  • Thomas, I have edited the post and added the Express code also. Now you can see it again. Commented Nov 8, 2015 at 18:04
  • Have you checked that there is a cookie on your domain? And if so, are you sending your cookie in your headers to your Node server? Commented Nov 8, 2015 at 20:28
  • Cookie on the domain means? I am testing the product on my local machine. Also one more thing. If I test the concept using two app.get( ) functions, one which sets session and other just as a test get function with restrict function, it works. And req.session.email has value Commented Nov 8, 2015 at 20:41
  • Local development is not an issue. Open Google Chrome > browse to your domain (with port 8080) > open Developer Tools > Resources > Cookies. Is there a cookie from your app? Next, make a call. Back to Google Chrome > Network > find your call > click on your call > Headers > Check if cookie is send inside the headers Commented Nov 8, 2015 at 20:43

1 Answer 1

3

Ok! So the reason is that AngularJS is running on a different port 8080

Express was running on port 8090. This means that if AngularJS calls an API of Express, the session of Express would be lost unless Express allows session to be passed on to AngularJS and AngularJS calls the API of Express with {withCredentials: true} parameter set. Below are the changes that I had to make to get the session maintained when AngularJS and ExpressJS were running on different ports

In AngularJS makes sure any API you call of Express, it should have {withCredentials: true} like this

$http.get('http://expressdomainname:expressport/api',{withCredentials: true})

like wise in case you use $http.post the parameter {withCredentials: true} is important

Now on the Express side

make sure you have app setting like this

app.all('*',function(req, res, next){

//Origin is the HTML/AngularJS domain from where the ExpressJS API would be called
    res.header('Access-Control-Allow-Origin', 'http://localhost:8080');
    res.header('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS');
    res.header('Access-Control-Allow-Headers', 'Content-Type');

//make sure you set this parameter and make it true so that AngularJS and Express are able to exchange session values between each other 
    res.header("Access-Control-Allow-Credentials", "true");
    next();

});

Please feel free to ask me question in case you have about this topic. I spent days to resolve this.

Sign up to request clarification or add additional context in comments.

5 Comments

Hi Tahseen, I am also facing issue similar to which you have resolved. I am using node.js express and angular4. I updated the code as mentioned by you but with no success. My node.js express app is on port: 4000 and angular on port: 4200. Could you please check this for more info and advise me what I am doing wrong. stackoverflow.com/questions/44513553/…
Hi ijs, if you see above, i already wrote the solution too, after I figured it out. And it worked
Thanks Tahseen for your reply. Yes I did saw your solution and updated my code accordingly. However, it still doesn't work. I have also updated the link above........Thanks
You have done the part on NodeJS side. What about the AngularJS side ? Have you done that also ? GetCredentials : True ?
Yes, I have. In the service.ts file, I have this is what I am passing: return this.http.get('http://localhost:4000/depts/getDept', {withCredentials: true}).map(res => res.json());

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.