Logout BasicAuth in node.js - node.js

i have reference for http://blog.modulus.io/nodejs-and-express-basic-authentication
my code conect my database mongodb:
var admin = express.basicAuth(authentikasi);
function authentikasi(user, pass, callback) {
// declrare my database mongodb
db.collection('ak_admin', function (err, data) {
data.findOne({'adm_name': {'$regex': user}}, function (err, level) {
if (level == null) {
console.log('Nilai database Administrator masuk Null ulangi login');
callback(null);
} else {
var a = level.adm_name;
var b = level.adm_password;
var c = level.adm_mobile;
if (user === a && pass === b) {
callback(null, {name: a, id: c});
} else
callback(null, false);
}
});
});
};
app.get('/admin', admin, function(req, res){
res.sendfile(__dirname + '/admin/index.html');
});
my schema for login basicauth is succesfull but my question : how to create logout because my site admin have login after use this schema not input username and password again :
app.get('/logout', function(req, res){
//how code in here for erase memory in variable admin (user and pass)
res.sendfile(__dirname + '/public/index.html');
});
please help me thanks you...

Related

Passport + Express - User Sessions Conflicting

I have a simple Node+Express application with Passport Local authentication, it's working nearly perfectly (the right pages are served up, login/logout works, etc).
One issue though is that if a second user logs in, that session "takes over" the first user's session and suddenly the first user is now logged in as the second user!
This is almost certainly an issue with the order of the middleware, but I haven't been able to find it - I'm fairly new to Passport and Express. The code is taken liberally from docs and examples, but I might have messed the order up.
I've followed the order in this answer but it's still not working. Can anyone suggest where I might be mixed up?
The main server:
var express = require('express');
var passport = require('passport');
var Strategy = require('passport-local').Strategy;
var url = require('url');
var db = require('./db');
// Configure the local strategy for use by Passport.
passport.use(new Strategy(
function(username, password, cb) {
db.users.findByUsername(username, function(err, user) {
if (err) { return cb(err); }
if (!user) { return cb(null, false); }
if (user.password != password) { return cb(null, false); }
return cb(null, user);
});
}));
// Configure Passport authenticated session persistence.
passport.serializeUser(function(user, cb) {
console.log('DEBUG: serializeUser called ' + user.id);
cb(null, user.id);
});
passport.deserializeUser(function(id, cb) {
console.log('DEBUG: deserializeUser called ' + id);
db.users.findById(id, function (err, user) {
if (err) { return cb(err); }
cb(null, user);
});
});
// Create a new Express application.
// Use application-level middleware for common functionality (Order is important!)
// Initialize Passport and restore authentication state, if any, from the session.
var app = express();
app.use(require('cookie-parser')());
app.use(require('body-parser').urlencoded({ extended: true }));
app.use(require('express-session')({ secret: 'qwerty', resave: false, saveUninitialized: false })); // Step 2.
app.use(passport.initialize());
app.use(passport.session());
app.post('/login',
passport.authenticate('local', { failureRedirect: '/login.html' }),
function(req, res) {
console.log('Logged In: ' + req.user.username);
res.redirect('/');
});
app.get('/logout', function(req, res){
if (req.user != null) {
console.log('Logged Out: ' + req.user.username);
req.logout();
} else {
console.log('Warning: null user logging out');
}
res.redirect('/login.html');
});
app.get('/user', function(req, res){
if (req.user != null) {
res.send(req.user.displayName);
} else {
res.send('ERROR: No current user?');
}
});
function isAuthenticated(req, res, next) {
if (req.user) { // User is logged in
return next();
}
if (req.url.startsWith('/login')) { // Allow login through to avoid infinite loop
return next();
}
res.redirect('/login.html');
}
app.use('/', isAuthenticated, express.static('/public/'));
The db/users.js file:
var records = [
{ id: 1, username: 'jill', password: 'birthday', displayName: 'Jill'}
{ id: 2, username: 'jack', password: 'hello', displayName: 'Jack'}
];
exports.findById = function(id, cb) {
process.nextTick(function() {
var idx = id - 1;
if (records[idx]) {
cb(null, records[idx]);
} else {
cb(new Error('User ' + id + ' does not exist'));
}
});
}
exports.findByUsername = function(username, cb) {
process.nextTick(function() {
for (var i = 0, len = records.length; i < len; i++) {
var record = records[i];
if (record.username === username) {
return cb(null, record);
}
}
return cb(null, null);
});
}
Tumbleweeds!
So it turns out that it was working fine - the problem was just that Chrome reuses its session across tabs. I found a helpful comment buried in this question's answer. One login from Chrome and another from IE works fine, no conflict.
Node + Passport - multiple users

