I am implementing local authentication using Passport.js. I have already implemented Github Oauth, which is fine but for some reason the local strategy is failing with the above error. I cannot find any source of the issue so far. I have read other posts but the usual answer is that you should change the require statement to:
var LocalStrategy = require('passport-local').Strategy;
However, I have already done this. Any help would be much appreciated. Here are my files as it stands. I have omitted the github strategy code to focus on the problem strategy:
signin.html:
<div class="signin-bg">
<!-- <div class="modal fade" id="login-modal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true" style="display: none;"> -->
<div class="modal-dialog">
<div class="loginmodal-container">
<h1>Login using Github</h1><br>
<i class="icon-github-sign"></i>
<h3>Or Use your Email</h3>
<form action="/signin" method="post">
<input type="text" name="username" placeholder="Email">
<input type="password" name="password" placeholder="Password">
<input type="submit" name="login" class="login loginmodal-submit" value="Login">
</form>
<div class="login-help">
Register - Forgot Password
</div>
</div>
</div>
routes.js:
var User = require('./models/userModel');
var passport = require('passport');
var authStore = require('./config/authStore');
module.exports = function(app){
app.get('/signin', function(req, res, next){
res.render('signin', { message: req.flash('signinMessage') });
});
app.post('/signin', passport.authenticate('local', {
successRedirect: '/storyBoard',
failureRedirect: '/signin',
failureFlash: true
}));
app.get('/signup', function(req, res){
res.render('signup', { message: req.flash('signupMessage') });
});
app.post('/signup', passport.authenticate('local', {
successRedirect: '/signin',
failureRedirect: '/signup',
failureFlash: true
}));
function isLoggedIn(req, res, next) {
if(req.isAuthenticated()){
return next();
}
res.redirect('/#/signin');
}
};
passport.js
var User = require('../models/userModel.js');
var passport = require('passport');
var GithubStrategy = require('passport-github').Strategy;
var LocalStrategy = require('passport-local').Strategy;
var bcrypt = require('bcrypt');
module.exports = function(passport) {
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
User.findUserByGithubId(id, function(err, user) {
user ? done(null, user) : done(err, null);
});
});
passport.use('local', new LocalStrategy({
usernameField: 'email',
passwordField: 'password',
passReqToCallback: true
},
function(req, email, password, done){
process.nextTick(function(){
User.findLocalUser(req.email, function(err, user){
if(err)
return done(err);
if(!user)
return done(null, false, req.flash('signinMessage', 'No user found'));
if(!User.generateHash(password)){
return done(null, false, req.flash('signinMessage', 'Invalid password'));
}
return done(null, user);
});
});
}
));
Well, i'm not sure what you are doing wrong exactly since you not paste all your code, but here is a express silly working sample with passport and connect flash, good luck.
var express = require('express');
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var flash = require('connect-flash');
// You need session to use connect flash
var session = require('express-session');
var bodyParser = require('body-parser');
var app = express();
app.use(bodyParser.urlencoded({extended: true}));
app.use( session({
saveUninitialized : true,
secret : 'Some Secret' ,
resave : true,
}));
app.use( passport.initialize());
app.use( passport.session());
app.use(flash());
// Authentication
passport.use(
new LocalStrategy(
{},
function(username, password, done) {
// Fake user definition, just a sample.
var user = {name: 'fake', password: 'fake'};
// Here you can put your async authentication method from db
if(user.name === username && user.password === password) {
return done(null, {
username: username
});
}
else {
return done(null, false,{});
}
})
);
passport.serializeUser( function(user, done) {
return done(null, user);
});
passport.deserializeUser( function(user, done) {
return done(null, user);
});
app.get('/', function(req, res) {
var htmlToSend = '';
var error = req.flash('error')[0];
if(error)
htmlToSend += '<div style="background-color:red; width:30%;">' + error + '</div>';
htmlToSend += '<form action="/login" method="post"> \
<input name="username"/> \
<input type="password" name="password"/> \
<button> send \
</form>';
res.send(htmlToSend);
});
app.post('/login', passport.authenticate('local', {
failureRedirect: '/',
successFlash: 'Welcome!',
failureFlash: 'User/Password Invalid!'
}),
function(req, res) {
res.send('Loged In as '+ req.user.username);
});
app.listen(3000, function() {
console.log('started');
});
Related
im making a simple todo list app , but am getting an error Cannot GET /
I think it has something to do with not creating a home route , also there might be a bug in index.ejs , but not sure exactly what it is. Any help is greatly appreciated ! thanks !!
app.js
// Dependencies
var express = require('express'),
path = require('path'),
bodyParser = require('body-parser'),
mongoose = require('mongoose'),
cookieParser = require('cookie-parser'),
expressSession = require('express-session'),
passport = require('passport'),
passportLocal = require('passport-local');
// MongoDB
mongoose.connect('mongodb://localhost/todos');
// Express
var app = express();
// Configuration
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());
// app.use(cookieParser);
app.use(expressSession({
secret: 'secret-key',
resave: false,
saveUninitialized: false
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(express.static(path.join(__dirname, 'bower_components')));
app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, 'views'));
// Route
app.use('/todo', require('./routes/todo'));
app.use('/', require('./routes/user'));
// Start Server
app.listen(3000);
console.log('TODO app is running...');
routes/user.js
var express = require('express');
var mongoose = require('mongoose');
var router = express.Router(),
cookieParser = require('cookie-parser'),
expressSession = require('express-session'),
passport = require('passport'),
passportLocal = require('passport-local');
require('../models/user');
var User = mongoose.model('user');
passport.use( new passportLocal.Strategy(function(username, password, done){
User.findOne({ username: username }, function (err, user) {
console.log(user);
if (err) { return done(err); }
if (!user) {
return done(null, false, { message: 'Incorrect username.' });
}
if (user.password != password) {
return done(null, false, { message: 'Incorrect password.' });
}
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);
});
});
router.get('/login', function(req, res){
if(req.isAuthenticated()){
res.redirect('/todo');
}
res.render('login', { message: req.session.messages });
});
router.post('/login', loginPost);//passport.authenticate('local'), function(req, res){
// res.redirect('/todo');
// });
function loginPost(req, res, next) {
passport.authenticate('local', function(err, user, info) {
if (err) {
return next(err);
}
if (!user) {
req.session.messages = info.message;
return res.redirect('/login');
}
req.logIn(user, function(err) {
if (err) {
req.session.messages = "Error";
return next(err);
}
// set the message
return res.redirect('/todo');
});
})(req, res, next);
}
router.get('/logout', function(req, res){
req.logout();
req.session.messages = "";
res.redirect('/login');
});
router.get('/signup', function(req, res){
if(req.isAuthenticated()){
res.redirect('/todo');
}
res.render('signup');
});
router.post('/signup', function(req, res){
new User({username: req.body.username, password: req.body.password}).save(function(err, doc){
if(err) res.json(err);
else res.redirect('/login');
});
});
module.exports = router;
routes/todo.js
var express = require('express');
var mongoose = require('mongoose');
var router = express.Router();
require('../models/todo');
require('../models/user');
var todo = mongoose.model('todo');
function isAuthenticated(req, res, next) {
// CHECK THE USER STORED IN SESSION FOR A CUSTOM VARIABLE
// you can do this however you want with whatever variables you set up
if (req.isAuthenticated())
return next();
// IF A USER ISN'T LOGGED IN, THEN REDIRECT THEM SOMEWHERE
res.redirect('/login');
}
router.get('/', isAuthenticated, function(req, res){
console.log(req.session.passport.user);
var User = mongoose.model('user'), userData;
User.find({ _id: req.session.passport.user}, function(err, user){
console.log(user);
userData = user; return true;
}).limit(1);
console.log(userData);
todo.find({user: req.session.passport.user}, function(err, todos){
res.render('index', {items:todos, userData:userData});
});
});
router.post('/add', function(req, res){
new todo({task: req.body.task, user: req.session.passport.user}).save(function(err, doc){
if(err) res.json(err);
else res.redirect('/todo');
});
});
router.get('/delete/:id', function(req, res){
todo.remove({_id: req.params.id}, function(err){
res.redirect('/todo');
});
});
router.post('/update', function(req, res){
todo.where({_id: req.body.id}).update({status: req.body.status}, function(err, doc){
if(err) res.json(err);
else res.send(200);
});
});
module.exports = router;
views/index.ejs
<!DOCTYPE html>
<html>
<head>
<title>EHad Todo App</title>
<link rel="stylesheet" type="text/css" href="bootstrap/dist/css/bootstrap.css">
<link rel="stylesheet" type="text/css" href="todo.css">
</head>
<body>
<div class="container">
<div class="row">
<div class=".col-md-6 .col-md-offset-3">
<section class="panel tasks-widget">
<header class="panel-heading">
<p class="bg-primary"><%= userData[0].username %> Todo list</p>
</header>
<div class="panel-body">
<div class="task-content">
<ul class="task-list">
<% for (var i = 0; i < items.length; i++) { %>
<li class="task-<%= items[i].status %>">
<div class="task-checkbox">
<input type="checkbox" class="task-list-check" value="<%= items[i]._id %>" <% if(items[i].status == 'done'){ %> checked <% }%> >
</div>
<div class="task-title">
<span class="task-title-sp"><%= items[i].task %></span><sub class="date"><%= items[i].date.toDateString() %></sub>
<div class="pull-right hidden-phone">
<button class="btn btn-danger btn-xs">x</i></button>
</div>
</div>
</li>
<% } %>
</ul>
</div>
<div class=" add-task-row">
<form action="todo/add" method="post">
<div class="form-group">
<input type="text" class="form-control" name="task" placeholder="ADD Task">
</div>
<button type="submit" class="btn btn-success btn-sm pull-right">Add New Tasks</button>
</form>
</div>
<span style="font-size:12px">Logout</span>
<div><p class="bg-info">copyright By #emranulhadi 2015</p></div>
</div>
</section>
</div>
</div>
</div>
<script type="text/javascript" src="jquery/dist/jquery.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$(".btn-danger").on("click", function(e){
var r = confirm("Are You Sure? You want to DELETE!!!");
if (r == true) {
return true;
} else {
e.preventDefault();
return false;
}
});
$('.task-list-check').click(function() {
var taskStatus = "done";
if($(this).is(":checked")){
$(this).parent().parent().addClass('task-done');
} else {
$(this).parent().parent().removeClass('task-done');
taskStatus = "new";
}
$.post( "todo/update", {id: $(this).val(), status: taskStatus}, function( data ) {
console.log(data);
return true;
});
});
});
</script>
</body>
</html>
In your routes/user.js file, define another route definition for /, and render whatever view you want for the index route.
router.get('/', (req, res){
res.render("/path/to/view/file");
});
I'm trying to authenticate users on my website and I got this error
Unknown authentication strategy 'local-login'
I've tried changing the name of the strategy, also I've read other threads in SO but didn't find a solution.
// Passport
module.exports = function(passport) {
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
connection.query('SELECT * FROM `users` WHERE `id` = ' + connection.escape(id), function(err, rows) {
done(err, rows[0]);
});
});
passport.use('local-login', new LocalStrategy({
usernameField : 'username',
passwordField : 'password'
},
function(req, username, password, done) {
connection.query('SELECT * FROM `users` WHERE `username` = ' + connection.escape(username), function(err, rows) {
if(err)
return done(err);
if(!rows.length) {
return done(null, false, req.flash('loginMessage', 'Invalid username or password. Please try again.'));
}
if(!(rows[0].password == password))
return done(null, false, req.flash('loginMessage', 'Invalid username or password. Please try again.'));
return done(null, rows[0]);
});
}));
}
// Express Router
app.use(sessionMiddleware);
app.use(passport.initialize());
app.use(passport.session());
app.use(flash());
app.use('/static', express.static('./static'));
app.post('/login/auth', passport.authenticate('local-login', {
successRedirect: '/dashboard',
failureRedirect: '/',
failureFlash: true
}));
First check your installation with:
npm install passport passport-local --save
Then import passport like below:
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
before your app.use() methods:
...
..
app.use(passport.initialize());
app.use(passport.session());
Then use it as follows. (No need to give 'local-login' as a first argument)
passport.use(new LocalStrategy({
usernameField : 'username',
passwordField : 'password'
}, (req, username, password, done) => {
// Your logic here...
...
..
}));
}
Finally in your router:
app.post('/login/auth', passport.authenticate('local', {
successRedirect: '/dashboard',
failureRedirect: '/',
failureFlash: true }),
function(req, res) {
res.redirect('/');
});
More info:
passport-local
I have a problem with post request in angularJS to express.
On the client side there is a HTML form definition:
<div ng-controller="LoginCtrl">
<form ng-submit="login()">
<div>
<label>Username</label>
<input ng-model="username">
<label>Password</label>
<input ng-model="password" type="password">
</div>
<button type="submit">Submit</button>
</form>
</div>
and the post method in the Angular controller:
angular.module('app')
.controller('LoginCtrl', ['$scope', '$state', '$http', function($scope, $state, $http) {
$scope.login= function(username, password) {
console.log('Login');
$http.post('/login', {username:username, password:password}).then(function(response) {
if(response.data.success) {
console.log('logged in');
$state.go('home');
}
else {
console.log('failed to log in');
}
});
};
$scope.user = {
username: '',
password: ''
};
}]);
On the server side in routes there is users.js file in which is defined middleware:
var express = require('express');
var router = express.Router();
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var User = require('../models/user');
// Login
router.get('/login', function(req, res){
res.render("login");
});
passport.use('local', new LocalStrategy(
function(username, password, done) {
User.getUserByUsername(username, function(err, user){
if(err) throw err;
if(!user){
return done(null, false, {message: 'Unknown User'});
}
User.comparePassword(password, user.password, function(err, isMatch){
if(err) throw err;
if(isMatch){
return done(null, user);
} else {
return done(null, false, {message: 'Invalid password'});
}
});
});
}));
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
User.getUserById(id, function(err, user) {
done(err, user);
});
});
router.post('/login',
passport.authenticate('local', {successRedirect:'/', failureRedirect:'/login',failureFlash: true}),
function(req, res) {
res.redirect('/');
});
module.exports = router;
When I click on the submit button, the error message appears in the console: POST http://localhost:3000/login 404 (Not Found)
Does someone know where could be the problem?
You are missing post for login. You need something like:
// Login
router.post('/login', function(req, res){
// validate user credentials and login user
});
Using Scotch.io and the official passport docs as reference, I'm implementing a Node/Express/Sequelize application where I have a basic signup form with fields for email and password:
./views/signup.ejs
<form action="/signup" method="post">
<div class="form-group">
<label>Email</label>
<input type="text" class="form-control" name="email">
</div>
<div class="form-group">
<label>Password</label>
<input type="password" class="form-control" name="password">
</div>
<button type="submit" class="btn btn-warning btn-lg">Signup</button>
</form>
with the passport-local strategy defined as follows:
./config/passport.js
const db = require('./sequelize');
const passport = require('passport'),
LocalStrategy = require('passport-local').Strategy;
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(user, done) {
db.User.findById(id, function(err, user) {
done(err, user);
});
});
passport.use('local', new LocalStrategy({
emailField : 'email',
passwordField : 'password',
passReqToCallback : true
},
function(email, password, done){
process.nextTick(function() {
// find a user whose email is the same as the forms email
// we are checking to see if the user trying to login already exists
db.User.findOne({ email : email }, function(err, user) {
// if there are any errors, return the error
if (err)
return done(null, false, {message: err});
// check to see if theres already a user with that email
if (user) {
return done(null, false, {message: 'User already exists'});
}
else {
// if there is no user with that email
// create the user
db.User.create({
email: email,
password: password
});
return done(null, false, {message: 'User created'});
}
});
});
}
));
module.exports = passport;
and lastly the routes are taken care of in
app.js
const express = require('express');
const http = require('http');
const https = require('https');
const sequelize = require('sequelize');
const db = require('./config/sequelize');
const querystring = require('querystring');
const config = require('./config/config');
const passport = require('./config/passport');
const bodyParser = require( 'body-parser' );
const env = 'development';
const app = express();
const port = 3000;
app.use( bodyParser.urlencoded({ extended: true }) );
app.use(passport.initialize());
app.use(passport.session());
app.set('view engine', 'ejs');
app.listen(port);
app.post('/signup', function(req, res, next){
const user = req.body;
passport.authenticate('local', function(err, user, info){
if (err){
res.send({success: false, message: 'authentication failed'});
}
else{
console.log(info);
res.json({message: "success"});
}
})(req, res, next)
});
What I expect to happen if the local strategy works is for the res.json({message: "success"}) to appear on the browser and for the database to be updated per the specifications of ./config/passport.js. The {message: "success"} is appearing on the screen, but the database is not being updated, which leads me to believe that something is wrong with my implementation in ./config/passport.js. In app.js, the console.log(info) statement shows the following message on cmd:
Executing (default): SELECT `id`, `username`, `email`, `password`, `createdAt`,
`updatedAt` FROM `Users` AS `User` LIMIT 1;
which makes it look like the insertions might be going through but inspections of the db reveal otherwise. I have done previous sanity checks with CRUD updates to confirm that the basic implementation of Sequelize works, and will provide the schema of the table upon request. How else can I debug this situation?
Read about how to make queries in sequelize
http://docs.sequelizejs.com/en/latest/docs/querying/
you should use promises, like this:
db.User.findOne({ where: {email : email }})
.then(function(user){
//do smth;
})
.catch(function(error){
console.log(error);
});
I'm trying to implement passport.js in a Node/Express/Sequelize app. I'm trying to stay as faithful as possible to both the official documentation and the Scotch.io tutorial, and currently have the following relevant code segments in my scaffolding:
app.js
const express = require('express');
const http = require('http');
const https = require('https');
const sequelize = require('sequelize');
const db = require('./config/sequelize');
const config = require('./config/config');
const passport = require('./config/passport');
const app = express();
const port = 3000;
app.use(passport.initialize());
app.use(passport.session());
app.set('view engine', 'ejs');
app.listen(port);
app.post('/signup', passport.authenticate('local', function(req, res, next, err){
if (err) { console.log(err); }
res.json(req.body);
}));
./config/passport.js
const db = require('./sequelize');
const passport = require('passport'),
LocalStrategy = require('passport-local').Strategy;
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(user, done) {
db.User.findById(id, function(err, user) {
done(err, user);
});
});
passport.use('local', new LocalStrategy({
usernameField : 'email',
passwordField : 'password',
passReqToCallback : true
},
function(email, password, done){
process.nextTick(function() {
db.User.findOne({ email : 'local.email' }, function(err, user) {
if (err)
return done(err);
if (user) {
return done(null, false, req.flash('signupMessage', 'That email is already taken.'));
}
else {
db.User.create({
username: 'local.email',
password: 'local.password'
});
}
});
});
}
));
module.exports = passport;
./views/signup.ejs
<!-- LOGIN FORM -->
<form action="/signup" method="post">
<div class="form-group">
<label>Email</label>
<input type="text" name="username">
</div>
<div class="form-group">
<label>Password</label>
<input type="password" name="password">
</div>
<button type="submit">Signup</button>
</form>
With this implementation in hand, I fire up the app, enter the email address and password to sign up on ./views/signup.ejs, and get the following error:
TypeError: Cannot read property 'body' of null
at C:\Users\Adam\Desktop\repos\chinese-democracy\app.js:45:15
at allFailed (C:\Users\Adam\Desktop\repos\chinese-democracy\node_modules\passport\lib\middleware\authenticate.js:94:18)
at attempt (C:\Users\Adam\Desktop\repos\chinese-democracy\node_modules\passport\lib\middleware\authenticate.js:167:28)
...
This indicates that req.body is being returned as null, and I have a suspicion it has to do with the manner in which the deserializeUser and serializeUser functions are defined in ./config/passport.js, but how can I get verbose error outputs to determine what the exact cause is? Also, I have done sanity CRUD checks with my Sequelize database so I omitted that file, but will provide it as an edit if any of you think that would be of use in resolving this issue.
Please try this in your app.js :
app.post('/signup', passport.authenticate('local'), function(req, res, next, err){
//^ close
// If this function gets called, authentication was successful.
res.redirect('/users/' + req.user.username);
});
If you need a custom callback:
app.post('/signup', function(req, res, next){
passport.authenticate('local', function(err, user, info) {
//Your code here
})(req, res, next);
});
Please refer to http://passportjs.org/docs/authenticate for more details.