Handle sessions using Express-Sessions - angularjs

Im new working with nodeJS. I have a webpage (with AngularJS) in a AWS ec2-server that gets information from a nodeJS(Express) server. Im trying to keep logged my users once they log in, even if they refresh. I have read that I can do that using express-sessions. This is my code in the client side:
$http({
method: 'GET',
url: 'http://ec2-bla-bla-bla.compute.amazonaws.com:8080/verifySession'
}).then(function successCallback(response) {
console.log(response);
}, function errorCallback(response) {
});
//And here i have the http post method that call login webservice
This is my server code:
var express = require('express');
var bodyParser = require('body-parser');
var path = require("path");
var session = require('express-session');
var app = express();
var loginManual = require('./model/ws_package/loginManual.js');
var sess;
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
app.use(session({secret: 'ssshhhhh'}));
app.use( bodyParser.json() ); // to support JSON-encoded bodies
app.use(bodyParser.urlencoded({ // to support URL-encoded bodies
extended: true
}));
app.use(express.static(path.join(__dirname + '/view')));
app.get('/verify',function(req,res){
sess=req.session;
if(sess.email){
res.send({state:1,email: sess.email});
}
else{
res.send({state:-1,email: "NE"});
}
});
app.post("/login",function(req, res)
{
var userEmail; //here is myuseremail
//I have some login code here and if it is successful:
sess = req.session;
sess.email=userEmail;
res.send(response);
}
);
It is not working, but when I tested /login and /verify webservices, directly in my browser, writing the url, it works. Another thing I discovered is that everytime I make a new $http method from angular, my session id changes, so I dont know if that could mean something that affects me. How can I solve this? Sorry for my english, i am Costa Rican! Thanks!

Related

CORS error occurs when HTTPS applied to the my server using Let's Encrypt

I have a Digital Ocean Linux server.
I deployed my REST API and also front end in the same server.
My Back End runs using Node.JS and front end using AngularJS.
After enabling HTTPS, I changed all the REST URLs into HTTPS.
Like this :
var mainHost = "https://xxx.xxx.xxx.xx:7000/api";
Now I'm getting this CORS error :
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://xxx.xxx.xxx.xx:7000/api/user_manage/login. (Reason: CORS request did not succeed).
I am using Node.JS CORS plugin also.
var cors = require('cors');
var app = express();
app.use(cors());
This started when I added HTTPS and I tried many things. Including changing the .htaccess and adding some meta tags. Still no good. What is the reason for this ? Why CORS error comes after adding HTTPS ? Please help me to solve this.
This is the controller call for the service layer :
sessionService.getAllSessions(100, 0).then(function (data) {
console.log(data);
$scope.allSessions = data.data;
});
And this is the service layer :
getAllSessions: function (limit, offset) {
return $http({
method: "GET",
url: host.session_manage + '/session/' + limit + '/' + offset
}).then(function (response) {
return response.data;
});
}
I'm not using headers in the service call as you can see in the above section.
This is the server code snippet :
var express = require("express");
var bodyParser = require("body-parser");
var morgan = require("morgan");
var config = require("./config");
// var cors = require('cors');
var app = express();
// app.use(cors());
// app.use(cors({
// origin: 'https://xxxxxx.com'
// }));
app.use(function (req, res, next) { res.header("Access-Control-Allow-Origin", "*"); res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); next(); });
app.set('views', './app/views');
app.set('view engine', 'pug');
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(morgan('dev'));
var session = require('./app/routes/session')(app, express);
app.use('/api/session_manage', session);
app.listen(config.port, function (err) {
if (err) {
console.log(err);
} else {
console.log("localhost:7000");
}
});
Thank you guys.
You are in production you don't want to allow CORS access for all origins but if you need to allow cross origin requests from some specified host(s) you can do add the following code:
server.use(cors({
origin: 'https://example.com'
}));
This will allow https://example.com to send cross origin requests to your Express server without the Same Origin Policy getting in the way.
You can also enable CORS for a single Express route
server.get('/endpoint', cors(), function (req, res, next) {
res.json({msg: 'This has CORS-enabled for only this route: /endpoint'})
})
If you want to allow multiple origins you need to use a function (for origin instead of a string) that dynamically set the CORS header depending on the origin making the request and a white list that you specify which contains the origin to allow.
var whitelist = ['http://example.com', 'http://othersite.com'];
var options = { origin: function (origin, callback) {
if (whitelist.indexOf(origin) !== -1) {
callback(null, true)
} else {
callback(new Error('Not allowed by CORS'))
}
}
}
server.use(cors(options))

req.body empty Node.js

