JWT login issue - node.js

I'm using JWT with Passport for authentication in my app. I use MongoDB and Mongoose for database. I added a user with username = manager and password=manager with addManager function the password saved in db is not "manager" and is : "$2b$10$O7YAgTJKETOY.lanZoErWum2e6ZPpVi.RjMp0VHKfMT82z9uEmrlS" I don't know why! and I can't login with password :"manager". I don't know what is the problem .I used this article for my code. if you understand what't wrong please tell me.
app.js :
//settings and Requirements
const express = require('express');
const bodyParser = require('body-parser');
const cookieParser = require('cookie-parser');
const path = require('path');
const mongoose = require('mongoose');
const passport = require('passport');
const config = require('./api/config/database');
mongoose.connect(config.database);
let db = mongoose.connection;
require('./api/config/auth');
db.once('open', function () {
console.log('connected to mongodb...');
});
db.on('error', function (error) {
console.log(error);
});
let User = require('./api/models/user');
let basics = require('./api/config/basics');
let port = process.env.PORT || 8080;
const app = express();
app.use(bodyParser.urlencoded({
extended: false
}));
app.use(bodyParser.json());
app.use(bodyParser.json({
type: 'application/vnd/api+json'
}));
app.use(cookieParser());
basics.addManager(basics.manager);
router(app);
app.listen(port, function (err) {
if(err)
console.log(err);
console.log("port is " + port);
});
auth.js:
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
const User = require('../../api/models/user');
const passportJWT = require("passport-jwt");
const JWTStrategy = passportJWT.Strategy;
const ExtractJWT = passportJWT.ExtractJwt;
passport.use(new LocalStrategy({
usernameField: 'username',
passwordField: 'password'
},
function (username, password, cb) {
//this one is typically a DB call. Assume that the returned user object is pre-formatted and ready for storing in JWT
return User.findOne({username:username, password:password})
.then(user => {
if (!user) {
return cb(null, false, {message: 'Incorrect username or password.'});
}
return cb(null, user, {message: 'Logged In Successfully'});
})
.catch(err => cb(err));
}
));
passport.use(new JWTStrategy({
jwtFromRequest: ExtractJWT.fromAuthHeaderAsBearerToken(),
secretOrKey : 'your_jwt_secret'
},
function (jwtPayload, cb) {
//find the user in db if needed. This functionality may be omitted if you store everything you'll need in JWT payload.
return User.findOneById(jwtPayload.id)
.then(user => {
return cb(null, user);
})
.catch(err => {
return cb(err);
});
}
));
authenticate.js:
const express = require('express');
const passport = require('passport');
const jwt = require('jsonwebtoken');
const router = express.Router();
router.post('/login', function (req, res, next) {
console.log(req.body);
passport.authenticate('local', {session: false}, (err, user, info) => {
console.log(user);
if (err || !user) {
return res.status(400).json({
message: info ? info.message : 'Login failed',
user : user
});
}
req.login(user, {session: false}, (err) => {
if (err) {
res.send(err);
}
// generate a signed son web token with the contents of user object and return it in the response
const token = jwt.sign(user, 'your_jwt_secret');
return res.json({user, token});
});
})(req, res);
});
module.exports = router;
addManager:
`
addManager : function(manager){
let newUser = new User({
username : manager.username,
password : manager.password,
isManager : true
});
newUser.save(function(err , user){
if(err)
console.log(err);
console.log('manager added successfuly');
});
}
`

Related

Getting error TypeError: next is not a function

