express, authentication without 401 - node.js

This is a resume about an authentication method.
I tried to use express.basicAuth, but it forces the browser to ask for user and pass, and I need to use my own login page, like google, facebook yahoo...
Is this right? Is there any better way to do this?
I want to avoid modules, like passport, if I can.
I want to use a function like this, using auth middleware (app.get('/loggedin', auth, function(req, res)...)
var express = require('express');
var app = express();
app.use(express.cookieParser());
var RedisStore = require('connect-redis')(express);
app.use(express.session({
store: new RedisStore({
host: 'localhost',
port: 6379,
db: 2,
pass: 'RedisPASS'
}), secret: '1234567890QWERTY'
}));
var auth = function(req, res, next) {
if (req.session.authStatus === 'loggedIn')
next();
else
res.redirect('/login');
};
app.get('/', function(req, res) {
console.log("/");
res.send('not authenticate');
});
app.get('/signin', function(req, res) {
console.log("/signin");
if (req.body.user && req.body.pass)
{
req.user = req.body.user;
req.remoteUser = req.body.user;
req.session.authStatus = 'loggedIn';
req.session.lastPage = '/signin';
res.redirect('/loggedin');
}
else
res.redirect('/login');
});
app.get('/loggedin', auth, function(req, res) {
if(req.session.lastPage) {
res.write('Last page was: ' + req.session.lastPage + '. ');
}
req.session.lastPage = '/loggedin';
res.write('Yeeeeeeeeeee');
res.end();
});
app.get('/loggedin2', auth, function(req, res) {
console.log("/loggedin2");
if(req.session.lastPage) {
res.write('Last page was: ' + req.session.lastPage + '. ');
}
req.session.lastPage = '/loggedin2';
res.write('WoWWWWW!!!!!!');
res.end();
});
app.get('/logout', auth, function(req, res) {
console.log("/logout");
req.session.destroy();
});
app.get('/login', function(req, res) {
console.log("/notlogged");
res.send('enter user and pass...');
});
app.listen(process.env.PORT || 8080);

You could use the passport middleware module in npm — the passport-local module provides authentication against a local resource such as a database.

Related

Invalid redirect error in Chrome after migrating to CloudFlare

My site www.exampartner.in runs on an EC2 instance using NodeJS connected to a domain I bought on bigrock.in. To use SSL I migrated to CloudFlare however ever since I migrated to CloudFlare my site is having issues. The main issue is the invalid redirect error I faced on the javascript, logo and ham pic after setting https redirect as a page rule. I then disabled it and tried to load these resources over HTTP but it still failed. Now I've disabled the SSL as well and the page seems to be working. I've attached screenshot for reference. Please Help. Thank You.
Here's my routes.js:
var express = require('express');
var router = express.Router();
var passport = require('passport');
router.get('/login', function (req, res, next) {
res.render('login', { message: req.flash('loginMessage'), user: req.user });
});
router.get('/', function (req, res) {
res.render('mainpage', { user: req.user });
});
router.get('/signup', function (req, res, next) {
res.render('signup', { message: req.flash('signupMessage'), user: req.user });
});
// process the login form
router.post('/login', passport.authenticate('local-login', {
successRedirect: '/profile', // redirect to the secure profile section
failureRedirect: '/login', // redirect back to the signup page if there is an error
failureFlash: true // allow flash messages
}));
// app.post('/signup', do all our passport stuff here);
router.post('/signup', passport.authenticate('local-signup', {
successRedirect: '/profile', // redirect to the secure profile section
failureRedirect: '/signup', // redirect back to the signup page if there is an error
failureFlash: true // allow flash messages
}));
// =====================================
// PROFILE SECTION =====================
// =====================================
// we will want this protected so you have to be logged in to visit
// we will use route middleware to verify this (the isLoggedIn function)
router.get('/profile', isLoggedIn, function (req, res) {
res.render('profile', {
user: req.user // get the user out of session and pass to template
});
});
// =====================================
// LOGOUT ==============================
// =====================================
router.get('/logout', function (req, res) {
req.logout();
res.redirect('/');
});
// };
// route middleware to make sure a user is logged in
function isLoggedIn(req, res, next) {
// if user is authenticated in the session, carry on
if (req.isAuthenticated())
return next();
// if they aren't logged redirect them to the home page
res.redirect('/');
}
router.post('/login', passport.authenticate('local-login', {
successRedirect: '/profile', // redirect to the secure profile section
failureRedirect: '/login', // redirect back to the signup page if there is an error
failureFlash: true // allow flash messages
}));
router.get('/bitsat', function (req, res) {
res.render('bitsat', { user: req.user });
})
router.get('/aieee', function (req, res) {
res.render('aieee', { user: req.user });
})
router.get('/ip', function (req, res) {
res.render('ip', { user: req.user });
})
router.get('/jeemain', function (req, res) {
res.render('jeemain', { user: req.user });
})
router.get('/jeeadvanced', function (req, res) {
res.render('jeeadvanced', { user: req.user });
})
router.get('/jeemain/:year', function (req, res) {
res.render(__dirname + '/views/jee_main/' + req.params.year, { user: req.user });
});
router.get('/jeemain/:year/:paper', function (req, res) {
var filename = req.params.paper.substr(0, 2) + 'April' + req.params.year
var mor = req.params.paper.indexOf('Morning')
var eve = req.params.paper.indexOf('Evening')
if (mor !== -1) {
filename = filename + req.params.paper.substr(mor, req.params.paper.length)
}
if (eve !== -1) {
filename = filename + req.params.paper.substr(eve, req.params.paper.length);
}
res.download(__dirname + '/downloads/jee_main/' + req.params.year + '/' + filename + '.pdf')
});
router.get('/bitsat/:op', function (req, res) {
res.render(__dirname + '/views/bitsat/' + req.params.op, { user: req.user });
});
router.get('/bitsat/:op/:year', function (req, res) {
res.download(__dirname + '/downloads/bitsat/' + req.params.op + '/' + req.params.year + '.pdf')
});
module.exports = router;
Edit: In order to use Cloudflare's strict SSL, you need to install an SSL certificate on your server. Lets Encrypt provides free SSL certificates that have to be renewed every 90 days. If the process seems difficult, you can use Zero SSL which makes it easy to get a certificate from lets encrypt, as well as to update existing certificate.
You have to set up express to handle https request/response. The Node.js app needs ssl certificate and key.
const express = require('express')
const fs = require('fs')
const https = require('https')
const app = express()
https.createServer({
key: fs.readFileSync('server.key'),
cert: fs.readFileSync('server.cert')
}, app)
.listen(process.env.PORT || 3000, function () {
console.log('"App Listening at port:" + port')
})

How to provide SP metadata to TestShib IdP using passport-saml?

I have a node.js script, using passport-saml, that simulates an SP. My goal is to connect it to this TestShib IdP but I get the following error: SAML 2 SSO profile is not configured for relying party.
Based on what I read here, I know that I need to provide the SP metadata, but I do not know how. I know that passport-saml has the function: generateServiceProviderMetadata(decryptionCert) and I while I have the certificates required, I do not know how to make it all work.
Also, I want to avoid having to register my SP if that is possible.
Here is my script:
const https = require('https');
const fs = require('fs');
const express = require('express');
const morgan = require('morgan');
const bodyParser = require('body-parser');
const cookieParser = require('cookie-parser');
const session = require('express-session');
const passport = require('passport');
const saml = require('passport-saml');
/*
---------------------------------------------------------------------------------------------------
-- certificates
---------------------------------------------------------------------------------------------------
*/
// for https server
const https_cert = fs.readFileSync('certificate.pem', 'utf-8');
const https_pvk = fs.readFileSync('privatekey.pem', 'utf-8');
// from idp's metadata
const idp_cert_1 = 'MIIDAzCCAeugAwIBAgIVAPX0G6LuoXnKS0Muei006mVSBXbvMA0GCSqGSIb3DQEBCwUAMBsxGTAXBgNVBAMMEGlkcC50ZXN0c2hpYi5vcmcwHhcNMTYwODIzMjEyMDU0WhcNMzYwODIzMjEyMDU0WjAbMRkwFwYDVQQDDBBpZHAudGVzdHNoaWIub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAg9C4J2DiRTEhJAWzPt1S3ryhm3M2P3hPpwJwvt2q948vdTUxhhvNMuc3M3S4WNh6JYBs53R+YmjqJAII4ShMGNEmlGnSVfHorex7IxikpuDPKV3SNf28mCAZbQrX+hWA+ann/uifVzqXktOjs6DdzdBnxoVhniXgC8WCJwKcx6JO/hHsH1rG/0DSDeZFpTTcZHj4S9MlLNUtt5JxRzV/MmmB3ObaX0CMqsSWUOQeE4nylSlp5RWHCnx70cs9kwz5WrflnbnzCeHU2sdbNotBEeTHot6a2cj/pXlRJIgPsrL/4VSicPZcGYMJMPoLTJ8mdy6mpR6nbCmP7dVbCIm/DQIDAQABoz4wPDAdBgNVHQ4EFgQUUfaDa2mPi24x09yWp1OFXmZ2GPswGwYDVR0RBBQwEoIQaWRwLnRlc3RzaGliLm9yZzANBgkqhkiG9w0BAQsFAAOCAQEASKKgqTxhqBzROZ1eVy++si+eTTUQZU4+8UywSKLia2RattaAPMAcXUjO+3cYOQXLVASdlJtt+8QPdRkfp8SiJemHPXC8BES83pogJPYEGJsKo19l4XFJHPnPy+Dsn3mlJyOfAa8RyWBS80u5lrvAcr2TJXt9fXgkYs7BOCigxtZoR8flceGRlAZ4p5FPPxQR6NDYb645jtOTMVr3zgfjP6Wh2dt+2p04LG7ENJn8/gEwtXVuXCsPoSCDx9Y0QmyXTJNdV1aB0AhORkWPlFYwp+zOyOIR+3m1+pqWFpn0eT/HrxpdKa74FA3R2kq4R7dXe4G0kUgXTdqXMLRKhDgdmA==';
const idp_cert_2 = 'MIIDAzCCAeugAwIBAgIVAPX0G6LuoXnKS0Muei006mVSBXbvMA0GCSqGSIb3DQEBCwUAMBsxGTAXBgNVBAMMEGlkcC50ZXN0c2hpYi5vcmcwHhcNMTYwODIzMjEyMDU0WhcNMzYwODIzMjEyMDU0WjAbMRkwFwYDVQQDDBBpZHAudGVzdHNoaWIub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAg9C4J2DiRTEhJAWzPt1S3ryhm3M2P3hPpwJwvt2q948vdTUxhhvNMuc3M3S4WNh6JYBs53R+YmjqJAII4ShMGNEmlGnSVfHorex7IxikpuDPKV3SNf28mCAZbQrX+hWA+ann/uifVzqXktOjs6DdzdBnxoVhniXgC8WCJwKcx6JO/hHsH1rG/0DSDeZFpTTcZHj4S9MlLNUtt5JxRzV/MmmB3ObaX0CMqsSWUOQeE4nylSlp5RWHCnx70cs9kwz5WrflnbnzCeHU2sdbNotBEeTHot6a2cj/pXlRJIgPsrL/4VSicPZcGYMJMPoLTJ8mdy6mpR6nbCmP7dVbCIm/DQIDAQABoz4wPDAdBgNVHQ4EFgQUUfaDa2mPi24x09yWp1OFXmZ2GPswGwYDVR0RBBQwEoIQaWRwLnRlc3RzaGliLm9yZzANBgkqhkiG9w0BAQsFAAOCAQEASKKgqTxhqBzROZ1eVy++si+eTTUQZU4+8UywSKLia2RattaAPMAcXUjO+3cYOQXLVASdlJtt+8QPdRkfp8SiJemHPXC8BES83pogJPYEGJsKo19l4XFJHPnPy+Dsn3mlJyOfAa8RyWBS80u5lrvAcr2TJXt9fXgkYs7BOCigxtZoR8flceGRlAZ4p5FPPxQR6NDYb645jtOTMVr3zgfjP6Wh2dt+2p04LG7ENJn8/gEwtXVuXCsPoSCDx9Y0QmyXTJNdV1aB0AhORkWPlFYwp+zOyOIR+3m1+pqWFpn0eT/HrxpdKa74FA3R2kq4R7dXe4G0kUgXTdqXMLRKhDgdmA==';
/*
---------------------------------------------------------------------------------------------------
-- passport-saml setup
---------------------------------------------------------------------------------------------------
*/
const saml_strategy = new saml.Strategy(
{
'callbackUrl': 'https://localhost:44300/login/callback',
'entryPoint': 'https://idp.testshib.org/idp/profile/SAML2/Redirect/SSO',
'issuer': 'https://localhost:44300',
'decryptionPvk': https_pvk,
'cert': [idp_cert_1, idp_cert_2]
},
function (profile, done)
{
console.log('passport.use() profile: %s \n', JSON.stringify(profile));
return done(
null,
{
'nameIDFormat': profile.nameIDFormat,
'nameID': profile.nameID
}
);
}
);
passport.serializeUser(function (user, done) {
console.log('passport.serializeUser() user: %s \n', JSON.stringify(user));
done(null, user);
});
passport.deserializeUser(function (user, done) {
console.log('passport.deserializeUser() user: %s \n', JSON.stringify(user));
done(null, user);
});
passport.use(saml_strategy);
/*
---------------------------------------------------------------------------------------------------
-- express setup
---------------------------------------------------------------------------------------------------
*/
const app = express();
// configure view engine to render EJS templates
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
// additional settings for logging and parsing
app.use(morgan('dev'));
app.use(cookieParser());
app.use(bodyParser.urlencoded({'extended': true}));
app.use(session({ 'secret': 'this-is-secret', 'resave': false, 'saveUninitialized': false }));
// initialize Passport and restore authentication state, if any, from the session
app.use(passport.initialize());
app.use(passport.session());
/*
---------------------------------------------------------------------------------------------------
-- routes
---------------------------------------------------------------------------------------------------
*/
app.get(
'/',
function (req, res) {
if (req.isAuthenticated()) {
console.log('GET [/] user authenticated! req.user: %s \n', JSON.stringify(req.user));
res.render('home', { 'user': req.user });
} else {
console.log('GET [/] user not authenticated! \n');
res.render('home', { 'user': null });
}
}
);
app.get(
'/login',
passport.authenticate('saml', { 'successRedirect': '/', 'failureRedirect': '/login' })
);
app.post(
'/login/callback',
passport.authenticate('saml', { 'failureRedirect': '/', 'failureFlash': true }),
function(req, res) {
console.log('POST [/login] \n');
res.redirect('/');
}
);
app.get(
'/profile',
function(req, res){
if (req.isAuthenticated()) {
console.log('GET [/profile] user authenticated! req.user: %s \n', JSON.stringify(req.user));
res.render('profile', { 'user': req.user });
} else {
console.log('GET [/profile] user not authenticated! \n');
res.redirect('/login');
}
}
);
app.get(
'/logout',
function(req, res) {
console.log('GET [/logout] \n');
passport._strategy('saml').logout(
req,
function(err, requestUrl) {
req.logout();
res.redirect('/');
}
);
}
);
/*
---------------------------------------------------------------------------------------------------
-- start https server
---------------------------------------------------------------------------------------------------
*/
const server = https.createServer({
'key': https_pvk,
'cert': https_cert
}, app);
server.listen(44300, function() {
console.log('Listening on https://localhost:%d', server.address().port)
});
Thank you in advance for your help and guidance!
I know that passport-saml has the function: generateServiceProviderMetadata(decryptionCert) and I while I have the certificates required, I do not know how to make it all work.
For the sake of completeness, I'll list all the steps needed. But you've already done the first 2 so you can skip them:
Create the cert/key
In your SamlStrategy, define decryptionPvk
decryptionPvk: fs.readFileSync('./credentials/key.pem', 'utf-8'),
Lastly, you can create an endpoint that exposes your metadata (this is the part you're missing)
app.get('/metadata',
function(req, res) {
const decryptionCert = fs.readFileSync('./credentials/cert.pem', 'utf-8');
res.type('application/xml');
res.send((myStrategy.generateServiceProviderMetadata(decryptionCert)));
}
);
Here's what that would look like reformatted to match the sample code you posted:
app.get(
'/metadata',
function(req, res) {
res.type('application/xml');
res.send((saml_strategy.generateServiceProviderMetadata(https_cert)));
}
);
Once that's done you should be able to access your metadata from the /metadata path.
Also, I want to avoid having to register my SP if that is possible.
I'm not a SAML expert, but you probably won't be able to avoid registration. This would only work with an IdP that was set up to trust all SPs, but that wouldn't make much sense because a key part of SAML is the two-way trust that's established between the IdP and SP.

mynodejs login page is not responding

I'm new to node js and i tried creating a simple login page. but when i run my code it takes me to the login page alright. the problem is when i enter a user name and password, it doesn't display the information it supposed to display.
var express = require('express');
var sessions = require('express-session');
var session;
var bodyParser = require('body-parser');
var app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended:true}));
app.use(sessions({
secret: '2937#&&#',
resave: false,
saveUninitialized: true
}))
app.get('/login', function(req, resp){
session = req.session;
if(session.uniqueID){
resp.redirect('/redirects');
}
resp.sendFile('./files/login.html', {root: __dirname});
});
app.post('/login', function(req, resp){
// resp.end(JSON.stringify(req.body));
session = req.session;
if(session.uniqueID) {
resp.redirect('/redirects');
}
if(req.body.username == 'admin' && req.body.password == 'admin'){
session.uniqueID = req.body.username;
}
resp.redirect('/redirects');
});
app.get('/logout', function(req, resp){
req.session.destroy();
resp.redirect('/login');
});
app.get('/admin', function(req, resp){
session = req.session;
if(session.uniqueID != 'admin'){
resp.end('Unauthorised acess')
}
resp.end('You are good');
})
app.get('/redirects', function(req, resp){
session = req.session;
if(session.uniqueID =='admin') {
console.log(session.uniqueID)
resp.redirect('/admin');
} else {
resp.send(req.session.uniqueID + 'not found KILL SESSION');
}
})
app.listen(1337, function() {
console.log('Listening at port 1337');
});
Nothing happens because you can't redirect on an AJAX call. Your POST probably works, but then your redirect directive has no effect.
Try sending a "success" response if the username and password are good (a simple res.send('OK'); would do) and then on the client side redirect the user to /redirects (window.location.replace('https://yoursite.com/redirects')); if a success code is returned.
This will be handled by your GET route for /redirects and you should see what you want.

