Is this Node (Express) implementation secure? - javascript

Some questions:
Is this implementation of Passport for Node.js (Express) secure?
Is it a correct implementation of REST?
Can I store state in the session in this way?
/************************************
* Module dependencies.
************************************/
var express = require('express')
, passport = require('passport')
, BasicStrategy = require('passport-http').BasicStrategy
, crypto = require('crypto')
, http = require('http')
, path = require('path')
, fs = require('fs')
, app = express()
, service = require('./service');
var privateKey = fs.readFileSync('privatekey.pem').toString();
var certificate = fs.readFileSync('certificate.pem').toString();
var credentials = crypto.createCredentials({key: privateKey, cert: certificate});
/************************************
* Passport
************************************/
// User object supplied by MongoDB from the `service` object
//
// {
// id: 1,
// password: 'otherTestPass',
// salesmanId: 'A015',
// email: 'otheruser#email.com'
// }
passport.use(new BasicStrategy(
function(username, password, done) {
User.findOne({ username: username }, function (err, user) {
if (err) { return done(err); }
if (!user) { return done(null, false); }
if (!user.validPassword(password)) { return done(null, false); }
return done(null, user);
});
}
));
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user) {
done(err, user);
});
});
/************************************
* Config
************************************/
// all environments
app.set('port', process.env.PORT || 8000);
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.cookieParser());
app.use(express.bodyParser());
app.use(express.session({ secret: 'keyboard cat' })); // would normally have a randomly generated string
app.use(passport.initialize());
app.use(passport.session());
app.use(passport.authenticate('basic', {session: true}));
app.use(express.compress());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'dist'))); // backbone SPA that talks to the '/api/' routes
// development only
if ('development' == app.get('env')) {
app.use(express.errorHandler());
}
/************************************
* Routes
************************************/
app.get('/api/session/user', function(req,res){
var user = req.user;
delete user.password;
res.json(user);
});
app.get('/api/customers', function(req,res){
service.findAllCustomersBySalesmanId(req.user.salesmanId, function(result){
res.json(result);
});
});
app.get('/api/products', function(req,res){
service.findAllProducts(function(result){
res.json(result);
});
});
app.get('/api/orders', function(req,res){
service.findAllOrders(function(result){
res.json(result);
});
});
// ... other routes
/************************************
* Server Start
************************************/
http.createServer(app)
.setSecure(credentials)
.listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
}
);
Extra credit to anyone that can suggest:
Good way of moving the api routes to a different file and 'mounting' them at /api/ as part of the middleware configuration.
Internally securing the app by checking if a user is allowed to perform a certain operation.

Related

steam passport implementation, convert from express to nestjs

I've started to convert express project to nestjs. How should it work in Nestjs. Here is working code from Express.
(Code below just redirects to steam sign-in page)
/* eslint-disable space-before-function-paren */
// Require all the installs
var express = require('express');
var passport = require('passport');
var session = require('express-session');
var passportSteam = require('passport-steam');
var SteamStrategy = passportSteam.Strategy;
var app = express();
// Let's set a port
var port = 4000;
// Spin up the server
app.listen(port, () => {
console.log('Listening, port ' + port);
});
// Set up the SteamStrategy
// Required to get data from user for sessions
passport.serializeUser((user, done) => {
done(null, user);
});
passport.deserializeUser((user, done) => {
done(null, user);
});
// Initiate Strategy
passport.use(
new SteamStrategy(
{
returnURL: 'http://localhost:' + port + '/api/auth/steam/return',
realm: 'http://localhost:' + port + '/',
apiKey: 'My API key',
},
function (identifier, profile, done) {
process.nextTick(function () {
profile.identifier = identifier;
return done(null, profile);
});
}
)
);
app.use(
session({
secret: 'Whatever_You_Want',
saveUninitialized: true,
resave: false,
cookie: {
maxAge: 3600000,
},
})
);
app.use(passport.initialize());
app.use(passport.session());
// Routes
app.get('/', (req, res) => {
res.send(req.user);
});
app.get(
'/api/auth/steam',
passport.authenticate('steam', { failureRedirect: '/' }),
function (req, res) {
res.redirect('/');
}
);
app.get(
'/api/auth/steam/return',
passport.authenticate('steam', { failureRedirect: '/' }),
function (req, res) {
res.redirect('/');
}
);
The question is how to implement same in the nestjs???
Or if I want to implement middlewares for passport lib (serializeUser, deserializeUser), how should it happen, in nest official docs I found this examples of custom middlewares
export function logger(req: Request, res: Response, next: NextFunction) {
console.log(`Request...`);
next();
};
But how I should use passport middlware