I'm getting error "TypeError: next is not a function" while trying to authenticate dashboard route in nodejs.
I am trying to make and CRUD app with node and mongoDB suing these modules express ejs mongoose bcryptjs passport passport-local.
Getting this error when I submit login form.
I am new in nodejs, Please help me
Thanks in advance.
auth/protect.js file
const protectRoute = (req, res, next) =>{
if (req.isAuthenticated()) {
return next();
}
console.log('Please log in to continue');
res.redirect('/login');
}
const allowIf = (req, res, next) =>{
if (!req.isAuthenticated()) {
return next();
}
res.redirect('/dashboard');
}
module.exports = {
protectRoute,
allowIf,
};
routes/login.js file
const express = require("express");
const {
registerView,
loginView,
registerUser,
loginUser,
} = require("../controllers/loginController");
const { dashboardView } = require("../controllers/dashboardController");
const { protectRoute } = require("../auth/protect");
const router = express.Router();
router.get("/register", registerView);
router.get("/login", loginView);
router.get("/", loginView);
//Dashboard
router.get("/dashboard", protectRoute, dashboardView);
router.post("/register", registerUser);
router.post("/login", loginUser);
module.exports = router;
server.js file
const express = require("express");
const cors = require("cors");
const app = express();
const mongoose = require('mongoose');
const session = require('express-session');
const passport = require("passport");
const { loginCheck } = require("./auth/passport");
var corsOptions = {
origin: "http://localhost:8081"
};
app.use(cors(corsOptions));
const db = require("./models");
db.mongoose
.connect(db.url, {
useNewUrlParser: true,
useUnifiedTopology: true
})
.then(() => {
console.log("Connected to the database!");
})
.catch(err => {
console.log("Cannot connect to the database!", err);
process.exit();
});
app.set('view engine', 'ejs');
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(session({
secret:'oneboy',
saveUninitialized: true,
resave: true
}));
app.use(passport.initialize());
app.use(passport.session());
// simple route
app.use('/', require('./routes/login'));
const PORT = process.env.PORT || 8080;
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}.`);
});
I have missed to call a function loginCheck(passport); in my server.js file that's why I was getting error during login form submission.
server.js starting code
const express = require("express");
const cors = require("cors");
const app = express();
const mongoose = require('mongoose');
const session = require('express-session');
const passport = require("passport");
//var LocalStrategy = require('passport-local').Strategy;
const { loginCheck } = require("./auth/passport");
loginCheck(passport);
........................................
I was added this function in auth/passport.js file
passport.js
//js
const bcrypt = require("bcryptjs");
LocalStrategy = require("passport-local").Strategy;
//Load model
const User = require("../models/User");
const loginCheck = passport => {
passport.use(
new LocalStrategy({ usernameField: "email" }, (email, password, done) => {
//Check customer
User.findOne({ email: email })
.then((user) => {
if (!user) {
console.log("wrong email");
return done();
}
//Match Password
bcrypt.compare(password, user.password, (error, isMatch) => {
if (error) throw error;
if (isMatch) {
return done(null, user);
} else {
console.log("Wrong password");
return done();
}
});
})
.catch((error) => console.log(error));
})
);
passport.serializeUser((user, done) => {
done(null, user.id);
});
passport.deserializeUser((id, done) => {
User.findById(id, (error, user) => {
done(error, user);
});
});
};
module.exports = {
loginCheck,
};
If you are trying to use next() in normal function then it will give an error
const allowIf = (req, res, next) =>{
return next(); // throw an error - TypeError: next is not a function
}
allowIf();
So use next() as a Callback argument to the middleware function. It will work fine in this case. Try this:
const protectRoute = (req, res, next) =>{
console.log('protectRoute');
return next();
}
app.get('/', protectRoute);

Passport Local Strategy returns not found

I'm trying to make a register/login with node, express and mongoose. I want to register and login users and if they aren't logged in they can't retrieve data from the api.
To make the login and register i have been watching this tutorial: Link it isn't as addecuate for my needs because half of the efforts and code goes into the ejs but i have been okay until the passport login.
I have created my local strategy in config/passport.js:
const LocalStrategy = require("passport-local").Strategy;
const bcrypt = require("bcryptjs");
const User = require("../models/user");
module.exports = function (passport) {
passport.use(
new LocalStrategy({ usernameField: "email" }, (email, password, done) => {
User.findOne({ email: email })
.then((user) => {
if (!user) {
return done(null, false, {
message: "That email is not registered",
});
}
bcrypt.compare(password, user.password, (err, isMatch) => {
if (err) console.log(err);
if (isMatch) {
return done(null, user);
} else {
done(null, false, { message: "Incorrect Password" });
}
});
})
.catch((err) => console.log(err));
})
);
passport.serializeUser((user, done) => {
done(null, user.id);
});
passport.deserializeUser((id, done) => {
User.findById(id, (err, user) => {
done(err, user);
});
});
};
My app.js looks like this:
const express = require("express");
const cors = require("cors");
const usersRouter = require("./routes/users");
const passport = require("passport");
const session = require("express-session");
require("dotenv").config();
const app = express();
require("./config/passport")(passport);
const connectDB = require("./db/connect");
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(
session({
secret: "*****",
resave: true,
saveUninitialized: true,
})
);
app.use(passport.initialize());
app.use(passport.session());
app.use(cors());
app.use("/api/v1/users", usersRouter);
const PORT = process.env.PORT || 5000;
const start = async () => {
try {
await connectDB(process.env.MONGO_URI);
app.listen(PORT, console.log(`Server is listening on port: ${PORT}....`));
} catch (error) {
console.log(error);
}
};
const notFound = require("./middleware/notFound");
app.use(notFound);
start();
My users router looks like this:
const express = require("express");
const router = express.Router();
const { postRegister } = require("../controllers/register");
router.route("/register").post(postRegister);
const { postLogin } = require("../controllers/login");
router.route("/login").post(postLogin);
module.exports = router;
The register works perfectly, but the login controller doesn't. Each time i post to that endpoint instead of getting a succesMessage or failureMessage i get the page not found router that is called at the end of app.js, i checked if the router calls the login function via a console log and it does. Here is the code for the login controller:
const passport = require("passport");
const postLogin = (req, res, next) => {
console.log("The function has been triggered");
passport.authenticate("local", {
successMessage: "Login authenticated",
failureMessage: "Login failed",
})(req, res, next);
};
module.exports = {
postLogin,
};
Why don't I get the responses from the login controller or my local strategy and instead i get page not found when the Login controller actually works?

events.js:377 throw er; // Unhandled 'error' event / req.login is not a function

I have been in the process of building a server using node.js, express.js, Mongoose, and MongoDB. After trying to implement passport and JWT authentication, I have encountered an error (seen in the link) every time I try to make a request to my '/login' endpoint. This error occurs when I make a request through Postman using a username and password from my database to test if the user is assigned a JWT token.
https://i.stack.imgur.com/g6e4Z.png
All of my endpoints, except for the one in my auth.js file, work fine in my index.js file, which is the main file where everything gets imported. I do not have any problems getting/staying connected to my database, so this leads me to believe that the issue stems from some mistake in the error handling.
This is how the middleware is set up in the index.js file, right above my endpoints.
'use strict';
const express = require('express');
const morgan = require('morgan');
const mongoose = require('mongoose');
const Models = require('./models');
const Movies = Models.Movie;
const Genres = Models.Genre;
const Directors = Models.Director;
const Users = Models.User;
function displayErrorMsg(err) {
console.error(err);
res.status(500).send(`Error: ${err}`);
}
function resJSON(model, res) {
return model.find().then(data => res.json(data));
}
const app = express();
mongoose
.connect('mongodb://localhost:27017/filmfeverDB', {
useNewUrlParser: true,
useUnifiedTopology: true,
})
.then(res => console.log('DB Connected!'))
.catch(err => console.log(err, err.message));
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(express.static(`public`));
app.use(morgan('common'));
let auth = require('./auth')(app);
const passport = require('passport');
require('./passport');
passport.js
const passport = require("passport"),
LocalStrategy = require("passport-local").Strategy,
Models = require("./models.js"),
passportJWT = require("passport-jwt"),
config = require('./configs').config
let Users = Models.User,
JWTStrategy = passportJWT.Strategy,
ExtractJWT = passportJWT.ExtractJwt;
passport.use(
new LocalStrategy(
{
usernameField: "Username",
passwordField: "Password"
},
(username, password, callback) => {
console.log(username + " " + password);
Users.findOne({ Username: username }, (error, user) => {
if (error) {
console.log(error);
return callback(error);
}
if (!user) {
console.log("incorrect username");
return callback(null, false, {
message: "Incorrect username."
});
}
console.log("finished");
return callback(null, user);
});
}
)
);
passport.use(
new JWTStrategy(
{
jwtFromRequest: ExtractJWT.fromAuthHeaderAsBearerToken(),
secretOrKey: config.passport.secret
},
(jwtPayload, callback) => {
return Users.findById(jwtPayload._id)
.then(user => {
return callback(null, user);
})
.catch(error => {
return callback(error);
});
}
)
);
auth.js
const jwt = require("jsonwebtoken"),
passport = require("passport");
require("./passport");
let generateJWTToken = user => {
return jwt.sign(user, config.passport.secret, {
subject: user.Username,
expiresIn: config.passport.expiresIn,
algorithm: "HS256"
});
};
/* POST login. */
module.exports = router => {
router.post("/login", (req, res) => {
passport.authenticate("local", { session: false }, (error, user, info) => {
if (error || !user) {
return res.status(400).json({
message: "something is not right",
user: user
});
}
req.login(user, { session: false }, error => {
if (error) {
res.send(error);
}
let token = generateJWTToken(user.toJSON());
return res.json({ user, token });
});
})(req, res);
});
};
Here is my Mongoose connection and my imports of the auth.js, passport.js, and passport module files located in my index.js file.
mongoose
.connect('mongodb://localhost:27017/filmfeverDB', {
useNewUrlParser: true,
useUnifiedTopology: true,
})
.then(res => console.log('DB Connected!'))
.catch(err => console.log(err, err.message));
let auth = require('./auth')(app);
const passport = require('passport');
require('./passport');
If anyone has any ideas, please let me know.

Cannot call Passport local strategy

I'm a beginner in Angular 5 and I'm currently working on an app. So in login module, the passport local strategy is not working and passport.authenticate function is not working, and I can't seem to find the problem in my code.
Now I am not sure what is wrong because there is no error on the console and the return is null every time. That's why I'm copy pasting a lot of code.
Code is attached below.
Server.js file
const express = require('express');
const bodyParser = require('body-parser');
const path = require('path');
const http = require('http');
const cors = require('cors');
const app = express();
const cookieParser = require('cookie-parser');
const exphbs = require('express-handlebars');
const expressValidator = require('express-validator');
const flash = require('connect-flash');
const session = require('express-session');
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
// API file for interacting with MongoDB
const api = require('./routes/api');
const auth = require('./routes/auth_companies');
require('./models/passport');
// Parsers/middlewares
app.use(cors());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
app.use(cookieParser());
app.use(flash());
// Angular DIST output folder
app.use(express.static(path.join(__dirname, 'dist')));
app.use(express.static('public'));
// API location
app.use('/api', api);
app.use('/auth', auth);
// Express Session
app.use(session({
secret: 'secret',
saveUninitialized: true,
resave: true
}));
// Passport init
app.use(passport.initialize());
app.use(passport.session());
// Express Validator
app.use(expressValidator({
errorFormatter: function(param, msg, value) {
var namespace = param.split('.')
, root = namespace.shift()
, formParam = root;
while(namespace.length) {
formParam += '[' + namespace.shift() + ']';
}
return {
param : formParam,
msg : msg,
value : value
};
}
}));
// Connect Flash
app.use(flash());
// Global Vars
app.use(function (req, res, next) {
res.locals.success_msg = req.flash('success_msg');
res.locals.error_msg = req.flash('error_msg');
res.locals.error = req.flash('error');
res.locals.user = req.user || null;
next();
});
// Send all other requests to the Angular app
//app.get('*', (req, res) => {
// res.sendFile(path.join(__dirname, 'dist/index.html'));
//});
// start the server
//app.listen(app.get('port'), () => {
// console.log('server on port 3000');
//});
//Set Port
const port = process.env.PORT || '3000';
app.set('port', port);
const server = http.createServer(app);
console.log(port);
server.listen(port, () => console.log(Running on localhost:${port}));
Passport.js file
const express = require('express');
const router = express.Router();
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
const User = require ('./reg_company');
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
User.getUserById(id, function(err, user) {
done(err, user);
});
});
passport.use( new LocalStrategy(
function(email, password, done) {
console.log('9900---------------------------------', email)
User.getUserByEmail(email, 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.use('local.signup' , new LocalStrategy ({
passReqToCallback : true ,
emailfield:'email',
passwordfield:'password'
}, function(req, email, password, done){
User.findOne({'email':email}, function(err, user){
if (err)
{
return done(err);
}
if (user)
{
return done (null, false);
}
const newCompany=new User();
newCompany.email = req.body.email;
newCompany.password = req.body.passport;
User.createUser(newCompany, function(err, user){
if(err) throw err;
console.log(user);
return done(null, user);
});
})
}) )
Mongo File
const mongoose = require('mongoose');
const uri='mongodb://localhost/tourhubdb';
mongoose.connect(uri);
const db=mongoose.connection;
const bcrypt = require('bcryptjs');
//tourist Schema
let company_reg_schema = mongoose.Schema({
email:{
type:String,
require:true
},
password:
{
type:String,
require:true
}
});
let User = module.exports = mongoose.model('companies',company_reg_schema);
module.exports.createUser = function(newUser, callback){
bcrypt.genSalt(10, function(err, salt) {
bcrypt.hash(newUser.password, salt, function(err, hash) {
newUser.password = hash;
newUser.save(callback);
});
});
}
module.exports.getUserByEmail = function(email, callback){
var query = {email: email};
User.findOne(query, callback);
}
module.exports.getUserById = function(id, callback){
User.findById(id, callback);
}
module.exports.comparePassword = function(candidatePassword, hash, callback){
bcrypt.compare(candidatePassword, hash, function(err, isMatch) {
if(err) throw err;
callback(null, isMatch);
});
}
Routes file
const express = require("express");
const router = express.Router();
router.post('/login',function (req,res,next){
passport.authenticate('local-login', function (err ,user ,info){
})(req ,res ,next);
});
module.exports = router;
Just my two cents here...wherever you're returning done(null....) under
passport.use(), you could replace the null value with different errors for the different done() calls and see which one invokes and why.

TypeError: passport.initialize is not a function

Im using Node.js and passport, but for some reason i cant seem to access the passport.initialize function. it was working in another file but when i tried to use it on another project (the files below) wont work properly.
i add the relevant files.
server.js
const express = require('express');
const mongoose = require('mongoose');
const port = process.env.PORT || 3000;
const morgan = require('morgan');
const bodyParser = require('body-parser');
const methodOverride = require('method-override');
const app = express();
const authRoutes = require('./app/authRoutes.js');
mongoose.connect("mongodb://localhost/MeanMapApp");
const passport = require('./app/passport');
app.use(passport.initialize());
require('./app/routes.js')(app);
app.listen(port);
console.log('App listening on port ' + port);
passport.js
const passport = require('passport');
const request = require('request');
const LocalStrategy = require('passport-local').Strategy;
const User = require('../models/User');
passport.serializeUser((user, done) => {
done(null, user.id);
});
passport.deserializeUser((id, done) => {
User.findById(id, (err, user) => {
done(err, user);
});
});
authRoutes.js
var express = require('express');
const bluebird = require('bluebird');
const crypto = bluebird.promisifyAll(require('crypto'));
const passport = require('passport');
const User = require('../models/User');
/**
* GET /login
* Login page.
*/
exports.getLogin = (req, res) => {
if (req.user) {
return res.redirect('/account');
}
res.render('account/login', {
title: 'Login'
});
};
/**
* POST /login
* Sign in using email and password.
*/
exports.postLogin = (req, res, next) => {
req.assert('email', 'Email is not valid').isEmail();
req.assert('password', 'Password cannot be blank').notEmpty();
req.sanitize('email').normalizeEmail({ remove_dots: false });
const errors = req.validationErrors();
if (errors) {
req.flash('errors', errors);
return res.redirect('/login');
}
passport.authenticate('local', (err, user, info) => {
if (err) { return next(err); }
if (!user) {
req.flash('errors', info);
return res.redirect('/login');
}
req.logIn(user, (err) => {
if (err) { return next(err); }
req.flash('success', { msg: 'Success! You are logged in.' });
res.redirect('/account');
});
})(req, res, next);
};
/**
* GET /logout
* Log out.
*/
exports.logout = (req, res) => {
req.logout();
res.redirect('/');
};
/**
* GET /signup
* Signup page.
*/
exports.getSignup = (req, res) => {
if (req.user) {
return res.redirect('/account');
}
res.render('account/signup', {
title: 'Create Account'
});
};
/**
* POST /signup
* Create a new local account.
*/
exports.postSignup = (req, res, next) => {
req.assert('email', 'Email is not valid').isEmail();
req.assert('password', 'Password must be at least 4 characters long').len(4);
req.assert('confirmPassword', 'Passwords do not match').equals(req.body.password);
req.sanitize('email').normalizeEmail({ remove_dots: false });
const errors = req.validationErrors();
if (errors) {
req.flash('errors', errors);
return res.redirect('/signup');
}
const user = new User({
email: req.body.email,
password: req.body.password
});
User.findOne({ email: req.body.email }, (err, existingUser) => {
if (err) { return next(err); }
if (existingUser) {
req.flash('errors', { msg: 'Account with that email address already exists.' });
return res.redirect('/signup');
}
user.save((err) => {
if (err) { return next(err); }
req.logIn(user, (err) => {
if (err) {
return next(err);
}
res.redirect('/account');
});
});
});
};
I believe you are doing this the wrong way,instead of
const passport = require('./app/passport');
app.use(passport.initialize());
You should be using
var passport = require('passport');
require('./app/passport');
app.use(passport.initialize());
That should solve it
I'm using ExpressJS + TS and the following returned the same error.
import * as passport from 'passport';
app.use(passport.initialize());
However, this worked
import { initialize } from 'passport';
app.use(initialize());
Not sure why this is happening in the ExpressJS app with TS. I also have the first way implemented on a Google Cloud Function with TS and it works fine.
I also get the same err in the VS code hope it will help you
hello! Buddy everything you write correct but some normal syntax err. it's hard to find
here is my code that helps you to implement the authentication
just I used var at the place of Const
app.js code
var express= require("express");
var mongoose=require("mongoose");
var passport = require('passport');
var bodyParser=require("body-parser");
var User = require("./models/user");
var localStrategy=require("passport-local").Strategy;
var passportLocalMongoose=require("passport-local-mongoose");
mongoose.connect("mongodb://localhost/auth_demo_app",{ useNewUrlParser: true , useUnifiedTopology: true});
var app=express();
app.set("view engine" ,"ejs");
app.use(bodyParser.urlencoded({extended:true}));
app.use(require("express-session")({
secret:"login",
resave :false,
saveUninitialized:false
}));
app.use(passport.initialize());
app.use(passport.session());
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
//=============================================================
//routes
app.get("/",function(req,res){
res.render("home");
});
app.get("/secret",function(req,res){
res.render("secret");
});
//Auth routes============
//show form
app.get("/register",function(req,res){
res.render("register");
});
//heandling User Sign UP
app.post("/register",function(req,res){
req.body.username
req.body.password
User.register(new User({username : req.body.username}),req.body.password,function(err,user){
if(err){
console.log(err);
return res.render("register");
}
passport.authenticate("local")(req,res,function(){
res.redirect("/secret");
})
});
});
app.listen(8080,function(){
console.log("here i am");
});
you can change your local port
Do some changes as par your requirement and you good to go

Resources