Node in Corporative Environment with NODESSPI - javascript

I developed a NODE API to serve data to Angular app. The original idea is to use NODESSPI for integrated authentication as we plan to run this on a corporative environment. CORS will be needed as the API Node will be hosted on a different domain.
I'm struggling to use NODESSPI for integrated authentication of the $HTTP requests.
To test it on my computer I've created a simple js file to instantiate a node server with express to run my angular app (I know it could be done without express, but it was faster to implement). It is running on Port 5001.
'use strict';
var express = require('express');
var http = require('http');
var path = require('path');
var morgan = require('morgan');
var errorhandler = require('errorhandler');
var app = express();
// all environments
app.set('port', process.env.PORT || 5001);
app.set('views', path.join(__dirname, 'views'));
app.engine('html', require('ejs').renderFile);
app.use(morgan('dev'));
// serve up static assets
app.use(express.static(path.join(__dirname, 'app')));
// development only
if ('development' === app.get('env')) {
app.use(errorhandler());
}
console.log('trying to start server...', path.join(__dirname, 'app'));
http.createServer(app).listen(app.get('port'), function () {
console.log('App server listening on port ' + app.get('port'));
});
My Angular code is on very early stage as its purpose is just prove the concept. Note I'm not specifying any kind of headers on my $http get.
main.controller.js
'use strict';
monthApp.controller('mainPageCtrl',
function mainPageCtrl($scope, $rootScope, $location, $rootElement, $q, $http) {
console.log("mainPageCtrl is in control");
$http({
url: 'http://localhost:3000/api/',
methof: 'GET'
})
.then(function(data){
console.log(data);
})
.catch(function(error){
console.log(error);
})
});
To run my NODE API simulating the server side, I'm also using Express and running it at the port 3000, here is the code:
//Lib Dependecies
var cookieParser = require("cookie-parser");
var bodyParser = require("body-parser");
var sql = require("seriate");
var cors = require("cors");
var express = require("express");
var path = require("path");
var Q = require("q");
var oracle = require("oracledb");
var restClient = require("node-rest-client").Client;
var nodeSSPI = require('node-sspi');
var ActiveDirectory = require("activedirectory");
//API Custom Modules Dependecies
var reservoirApi = require("./reservoirApi");
var ldapApi = require("./ldapApi");
var energyApi = require("./energyApi");
var PIApi = require("./PIApi");
//Express config
var app = express();
app.use ( cors() );
app.options('*', cors() );
app.use ( bodyParser.json() );
app.use ( bodyParser.urlencoded( {extended: true} ) );
app.use ( cookieParser() );
app.use ( express.static( __dirname + '/public') );
//Server config
var serverConfig = {port: 3000};
//Sql server config
var config = {
"server":"myserver",
"user":"myuser",
"password":"mypass",
"database":"mydatabase"
};
sql.setDefaultConfig(config);
//Setup endpoint routes
var router = express.Router();
//Basic Router Config
router.use(function(req, res, next){
//Integrated Authentication for Windows
var nodeSSPIObj = new nodeSSPI({
retrieveGroups: true
});
try{
nodeSSPIObj.authenticate(req, res, function(err){
res.finished || next();
});
}
catch(err)
{
res.status(500).send(JSON.stringify({status: 500, message: "URL mal formatada, verifique sua requisição HTTP", detail: err.message}));
}
});
router.get('/', function(req, res){
res.json({Message: 'Data Access API.', AuthUser: req.connection.user, AuthUserGroups: req.connection.userGroups });
});
app.use('/api', router);
//Modules End-Point registration
reservoirApi.register(router);
ldapApi.register(router);
energyApi.register(router);
PIApi.register(router);
//Start Server
app.listen(serverConfig.port);
console.log("SOA API Listening port at " + serverConfig.port)
The results are:
When using Chrome to reach the address: http://localhost:3000/api this works just fine. It detects my user account and return all windows groups I'm part of.
When running my angular code it returns:
Object {data: "", status: 401, config: Object, statusText: "Unauthorized"}
When testing with Postman it also works (with authorization type = 'No Auth')
When removing all NodeSSPI code from my Routers, I can receive data (I've tested with other endpoints on my angular app) so CORS is properly set at the server side.
Is there anything I'm missing on the Angular side? I'm struggling to move forward from here. Appreciate any help.

Ok, I finally got this working. The changes needed as follow:
At the client Angular app
You need to set withCredentials to true on $http requests.
$http({
url: 'http://localhost:3000/api',
method: 'GET',
withCredentials: true,
headers : {
'Content-Type' : 'application/json',
}
})
At the node server
Some response headers are needed in the response. Origin cannot be '*' and you need to allow credentials. If you need to allow dynamic origins you can find a way of doing it in the CORS documentation.
//Cors options
var corsOptions = {
origin: 'http://localhost:5001',
optionsSuccessStatus: 200,
credentials: true,
}
//Express config
var app = express();
app.use ( cors(corsOptions) );
app.use ( bodyParser.json() );
app.use ( bodyParser.urlencoded( {extended: true} ) );
app.use ( cookieParser() );
app.use ( express.static( __dirname + '/public') );

Related

Node, module usage structure

I've been trying to understand how to set up Stripe for my app but am having problems with the implementation of the module. Normally when using a module i would require it in the top of the file to be able to use it but I'm not sure how to do this here in the paymentController file or if i even need to. I imported the Stripe npm, so does that i mean that i can access it globally? Well as you see i'm quite new to this and would like to understand how to structure this so that the payments work.
app.js file:
angular.module('userApp', ['appRoutes', 'userControllers', 'userServices', 'ngAnimate', 'mainController', 'authServices', 'managementController', 'paymentController'])
.config(function($httpProvider) {
$httpProvider.interceptors.push('AuthInterceptors');
});
paymentController file:
angular.module('paymentController', [])
.controller('paymentCtrl', function($scope) {
var app = this;
});
Server.js file:
var express = require('express'); // ExperssJS Framework
var app = express(); // Invoke express to variable for use in application
var port = process.env.PORT || 8080; // Set default port or assign a port in enviornment
var morgan = require('morgan'); // Import Morgan Package
var mongoose = require('mongoose'); // HTTP request logger middleware for Node.js
var bodyParser = require('body-parser'); // Node.js body parsing middleware. Parses incoming request bodies in a middleware before your handlers, available under req.body.
var router = express.Router(); // Invoke the Express Router
var appRoutes = require('./app/routes/api')(router); // Import the application end points/API
var path = require('path'); // Import path module
var passport = require('passport'); // Express-compatible authentication middleware for Node.js.
var social = require('./app/passport/passport')(app, passport); // Import passport.js End Points/API
app.use(morgan('dev')); // Morgan Middleware
app.use(bodyParser.json()); // Body-parser middleware
app.use(bodyParser.urlencoded({ extended: true })); // For parsing application/x-www-form-urlencoded
app.use(express.static(__dirname + '/public')); // Allow front end to access public folder
app.use('/api', appRoutes); // Assign name to end points (e.g., '/api/management/', '/api/users' ,etc. )
mongoose.connect('mongodb://localhost:27017/tutorial', function(err) {
if (err) {
console.log('Not connected to the database: ' + err);
} else {
console.log('Successfully connected to MongoDB');
}
});
// Set Application Static Layout
app.get('*', function(req, res) {
res.sendFile(path.join(__dirname + '/public/app/views/index.html')); // Set index.html as layout
});
// Start Server
app.listen(port, function() {
console.log('Running the server on port ' + port); // Listen on configured port
});
I'd recommend following what's shown for Node in this Stripe tutorial:
https://stripe.com/docs/charges
Just like your other includes, you want something like this at the top of any JS file that will use the Stripe library:
var stripe = require('stripe')('sk_my_secret_key')
Then, elsewhere in the same file, you can call any Stripe library methods you need:
stripe.charges.create(…)
Of course, in production you'll want to build a proper 12 Factor app[1] and put your secrets in environment variables or configuration files.
[1] https://12factor.net/config

Data undefined at Node.js from AngularJS POST request

I am attempting to send a fairly simple POST request to my server using AngularJS. The request goes through and hits my controller on the back end, but for some reason req.data is showing up as undefined.
Front End Controller:
function CardDirectiveController($http, $scope) {
var self = this;
self.addToFavorites = function() {
let card = {
id: $scope.$id,
attack : $scope.attack,
cost: $scope.cost,
img: $scope.img,
name: $scope.name,
class: $scope.class,
rarity: $scope.rarity,
type: $scope.type
}
return $http({
method: 'POST',
url: '/card',
data: card
})
};
}
angular.module('cardDirective').controller('CardDirectiveController', CardDirectiveController);
Server
'use strict';
let express = require('express'),
path = require('path'),
router = require('./routes/sampleRouter'),
cardRouter = require('./routes/cardRouter');
let app = express();
// Serve any requests for static files (like index.html)
app.use(express.static(path.join(__dirname + '/public/')));
// Use any routing rules found in the router file
app.use('/', router);
app.use('/card', cardRouter)
app.listen(PORT, function() {
console.log('Application live and running on port: ' + PORT);
});
Router:
'use strict';
let express = require('express'),
cardController = require('./../controllers/cardController');
let router = express.Router();
router.route('/').post(cardController.postCard);
router.route('/:cardName').get(cardController.showCards);
module.exports = router;
Back End Controller
'use strict';
let cardController = {
showCards: showCards,
postCard: postCard
};
module.exports = cardController
function showCards(req, res) {
console.log('showCards ', req.params.cardName);
res.end()
}
function postCard(req, res) {
console.log('postCard ', req.url, req.method, req.data)
res.end()
}
The response I am getting in the console from making this request is postCard / POST undefined. Console logging the card object returns the expected result. I feel like I must be missing something obvious, but I've been stuck for a while now.
You need to use bodyParser middleware to parse request body.
Install the body-parser module:
$ npm install body-parser
Configure it in app.js :
var bodyParser = require('body-parser');
// parse application/json
app.use(bodyParser.json());
In your controller use req.body instead of req.data:
function postCard(req, res) {
console.log('postCard ', req.url, req.method, req.body);
res.end();
}
Please use body-parser in your app.js file.
Change your server.js file to following code
'use strict';
let express = require('express'),
path = require('path'),
router = require('./routes/sampleRouter'),
cardRouter = require('./routes/cardRouter'),
bodyParser = require('body-parser');
let app = express();
// Serve any requests for static files (like index.html)
app.use(express.static(path.join(__dirname + '/public/')));
// parse application/json
app.use(bodyParser.json());
// Use any routing rules found in the router file
app.use('/', router);
app.use('/card', cardRouter)
app.listen(PORT, function() {
console.log('Application live and running on port: ' + PORT);
});

Return different HTTP response codes for a REST End Point

I'm using express to serve the REST API endpoints for a mocked backend. For one of the endpoints, I'd like to be able to return different http response codes, with the other endpoints continuing to return 200. My code currently looks something like this:
var port = 32000;
var express = require("express");
var bodyParser = require("body-parser");
var app = express();
app.use( bodyParser.json() );
app.use( bodyParser.urlencoded({ extended: true }) );
var setHeaders = function(req, res) {
res.setHeader("Content-Type", "application/json");
res.setHeader("Access-Control-Allow-Origin", "http://localhost:2000");
};
app.get("*", setHeaders);
app.listen(port, function () {});
app.get("my/enpoint/one", function(req, res){
res.send('hello');
});
You can use res.status to set the HTTP code:
res.status(404).send('Bad Request');

How to fetch images from node.js server's folder in URL?

Does anybody know how to fetch images from node.js server's folder in URL?
In my folder structure I have folder data and inside there is subfolder img with image. I want to access this image with URL, like this:
http://localhost:3000/data/img/default.jpg
but when I enter it into browser I always get this error:
Page Not Found /data/img/default.jpg is not a valid path.
server.js:
'use strict';
/**
* Module dependencies.
*/
var init = require('./config/init')(),
config = require('./config/config'),
mongoose = require('mongoose');
var express = require('express');
/**
* Main application entry file.
* Please note that the order of loading is important.
*/
// Bootstrap db connection
var db = mongoose.connect(config.db, function(err) {
if (err) {
console.error('\x1b[31m', 'Could not connect to MongoDB!');
console.log(err);
}
});
// Init the express application
var app = require('./config/express')(db);
// Bootstrap passport config
require('./config/passport')();
app.use(express.static('data/img'));
// Start the app by listening on <port>
app.listen(config.port);
// Expose app
exports = module.exports = app;
// Logging initialization
console.log('MEAN.JS application started on port ' + config.port);
express.js:
'use strict';
/**
* Module dependencies.
*/
var express = require('express'),
morgan = require('morgan'),
bodyParser = require('body-parser'),
session = require('express-session'),
compress = require('compression'),
methodOverride = require('method-override'),
cookieParser = require('cookie-parser'),
helmet = require('helmet'),
passport = require('passport'),
mongoStore = require('connect-mongo')({
session: session
}),
flash = require('connect-flash'),
config = require('./config'),
consolidate = require('consolidate'),
path = require('path');
module.exports = function(db) {
// Initialize express app
var app = express();
// Globbing model files
config.getGlobbedFiles('./app/models/**/*.js').forEach(function(modelPath) {
require(path.resolve(modelPath));
});
// Setting application local variables
app.locals.title = config.app.title;
app.locals.description = config.app.description;
app.locals.keywords = config.app.keywords;
app.locals.facebookAppId = config.facebook.clientID;
app.locals.jsFiles = config.getJavaScriptAssets();
app.locals.cssFiles = config.getCSSAssets();
// Passing the request url to environment locals
app.use(function(req, res, next) {
res.locals.url = req.protocol + '://' + req.headers.host + req.url;
next();
});
// Should be placed before express.static
app.use(compress({
filter: function(req, res) {
return (/json|text|javascript|css/).test(res.getHeader('Content-Type'));
},
level: 9
}));
// Showing stack errors
app.set('showStackError', true);
// Set swig as the template engine
app.engine('server.view.html', consolidate[config.templateEngine]);
// Set views path and view engine
app.set('view engine', 'server.view.html');
app.set('views', './app/views');
// Environment dependent middleware
if (process.env.NODE_ENV === 'development') {
// Enable logger (morgan)
app.use(morgan('dev'));
// Disable views cache
app.set('view cache', false);
} else if (process.env.NODE_ENV === 'production') {
app.locals.cache = 'memory';
}
// Request body parsing middleware should be above methodOverride
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(bodyParser.json());
app.use(methodOverride());
// Enable jsonp
app.enable('jsonp callback');
// CookieParser should be above session
app.use(cookieParser());
// Express MongoDB session storage
app.use(session({
saveUninitialized: true,
resave: true,
secret: config.sessionSecret,
store: new mongoStore({
db: db.connection.db,
collection: config.sessionCollection
})
}));
// use passport session
app.use(passport.initialize());
app.use(passport.session());
// connect flash for flash messages
app.use(flash());
// Use helmet to secure Express headers
app.use(helmet.xframe());
app.use(helmet.xssFilter());
app.use(helmet.nosniff());
app.use(helmet.ienoopen());
app.disable('x-powered-by');
// Setting the app router and static folder
app.use(express.static(path.resolve('./public')));
// Globbing routing files
config.getGlobbedFiles('./app/routes/**/*.js').forEach(function(routePath) {
require(path.resolve(routePath))(app);
});
// Assume 'not found' in the error msgs is a 404. this is somewhat silly, but valid, you can do whatever you like, set properties, use instanceof etc.
app.use(function(err, req, res, next) {
// If the error object doesn't exists
if (!err) return next();
// Log it
console.error(err.stack);
// Error page
res.status(500).render('500', {
error: err.stack
});
});
// Assume 404 since no middleware responded
app.use(function(req, res) {
res.status(404).render('404', {
url: req.originalUrl,
error: 'Not Found'
});
});
return app;
};
It's like you have already set your data/img folder as a static folder in the line below:
app.use(express.static('data/img'));
In that case, you should be accessing images placed in the static folder above using below url:
http://localhost:3000/default.jpg
I will however advice you use Node's global variable __dirname to indicate the root of the static folder but this depends on where your server.js is located within your file structure.
The js file containing the snippets below is located in the root and I have /data/img folder from the root as well and I am able to retrieve the image using /image name.
var express = require('express');
var app = express();
app.use(express.static(__dirname + '/data/img'));
app.listen(3500, function () {
console.log('Express server is listening, use this url - localhost:3500/default.png');
});
See if this helps you. If it does, make sure you know the reason for using the __dirname global variable name.
SO1

CORS header not working in MEAN stack application

I am developing an application using the MEAN stack (Node.js, Express, AngularJS, and Mongoose). I have a basic understanding of the two. My API is running on a different port from my frontend, and because of this, I've included the CORS header in my API file. However, Chrome is still giving me this error:
XMLHttpRequest cannot load http://localhost:9000/#/.
No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access.
This is the header I've included in my API:
app.all('*', function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With");
next();
});
I have no idea where I'm going wrong. If it helps at all, I'm trying to load a user object in order to display information on a profile page. This is the code from my Profile Controller:
angular.module('angTestApp')
.controller('ProfileCtrl', function ($scope, $http) {
$http.get('http://localhost:8080/profile')
.success(function (user) {
$scope.user = user;
console.log(user);
});
});
EDIT
Here's my server.js file if that helps:
// server.js
// BASE SETUP
// =============================================================================
// call the packages we need
var express = require('express'); // call express
var cors = require('cors');
var app = express(); // define our app using express
var bodyParser = require('body-parser');
var mongoose = require('mongoose');
mongoose.connect('mongodb://test:test#novus.modulusmongo.net:27017/a3pemoGa')
var classroom = require('./app/models/classroom');
var article = require('./app/models/article');
var user = require('./app/models/user');
//From Tutorial
var passport = require('passport');
var flash = require('connect-flash');
var morgan = require('morgan');
var cookieParser = require('cookie-parser');
var session = require('express-session');
// configure app to use bodyParser()
// this will let us get the data from a POST
app.use(bodyParser());
app.use(cors());
//app.use(express.static(__dirname + '/public'));
var port = process.env.PORT || 8080; // set our port
// ROUTES FOR OUR API
// =============================================================================
// more routes for our API will happen here
// REGISTER OUR ROUTES -------------------------------
//From tutorial
// set up our express application
require('./app/config/passport')(passport); // pass passport for configuration
app.use(morgan('dev')); // log every request to the console
app.use(cookieParser()); // read cookies (needed for auth)
app.use(bodyParser.json()); // get information from html forms
app.set('view engine', 'ejs'); // set up ejs for templating
app.use(session({ secret: 'ilovescotchscotchyscotchscotch' })); // session secret
app.use(passport.initialize());
app.use(passport.session()); // persistent login sessions
app.use(flash()); // use connect-flash for flash messages stored in session
require('./app/API/routes')(app, passport);
//require('./app/API/general');
// START THE SERVER
// =============================================================================
app.listen(port);
console.log('Magic happens on port ' + port);
//exports = module.exports = app;
i resolved the cors issue with tricky solution . first create the the route of scrape like this with require "REQUEST" npm
app.get('/scrape', function (req, res) {
console.log("=============================Scrape =========================")
var url = req.body.url;
request(url, function(error, response, html){
if(!error){
res.send(html)
}
});
and in the frontend use like this
$http.get("/scrape", {
params: { "url": "http://localhost:8080/profile" }
});

Categories