Mongoose findOne function is not working with authentication

I am working on a model here:
// user.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var bcrypt = require('bcrypt');
// Define collection and schema for Users
let User = new Schema(
{
firstName: String,
lastName: String,
emailaddress: String,
password: String,
},
{
collection: 'users'
}
);
// authenticate input against database documents
User.statics.authenticate = ((emailaddress, password, callback) => {
User.findOne({ emailaddress: emailaddress })
.exec(function(error, user){
if(error){
return callback(error)
} else if (!user){
console.log('User not found!');
}
bycrypt.compare(password, user.password, function(err, result){
if(result === true){
return callback(null, user);
} else {
return callback();
}
})
})
});
module.exports = mongoose.model('User', User);
As you can see on my model I put the User.statics.authenticate on my codes to do some authentication. And then on my login.js route file:
const path = require('path');
const express = require('express');
const router = express.Router();
const db = require('../../database/index');
const axios = require('axios');
const User = require('../../database/models/user');
router.get('/', (req, res) => {
console.log('hi there this is working login get');
});
router.post('/', (req, res) => {
var emailaddress = req.body.emailaddress;
var password = req.body.password;
if( emailaddress && password ){
User.authenticate(emailaddress, password, function(err, user){
if(err || !user){
console.log('Wrong email or password!');
} else {
req.session.userId = user._id;
return res.redirect('/');
}
});
} else {
console.log('both fields are required...');
}
});
module.exports = router;
I called the function and then User.authenticate function and also I created the route for root w/c is the sample that I want to protect and redirect the user after login:
router.get('/', (req, res) => {
if(! req.session.userId ){
console.log('You are not authorized to view this page!');
}
User.findById(req.session.userId)
.exect((err, user) => {
if(err){
console.log(err)
} else {
res.redirect('/');
}
})
});
Upon clicking submit on my react form it returns this error:
TypeError: User.findOne is not a function
at Function.User.statics.authenticate (/Users/mac/Documents/monkeys/database/models/user.js:35:8)
I checked the Mongoose documentation and it seems I am using the right syntax.Any idea what am I doing wrong here? Please help! Sorry super beginner here!
PS. I've already installed and set up the basic express session too.
UPDATES:
I remove the arrow function from my call and use this.model.findOne but still get the typerror findOne is not a function
// authenticate input against database documents
User.statics.authenticate = function(emailaddress, password, callback){
this.model.findOne({ emailaddress: emailaddress })
.exec(function(error, user){
if(error){
return callback(error)
} else if (!user){
console.log('User not found!');
}
bycrypt.compare(password, user.password, function(err, result){
if(result === true){
return callback(null, user);
} else {
return callback();
}
})
})
};
findOne is a method on your User model, not your user model instance. It provides its async results to the caller via callback:
User.findOne({field:'value'}, function(err, doc) { ... });

How can i pass the parameter “username” to "/" router with express?