this is my angular controller code where im passing certificationid and userid to delete certification details of a user.
$scope.deleteCertification = function(CertificationId){
var userName = $scope.userId;
var certificationId = CertificationId;
var deleteCertificationInfo = {'userName': userName, 'certificationId':certificationId};
console.log('deleteCertificationInfo*******');
console.log(deleteCertificationInfo);
userProfileService.deleteUserCertificationInfo(deleteCertificationInfo).then (function(data){
console.log($scope.Certification);
console.log('Certification Deleted');
})
}
userProfileData.deleteUserCertificationInfo = function (deleteCertificationInfo) {
var deferred = $q.defer();
$http.delete('/api/profileUpdate/deleteUserCertification', deleteCertificationInfo, {
}).success(function(res){
var deletedUserCertificationResult = res;
deferred.resolve(deletedUserCertificationResult);
$log.debug('response from certification API:['+JSON.stringify(deletedUserCertificationResult)+']');
}).error(function(err){
deferred.reject(err);
});
return deferred.promise;
};
that is written in userProfileService to call the delete API.
but in my node controller function req.body is empty. not sure where it is going. im consoling the data in front end before sending it to service . it's displayed then. but why the req.body is getting empty?
Even though you haven't posted the Express portion of your app, the best guess here is that you're not using body-parser. body-parser is an Express middleware that is required when using req.body, without adding it to your Express app, you won't be able to parse any incoming JSON or url-encoded request bodies.
const express = require('express');
const bodyParser = require('body-parser');
const port = process.env.PORT || 3000;
let app = express();
app.use(bodyParser.json()); // this will parse Content-Type: application/json
app.use(bodyParser.urlencoded({ extended: true })); // this will parse Content-Type: application/x-www-form-urlencoded
// Your routes go here
app.listen(port);
try with the follwing code, its worked for me , you shoud have this code in your node service js file
app.use(bodyParser.json()); // to support JSON-encoded bodies
app.use(bodyParser.urlencoded({ // to support URL-encoded bodies
extended: true
}));

Session undefined in Express when AngularJS as frontend

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
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.

enabling cors in meanjs rest api server

I am creating an api (server side) based on Meanjs.org latest version (0.4.0) and i managed to pull off only the MEN part and create one in http://localhost:3000/api
as the frontend part i created an Angularjs in http://localhost:4000/
and then i run both application using (P)ackage (M)anager 2
I am trying to create a user by sending user credentials using $resource like this
angular.module('users').factory('AuthenticationResource', ['$resource',
function($resource) {
return $resource('http://localhost:3000/api/auth/signup', {}, {
post: {
method: 'POST'
}
});
}
]);
...
//In my controller
$scope.signup = function() {
AuthenticationResource.post($scope.credentials, function(response) {
$scope.authentication.user = response;
$state.go($state.previous.state.name || 'home', $state.previous.params);
});
};
While in my server side's express.js
'use strict';
var config = require('../config'),
express = require('express'),
...
cors = require('cors');
...
module.exports.initModulesServerRoutes = function(app) {
// Globbing routing files
config.files.server.routes.forEach(function(routePath) {
require(path.resolve(routePath))(app);
});
};
module.exports.initCorsOption = function(app){
app.options('*', cors());
};
module.exports.init = function(db) {
// Initialize express app
var app = express();
...
// Initialise Cors options
this.initCorsOption(app);
// Initialize modules server routes
this.initModulesServerRoutes(app);
...
return app;
};
I am using node cors package to enable cors and just do app.options('*', cors()); to enable pre-flight across-the-board
But when i am trying to do a POST to http://localhost:3000/api/auth/signup i can see that my user is being saved to the database just fine but it doesn't give me any response and chrome console is giving me this
XMLHttpRequest cannot load http://localhost:3000/api/auth/signup. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:4000' is therefore not allowed access.
What did i miss?
I think you are missing app.use before all your routes:
Only express:
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
If you are using npm cors:
app.use(cors());

In Express.js with body-parser the value of request.body is undefined

I'm having a problem I cannot diagnose.
On a server, I have a simple URL handler using Express.js:
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var multer = require('multer');
app.configure(function() {
app.use(app.router);
app.use(bodyParser.json()); // see: http://expressjs.com/api.html#req.body
app.use(bodyParser.urlencoded({
extended: true
}));
});
app.post('/submit', function (req, res) {
console.log(req.body);
});
On client side, there's a form which is handled with Angular controller:
$scope.submit = function () {
// $http.post('/submit', $scope.data); // POST request to send data to the server
$http({
method: 'POST',
url: '/submit',
data: $scope.data
});
console.log('POST /submit ' + JSON.stringify($scope.data));
};
In browser's console everything is fine: $scope.data is valid; Node.js also responds with console.log, as expected, but writes undefined which means that, well, request.body is undefined.
What do I do wrong? How can I fix it?
If you're using Express 3 you shouldn't have to use the body-parser module as it is already bundled with Express 3 as express.bodyParser. You're getting an empty body because you're putting app.use(app.router) before the body parser.
app.configure(function() {
app.use(express.bodyParser());
app.use(app.router);
});
Which is why your other solution is working:
app.post('/submit', bodyParser.json(), function (req, res) {
Well, I just came up with solution, and it works. Here the app.post using body-parser is explained in few words. So I changed POST request handler definition to:
app.post('/submit', bodyParser.json(), function (req, res) {
console.log(req.body);
});
And now not only console.log(req.body) returns valid data, but it's deserialized into JSON correctly on the server without any extra code (which is, well, expected from Angular+Node pair).

Resources