How to keep a user logged on? Is it possible with ExpressJS and Passport?

I have a server in node.js using express and passport with the passport-local strategy.
I have the users in the database and through passport I'm able to authenticate them, unfortunately when a second request comes from the same client the req.isAuthenticated() method returns false.
There is also no user in the request (req.user = undefined).
I've also checked and when doing the authentication although I get back a user from passport.authenticate('local'... I do not get req.user populated then. If I try to set it up manually it just doesn't propagate for following requests.
I don't understand what I'm doing wrong, here is my code.
server.js
var express = require('express'),
compass = require('node-compass'),
routes = require('./server/routes')
http = require('http'),
path = require('path'),
passport = require('passport'),
LocalStrategy = require('passport-local').Strategy,
Database = require('./server/repositories/database'),
Configuration = require('./server/config').Config,
crypto = require('crypto');
var app = express();
app.enable("jsonp callback");
passport.use(new LocalStrategy(
function(email, password, done) {
process.nextTick(function () {
var userService = new UserService();
userService.login(email, crypto.createHash('md5').update(password).digest("hex"), function(error, user) {
if (error) done(error, user);
else if (!user) return done(null, false, { message: 'wrong credentials'});
return done(null, user);
});
});
}
));
passport.serializeUser(function(user, done) {
done(null, user._id);
});
passport.deserializeUser(function(id, done) {
var userService = new UserService();
userService.findById(id, function(err, user) {
done(err, user);
});
});
app.configure(function(){
app.set('port', Configuration.Port);
app.set('views', __dirname + '/app/views');
app.set('view engine', 'ejs');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.cookieParser());
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(compass({
project: path.join(__dirname, 'app'),
sass: 'styles'
}));
app.use(express.session({ secret: 'keyboard cat' }));
app.use(function(err, req, res, next){
console.error(err.stack);
res.send(500, 'Something broke!');
});
app.use(passport.initialize());
app.use(passport.session());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'app')));
});
routes.configure(app);
Database.open(function() {
app.listen(Configuration.Port, function() {
console.log("Express server listening on port " + Configuration.Port);
});
});
routes.js
var Configuration = require('./config').Config;
var ApiResult = require('../model/apiResult').ApiResult;
var ApiErrorResult = require('../model/apiErrorResult').ApiErrorResult;
var ApiReturnCodes = require('../model/apiReturnCodes').ApiReturnCodes;
var passport = require('passport');
var usersController = require('./controllers/usersController');
exports.configure = function(app) {
function ensureAuthenticated(req, res, next) {
console.log(req.isAuthenticated());
if (req.isAuthenticated()) { return next(); }
else {res.send(new ApiErrorResult(ApiReturnCodes.NOT_LOGGED_IN, null));}
}
app.post('/login', function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
if (err || !user) { console.log(info); res.send(new ApiErrorResult(ApiReturnCodes.ENTITY_NOT_FOUND, null)); }
// If this function gets called, authentication was successful.
// `req.user` contains the authenticated user
else res.send(new ApiResult(user));
})(req,res,next);
});
app.get('/anotherLink', ensureAuthenticated, function(req, res, next) {
res.json({Code:0});
});
}
When I hit the link /anotherLink after being authenticated I get res.isAuthenticated() as false.
Also when I see the req.session after the ensureAuthenticated is called I get:
{ cookie:
{ path: '/',
_expires: null,
originalMaxAge: null,
httpOnly: true },
passport: {} }
What am I missing for it to save the information that that user is authenticated?
On the client side I'm using Angular only doing a simple get with the url without parameters.
If I forgot to put something here just tell me, I'll update it.
Any help will be greatly appreciated. Thanks
So I found out what was wrong with my code.
My passport.deserializeUser method used the method userService.findById
And that called the repository... like this:
userRepository.findUnique({"_id": id}, callback);
because the id was generated by MongoDB the correct call needs to be:
userRepository.findUnique({"_id": new ObjectID(id)}, callback);
I hope this saves some time to the next person with the same problem.
With this detail, this code should work nicely for everyone wanting to use the LocalStrategy on the Passport framework.