I have a db operation in login post router, when db operation callback success, I got a username value, and how I can pass this username to the "/" router?
router.post('/login', (req, res)=> {
var username = req.body.username;
var password = common.md5(req.body.password + common.MD5_SUFFIX);
db.query(`SELECT * FROM admin_table WHERE username='${username}'`, (err, data)=> {
if (err) {
console.log(err);
res.status(500).send('database error').end();
} else {
if (data.length == 0) {
res.status(404).send('no this admin').end();
} else {
if (data[0].password == password) {
req.session['admin_id']=data[0].ID;
res.redirect('/');
} else {
res.status(404).send('This password is not incorrect!').end();
}
}
}
});
});
router.get('/login',(req,res)=>{
res.render('admin/login.ejs',{layout:'/admin/layout.ejs',title:'Login'});
});
router.get('/',(req,res)=>{
res.render('admin/index.ejs',{layout:'/admin/layout.ejs',title:'Index',username:username});
});
Such as in post login router, I got a username is "ollie", when db operation is ending, the router redirect "/", I can got the username "ollie" in the "/" router .
The simplest way is to use a session. E.g. where you configure the express app, use this:
if (data[0].password == password) {
req.session['admin_id']=data[0].ID;
req.session.username = data.username;
res.redirect('/');
}
Then later you can access that, e.g.
router.get('/route', (req, res) => {
console.log(req.session && req.session.username);
res.end(`Hi ${req.session && req.session.username}`)
});
And please, please, please do not use md5 in any authentication schemes, even example code.

Express.js session undefined in method put