Express / Passport SAML Authentication Redirects Leading to Infinite Loop

Trying to use passport-saml connecting to ADFS.
The SAML Response is coming back with Successful status codes.
We get the following success code back:
"<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success" /></samlp:Status>"
But our Passport IsAuthenicated is always generating a false.
I have listed out all of our files used for this below and would appreciate any help.
server.js file:
const express = require('express');
const http = require('http');
const path = require('path');
const passport = require('passport');
const morgan = require('morgan');
const cookieParser = require('cookie-parser');
const bodyParser = require('body-parser');
const session = require('express-session');
const errorhandler = require('errorhandler');
var env = process.env.NODE_ENV || 'development';
const config = require('./config/config')[env];
console.log('Using configuration', config);
require('./config/passport')(passport, config);
var app = express();
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(cookieParser());
app.enable('trust proxy'); // add this line
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
app.use(session(
{
resave: true,
saveUninitialized: true,
secret: 'default',
proxy: true // add this line
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(morgan('combined'));
function ensureAuthenticated(req, res, next) {
if (//req.isAuthenticated()
true
) {
console.log('req.isAuthenticated = ' + req.isAuthenticated());
return next(); }
else{
console.log('req.isAuthenticated = ' + req.isAuthenticated());
res.redirect('/login');
}
}
app.set('port', config.app.port);
require('./config/routes')(app, config, passport);
//ensure that ensureAuthenticated is in the get function call before master build
//ie app.get('/*', ensureAuthenticated, (req, res)
app.use(express.static(path.join(__dirname, 'public')));
app.get('/*', ensureAuthenticated, (req, res) => {
res.sendFile(path.join(__dirname, 'public/index.html'));
});
app.listen(app.get('port'), function () {
console.log('Express server listening on port ' + app.get('port'));
});
routes.js
module.exports = function (app, config, passport) {
app.get('/', function (req, res) {
res.redirect('/home')
});
app.get('/login',
passport.authenticate(config.passport.strategy,
{
successRedirect: '/',
failureRedirect: '/login'
})
);
app.post('/',
passport.authenticate(config.passport.strategy,
{
failureRedirect: '/',
failureFlash: true
}),
function (req, res) {
res.redirect('/');
}
);
app.get('/logout', function (req, res) {
req.logout();
// TODO: invalidate session on IP
res.redirect('https://redrectsite.com/?wa=signout1.0');
});
};
config.js
module.exports = {
development: {
app: {
name: 'Passport SAML strategy example',
port: process.env.PORT || 80
},
passport: {
strategy: 'saml',
saml: {
callbackUrl: process.env.SAML_CALLBACK_URL || 'https://oursite.com',
entryPoint: process.env.SAML_ENTRY_POINT || 'https://oursite.com/adfs/ls/idpinitiatedsignon',
issuer: process.env.SAML_ISSUER || 'https://oursite.com',
identifierFormat: null,
signatureAlgorithm: 'sha256',
authnContext: 'http://schemas.microsoft.com/ws/2008/06/identity/authenticationmethod/windows',
disableRequestedAuthnContext: true
//cert: process.env.SAML_CERT || null
}
}
}
};
passport.js
const SamlStrategy = require('passport-saml').Strategy;
module.exports = function (passport, config) {
passport.serializeUser(function (user, done) {
done(null, user);
});
passport.deserializeUser(function (user, done) {
done(null, user);
});
passport.use(new SamlStrategy(
{
callbackUrl: config.passport.saml.callbackUrl,
entryPoint: config.passport.saml.entryPoint,
issuer: config.passport.saml.issuer,
cert: config.passport.saml.cert,
identifierFormat: config.passport.saml.identifierFormat,
signatureAlgorithm: config.passport.saml.signatureAlgorithm,
authnContext: config.passport.saml.authnContext,
disableRequestedAuthnContext: config.passport.saml.disableRequestedAuthnContext
},
function (profile, done) {
return done(null,
{
id: profile.uid,
email: profile.email,
displayName: profile.cn,
firstName: profile.givenName,
lastName: profile.sn
});
})
);
};
I had a similar issue. If you look at what isAuthenticated() does, it's actually just checking a property within the request.session object.
https://github.com/jaredhanson/passport/blob/2327a36e7c005ccc7134ad157b2f258b57aa0912/lib/http/request.js#L86
req.isAuthenticated = function() {
var property = 'user';
if (this._passport && this._passport.instance) {
property = this._passport.instance._userProperty || 'user';
}
return (this[property]) ? true : false;
};
I'm not sure if it's passport or express-session, but once you get to the authentication method, the user object is stored at request.session.passport.user so if you like, you can directly verify that it's non-null instead of using the packaged isAuthenticated() method, which seems to check the wrong path.
My code started working after changing it to the following.
if (_.get(req, 'session.passport.user', null)) {
return next();
}
(lodash _.get for easier null-checking of the nested properties)

Node.js Passport Authentication - log is not defined error

I am working on user login page with node.js, passport, and postgres. I thought I got user authentication working. However, when I try to change pages I get this error and my server won't load anything. {"message":"log is not defined","error":{}}. I have been stuck on this error for hours now and can't figure out what is causing it. I am guessing that the session is somehow getting messed up but I could be wrong. I am hoping someone knows the answer. Here is my relevant code.
I am extremely new to web development and because of that I am sure it is probably something simple I am missing.
main-config.js
(function(appConfig) {
'use strict';
// *** main dependencies *** //
const path = require('path');
const cookieParser = require('cookie-parser');
const bodyParser = require('body-parser');
const session = require('express-session');
const flash = require('connect-flash');
const morgan = require('morgan');
const nunjucks = require('nunjucks');
const passport = require('passport');
// *** view folders *** //
const viewFolders = [
path.join(__dirname, '..', 'views')
];
// *** load environment variables *** //
require('dotenv').config();
appConfig.init = function(app, express) {
// *** view engine *** //
nunjucks.configure(viewFolders, {
express: app,
autoescape: true
});
app.set('view engine', 'html');
// *** app middleware *** //
if (process.env.NODE_ENV !== 'test') {
app.use(morgan('dev'));
}
app.use(cookieParser());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(session({
secret: 'anything',
resave: false,
saveUninitialized: true
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(flash());
app.use(express.static(path.join(__dirname, '..', '..', 'client')));
};
})(module.exports);
local.js
passport.use(new LocalStrategy({
usernameField: 'email',
passwordField: 'password'
},
(username, password, done) => {
return db.one("SELECT * " +
"FROM Users " +
"WHERE Email=$1", [username])
.then((result)=> {
return done(null, result);
})
.catch((err) => {
return done(null, false, {message:'Wrong user name or password'});
});
}));
passport.js
module.exports = () => {
passport.serializeUser((user, done) => {
done(null, user.userid);
});
passport.deserializeUser((id, done)=>{
log.debug("deserialize ", id);
db.one("SELECT * FROM User " +
"WHERE user_id = $1", id)
.then((user)=>{
done(null, user);
})
.catch((err)=>{
done(new Error(`User with the id ${id} does not exist`));
})
});
};
auth.js
router.post('/login', authHelpers.loginRedirect, (req, res, next) => {
passport.authenticate('local', (err, user, info) => {
if (err) { handleResponse(res, 500, 'error'); }
if (!user) {
console.log("User Not Found");
handleResponse(res, 404, 'User not found');
}
if (user) {
req.logIn(user, function (err) {
if (err) { handleResponse(res, 500, 'error'); }
handleResponse(res, 200, 'success');
});
}
})(req, res, next);
});
It's a clear error message - log is not defined in the following line in passport
log.debug("deserialize ", id);
Define your log object with a logger and everything should be good. Or just remove it for now.

ExpressJS backend Server with Angular2 CLI

I am using this Express Server to authenticate users by signing in by their steam account.
everything works now as expected.
What i want to know now, is how i can integrate this to my Angular2 Project, so i can use in the HomeComponent a Login Button which calls the Express Server.
Is it better to work with an Server.js or with a Server.ts Backend Server?
and will it be visible ? if yes, where should be its destination to garantuee security ?
Im new to this, thats why im so curious :)
thanks in advance
const express = require('express');
const session = require('express-session');
const FirebaseStore = require('connect-session-firebase')(session);
const firebase = require('firebase-admin');
const firebaseinit = firebase.initializeApp({
credential: ('**************************************'),
databaseURL: '**************************************'
});
// *************************************************************************************************************
var passport = require('passport'),
util = require('util'),
SteamStrategy = require('./').Strategy;
// *************************************************************************************************************
passport.serializeUser(function(user, done) {
done(null, user);
});
// *************************************************************************************************************
passport.deserializeUser(function(obj, done) {
done(null, obj);
});
// *************************************************************************************************************
passport.use(new SteamStrategy({
returnURL: 'http://localhost:3000/auth/steam/return',
realm: 'http://localhost:3000/',
apiKey: '**************************************'
},
function(identifier, profile, done) {
process.nextTick(function () {
profile.identifier = identifier;
return done(null, profile);
});
}
));
// *************************************************************************************************************
var app = express();
app.set('views', __dirname + '/signon/views');
app.set('view engine', 'ejs');
app.use(session({
store: new FirebaseStore({
database: firebaseinit.database()
}),
secret: 'keyboard cat',
name: 'name of session id',
resave: true,
saveUninitialized: true
}));
// *************************************************************************************************************
// *************************************************************************************************************
app.use(passport.initialize());
app.use(passport.session());
app.use(express.static(__dirname + '/../../public'));
// app.post('/auth/openid', passport.authenticate('openid'));
// *************************************************************************************************************
app.get('/auth/steam',
passport.authenticate('steam', { failureRedirect: '/' }),
function(req, res) {
res.redirect('/');
});
// *************************************************************************************************************
app.get('/auth/steam/return',
passport.authenticate('steam', { failureRedirect: '/' }),
function(req, res) {
res.redirect('/');
var db = firebase.database();
var ref = db.ref("/UserID");
var SteamUserID = ref.child(req.user.id);
SteamUserID.update({
Username : req.user.displayName,
UserImg : req.user.photos[2].value
});
});
// *************************************************************************************************************
app.get('/logout', function(req, res){
req.logout();
res.redirect('/');
});
// *************************************************************************************************************
app.get('/', function(req, res){
res.render('index', { user: req.user });
});
// *************************************************************************************************************
app.get('/account', ensureAuthenticated, function(req, res){
res.render('account', { user: req.user });
});
// *************************************************************************************************************
app.listen(3000, function () {
console.log('listening on port 3000!')
})
function ensureAuthenticated(req, res, next) {
if (req.isAuthenticated()) { return next(); }
res.redirect('/');
}
console.log('Listening on port ' + app.listen);

PassportJs, local strategy cannot be found

I am new to javascript and node. I followed the guide from passportJS and I am getting the error "local strategy cannot be found". I do not know why. my code, basically taken from the website at this point.
var express = require('express')
, routes = require('./routes')
, user = require('./routes/user')
, http = require('http')
, path = require('path')
, mongoose = require('mongoose')
, passport = require('passport')
, LocalStrategy = require('passport-local').Strategy;
app.use(passport.initialize());
//to configure the passport
app.use(new LocalStrategy({
usernameField: 'username',
passwordField: 'password'
},
function(username, password, done){
console.log(username);
console.log(password);
People.findOne({username:username},
function(err, user){
if(err){return done(err); }
if(!user){
return done(null, false, {message:
'Incorrect username'});
}
if(!user.validPassword(password)){
return done(null, false, {message:
'Incorrect Password'});
}
return done(null, user);
});
}
));
//route to authenticate the user
app.post('/login',
passport.authenticate('local', { successRedirect:'/accessed',
failureRedirect: '/access'})
);
My error is that "local strategy not found", I looked inside the local-strategy module and found the function that defines it. So I assume the error lies somewhere in the way I am attempting to access that variable.
My server is set up like
var app = express();
app.configure(function(){
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(passport.initialize());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
});
app.configure('development', function(){
app.use(express.errorHandler());
});
Here's a boilerplate for using passport-local. The order in which the middleware is configured matters. It also implements serializeUser/deserializeUser which seem to be missing from your code.
var express = require('express')
, http = require('http')
, path = require('path')
, passport = require('passport')
, LocalStrategy = require('passport-local').Strategy;
var app = express();
passport.use(new LocalStrategy(function(username, password, done) {
// insert your MongoDB check here. For now, just a simple hardcoded check.
if (username === 'foo' && password === 'bar')
{
done(null, { user: username });
}
else
{
done(null, false);
}
}));
passport.serializeUser(function(user, done) {
// please read the Passport documentation on how to implement this. We're now
// just serializing the entire 'user' object. It would be more sane to serialize
// just the unique user-id, so you can retrieve the user object from the database
// in .deserializeUser().
done(null, user);
});
passport.deserializeUser(function(user, done) {
// Again, read the documentation.
done(null, user);
});
app.use(express.bodyParser());
app.use(express.cookieParser());
app.use(express.session({ secret: 'secret' }));
app.use(passport.initialize());
app.use(passport.session());
// route to authenticate the user
app.post('/login', passport.authenticate('local', {
successRedirect: '/accessed',
failureRedirect: '/access'
}));
// app.listen(3012);
When you use curl -v -d "username=foo&password=bar" http://127.0.0.1:3012/login you see you'll get redirected to /accessed, meaning the authentication worked.

Categories

Resources