express session management not working

I am new to the node.js world. I am trying to write a REST services and I am stuck with session management. So I created a separate app just to see if I can get the session to work, but it doesn't, here is the code. The req.session.username is always undefined:
var express = require('express');
var url = require('url');
var app = express()
app.use(express.cookieParser('Hiren'))
app.use(express.session({ secret: 'HirenAdesara' }))
app.use(express.bodyParser())
app.use(app.router)
//Sniff HTTP
app.all('*', function(req, res, next) {
//Check for Authentication
console.log(req.session)
if ((!(/^\/auth/g.test(req.url))) && (!req.session)) {
console.log('in app.all: Unauthorized')
res.send(401)
}
else
{
return next()
}
})
app.post('/auth', function(req, res) {
var query = req.body
console.log('Query' + JSON.stringify(query))
username = query.username;
password = query.password;
if(username == 'Hiren' && password == 'Adesara')
{
req.session.username = 'Hiren';
console.log('New Session Created..')
res.send(200)
}
else
{
console.log('New session could not be created.')
res.send(401)
}
})
app.get('/projects', function(req,res) {
console.log('inside projects' + req.session.username);
res.send(req.session.username); })
app.listen(2048)
console.log('Listening on port 2048...')
It doesn't work and I have no idea what is wrong here.
Star by moving the 3 lines in your app.get('/'...) outside of it:
var express = require('express');
var querystring = require('querystring');
var app = express()
app.use(express.cookieParser('Hiren')); // This line
app.use(express.session({ secret: 'HirenAdesara' })); // This line
app.use(express.bodyParser()); // This line
app.get('/', function(req, res){
res.send('hello from the root page');
})
// the rest of your code

Resources