Building an API with node and express. In my "home" route i set a session with a users id.
When i want to add and update information on a user i want to access the session to know which user to update. In my get routes i can access the session, but in my route with put method its always undefined. Why is this?
app.get('/users/:id/spots', spot.findSpotsByUserId); //I set the session in this method
app.get('/spots/:id', spot.findById);
app.put('/userspot/spot/:spotId/add'', spot.addUserSpot);
exports.findSpotsByUserId = function(req, res) {
var id = req.params.id; //Should ofc be done with login function later
db.collection('users', function(err, collection) {
collection.findOne({'_id':new BSON.ObjectID(id)}, function(err, user) {
if (err) {
res.send({'error':'Couldnt find user'});
} else {
req.session.userId = id;//<----- sets session
console.log("SESSION",req.session.userId);
}
......}
exports.findById = function(req, res) {
var id = req.params.id;
console.log('Get spot: ' + id);
console.log("SESSION!",req.session.userId);// <----prints the id!
db.collection('spots', function(err, collection) {
collection.findOne({'_id':new BSON.ObjectID(id)}, function(err, item) {
res.send(item);
});
});
};
exports.addUserSpot = function(req, res) {
var user = req.session.userId;
var spot = req.params.spotId;
console.log("SESSION!",req.session.userId);// always UNDEFINED!
//........}
You are looking for req.params.userId, not req.session.
The session is persisted between multiple calls, and it has no connection to the params object. You can set req.session.userId in a previous call and access it here, but I don't think this is what you want.
Try this:
exports.findById = function(req, res) {
req.session.test = "from findById";
...
};
exports.addUserSpot = function(req, res) {
console.log(req.session.test, req.params.userId);
...
};

Problems in integration of everyauth example with a simple login application

I am trying to use everyauth example for logging in with facebook. I printed the everyauth debug message which kind of shows that the authentication is performed successfully. However, the everyauth.loggedIn variable is not set. I am not sure why. I am actually having my code like this
I have a page which has the link to auth/facebook. When the user clicks on that link, the user is sent for facebook authentication and everything completes. However, when I check for everyauth.loggedIn it is always undefined
if(everyauth.loggedIn) {
console.log('The user has logged in');
}
The above is something that I am trying to check when there is request at the '/' url. This is after the facebook authentication has been performed. However, it always comes out to be undefined. Could it be because of local, global variable issue. I am passing the everyauth variable to several modules. Any suggestions will be appreciated
app.js(sets up the express application)
var exp = require('express');
var app = exp.createServer();
var conf = require('/path/example/conf')
var everyauth = require('everyauth');
everyauth.debug = true;
var usersById = {};
var nextUserId = 0;
function addUser (source, sourceUser) {
var user;
user = usersById[++nextUserId] = {id: nextUserId};
user[source] = sourceUser;
return user;
}
var usersByFbId = {};
var usersByTwitId = {};
everyauth.everymodule
.findUserById( function (id, callback) {
callback(null, usersById[id]);
});
everyauth
.facebook
.appId(conf.fb.appId)
.appSecret(conf.fb.appSecret)
.findOrCreateUser( function (session, accessToken, accessTokenExtra, fbUserMetadata) {
return usersByFbId[fbUserMetadata.id] || (usersByFbId[fbUserMetadata.id] = addUser('facebook', fbUserMetadata));;
})
.redirectPath('/');
everyauth
.twitter
.consumerKey(conf.twit.consumerKey)
.consumerSecret(conf.twit.consumerSecret)
.findOrCreateUser( function (sess, accessToken, accessSecret, twitUser) {
return usersByTwitId[twitUser.id] || (usersByTwitId[twitUser.id] = addUser('twitter', twitUser));;
})
.redirectPath('/');
app.root = __dirname;
global.host = 'local.host';
require('./app/config')(app, exp, everyauth);
require('./app/server/router')(app,everyauth);
app.listen(3000, function(){
console.log("Express server listening on port %d in %s mode", app.address().port, app.settings.env);
});
config.js
module.exports = function(app, exp, everyauth) {
app.configure(function(){
app.set('views', app.root + '/app/server/views');
app.set('view engine', 'jade');
app.set('view options', { doctype : 'html', pretty : true });
app.use(exp.bodyParser());
app.use(exp.cookieParser());
app.use(exp.session({ secret: 'super-duper-secret-secret' }));
app.use(everyauth.middleware(app));
app.use(exp.methodOverride());
app.use(require('stylus').middleware({ src: app.root + '/app/public' }));
app.use(exp.static(app.root + '/app/server'));
app.use(exp.static(app.root + '/app/public'));
});
router.js
var CT = require('./modules/country-list');
var AM = require('./modules/account-manager');
var EM = require('./modules/email-dispatcher');
var mongodb = require('mongodb');
module.exports = function(app, everyauth) {
// main login page //
app.get('/', function(req, res){
console.log('Root page called');
// This is the problem area. everyauth.loggedIn always comes out undefined
if(everyauth.loggedIn) {
console.log('The user has logged in');
}
// check if the user's credentials are saved in a cookie //
if (req.cookies.user == undefined || req.cookies.pass == undefined){
res.render('login', { locals: { title: 'Hello - Please Login To Your Account'}});
} else{
// attempt automatic login //
AM.autoLogin(req.cookies.user, req.cookies.pass, function(o){
if (o != null){
req.session.user = o;
res.redirect('/dashboard');
} else{
res.render('login', { locals: { title: 'Hello - Please Login To Your Account' }});
}
});
}
});
app.post('/', function(req, res){
console.log('app called');
AM.manualLogin(req.param('user'), req.param('pass'), function(e, o){
if (!o){
res.send(e, 400);
} else{
req.session.user = o;
if (req.param('remember-me') == 'true'){
res.cookie('user', o.user, { maxAge: 900000 });
res.cookie('pass', o.pass, { maxAge: 900000 });
}
res.send(o, 200);
}
});
});
app.post('/feedback', function(req,res) {
var server = new mongodb.Server('localhost',27017, {auto_reconnect: true}, {safe:true});
var db = new mongodb.Db('clicker', server);
db.open(function(err, db) {
if(!err) {
db.collection('feedback', function(err, collection) {
var currentTime = new Date().getTime();
var feedback = {value:req.param('feedback'), datetime:currentTime};
collection.insert(feedback);
db.close();
});
}
});
res.send('ok', 200);
});
// logged-in user homepage //
app.get('/home', function(req, res) {
if (req.session.user == null){
// if user is not logged-in redirect back to login page //
res.redirect('/');
} else{
res.render('home', {
locals: {
title : 'Control Panel',
countries : CT,
udata : req.session.user
}
});
}
});
app.get('/dashboard', function(req, res) {
if (req.session.user == null){
// if user is not logged-in redirect back to login page //
res.redirect('/');
} else{
res.render('dashboard', {
locals: {
title : 'Dashboard',
countries : CT,
udata : req.session.user
}
});
}
});
app.post('/home', function(req, res){
if (req.param('user') != undefined) {
AM.update({
user : req.param('user'),
name : req.param('name'),
email : req.param('email'),
country : req.param('country'),
pass : req.param('pass')
}, function(o){
if (o){
req.session.user = o;
// udpate the user's login cookies if they exists //
if (req.cookies.user != undefined && req.cookies.pass != undefined){
res.cookie('user', o.user, { maxAge: 900000 });
res.cookie('pass', o.pass, { maxAge: 900000 });
}
res.send('ok', 200);
} else{
res.send('error-updating-account', 400);
}
});
} else if (req.param('logout') == 'true'){
res.clearCookie('user');
res.clearCookie('pass');
req.session.destroy(function(e){ res.send('ok', 200); });
}
});
// creating new accounts //
app.get('/signup', function(req, res) {
res.render('signup', { locals: { title: 'Signup', countries : CT } });
});
app.post('/signup', function(req, res){
AM.signup({
name : req.param('name'),
email : req.param('email'),
user : req.param('user'),
pass : req.param('pass'),
country : req.param('country')
}, function(e, o){
if (e){
res.send(e, 400);
} else{
res.send('ok', 200);
}
});
});
// password reset //
app.post('/lost-password', function(req, res){
// look up the user's account via their email //
AM.getEmail(req.param('email'), function(o){
if (o){
res.send('ok', 200);
EM.dispatchResetPasswordLink(o, function(e, m){
// this callback takes a moment to return //
// should add an ajax loader to give user feedback //
if (!e) {
// res.send('ok', 200);
} else{
res.send('email-server-error', 400);
for (k in e) console.log('error : ', k, e[k]);
}
});
} else{
res.send('email-not-found', 400);
}
});
});
app.get('/reset-password', function(req, res) {
var email = req.query["e"];
var passH = req.query["p"];
AM.validateLink(email, passH, function(e){
if (e != 'ok'){
res.redirect('/');
} else{
// save the user's email in a session instead of sending to the client //
req.session.reset = { email:email, passHash:passH };
res.render('reset', { title : 'Reset Password' });
}
})
});
app.post('/reset-password', function(req, res) {
var nPass = req.param('pass');
// retrieve the user's email from the session to lookup their account and reset password //
var email = req.session.reset.email;
// destory the session immediately after retrieving the stored email //
req.session.destroy();
AM.setPassword(email, nPass, function(o){
if (o){
res.send('ok', 200);
} else{
res.send('unable to update password', 400);
}
})
});
// view & delete accounts //
app.get('/print', function(req, res) {
AM.getAllRecords( function(e, accounts){
res.render('print', { locals: { title : 'Account List', accts : accounts } });
})
});
app.post('/delete', function(req, res){
AM.delete(req.body.id, function(e, obj){
if (!e){
res.clearCookie('user');
res.clearCookie('pass');
req.session.destroy(function(e){ res.send('ok', 200); });
} else{
res.send('record not found', 400);
}
});
});
app.get('/reset', function(req, res) {
AM.delAllRecords( );
res.redirect('/print');
});
app.get('*', function(req, res) { res.render('404', { title: 'Page Not Found'}); });
};
}
To enable the express helpers like everyauth.loggedIn you have to call:
everyauth.helpExpress(app);
I am not sure why your code doesn't work. I had an example which works correctly but it needs mongodb. Just pushed to github if you want to have a try.
link to github

Resources