I have my express server in Node app with OAuth using passport. There is no issue in registration and even with wrong credentials .But when I try to login with correct credentials the server not all responding .My url keeps on loading.
Even there is no error in console.
My passport local strategy code:
const MyStrategy = require('passport-local').Strategy
const bcrypt = require('bcrypt')
const mongoose = require('mongoose')
//User model
const User = require('./models/user')
function initialize(passport) {
const authUser = (email,password,done) =>{
User.findOne({ email : email })
.then(user =>{
if (!user) {
return done(null,false,{message: "User doesn't Exists"})
}
bcrypt.compare(password,user.password,(err,found)=>{
if (err) {
throw err
}
if (found) {
return done(null,user)
} else {
return done(null,false,{message : "Incorrect Credentials"})
}
})
})
.catch(err=>{
throw err
})
}
passport.use(new MyStrategy({ usernameField: 'email' },authUser))
passport.serializeUser((user,done) => { })
passport.deserializeUser((id,done) => { })
}
module.exports = initialize
App.js
const express = require("express");
const app = express();
const mongoose = require('mongoose')
require('dotenv').config()
const bodyParser = require("body-parser");
const ejs = require("ejs");
const passport = require('passport')
const flash = require("express-flash")
const session = require("express-session")
//DB connection
const mongo_uri = process.env.MONGODB_URI || "mongodb://localhost/testDB";
mongoose.connect(mongo_uri, {useNewUrlParser: true , useUnifiedTopology: true});
mongoose.connection.once('open', () => console.log("Connected"))
.on('npm ierror' , ()=> { console.log('Error') })
const Users = require('./models/user');
//OAuth
const UserAuth = require('./user_auth')
UserAuth(passport)
//Body Parser
app.use(express.urlencoded({extended: false}));
app.use(express.json());
//ejs
app.set('view engine', 'ejs');
app.use(express.static("public"));
//Session
app.use(session({
secret:process.env.SECRET||'secret',
saveUninitialized:false,
resave:false
}))
app.use(passport.initialize())
app.use(passport.session())
//Flash
app.use(flash())
//Routes
const regisrouter= require('./routes/register')
const indexrouter= require('./routes/index')
const homeRouter = require('./routes/home')
const composeRouter = require('./routes/compose')
const postRouter = require('./routes/post');
app.use('/',regisrouter);
app.use(indexrouter);
app.use(homeRouter);
app.use(composeRouter);
app.use('/posts',postRouter);
app.listen(3000, function() {
console.log("Server started on port 3000");
});
Login route page:
const express = require('express');
const router = express.Router()
const passport = require('passport')
router.post("/login", passport.authenticate('local',{
successRedirect: '/',
failureRedirect: '/login',
failureFlash : true
}));
router.get("/login",(req,res) =>{
res.render('index')
})
module.exports = router
I've been debugging this for 3 days but noting is improved. I guess there may be problem with async function but couldn't find anything
It looks like passport.serializeUser() and passport.deserializeUser() functions need to be updated... here is a great post on serialize and deserialize.
// used to serialize the user for the session
passport.serializeUser(function(user, done) {
done(null, user.id);
});
// used to deserialize the user
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user) {
done(err, user);
});
});
Also, make sure the passport-setup where you initialize the local-strategy is imported into App.js.
Related
I have been trying to build the authentication using PassportJs and MongoDB. I am using PassportJS only to log in. But, while submitting the post request it does not redirect me to the failureRedirect route, nor to the SuccessRedirect one, instead, the web page enters into an endless loop.
The code I have written is -
It has 2 files- app.js and user.js
App.js file -
const express = require("express");
const bodyParser = require("body-parser");
const ejs = require("ejs");
const passport = require('passport');
const mongoose = require('mongoose');
require('./db/db')
var fileupload = require('express-fileupload');
const path = require('path');
const app = express();
app.use(fileupload({
useTempFiles: true
}));
const session = require('express-session');
const mongostore = require('connect-mongo');
app.use(express.static(path.join(__dirname,'public')));
// session middle ware
app.use(session({
secret : 'mysupersecret',
resave : false,
saveUninitialized : false,
store: mongostore.create({
mongoUrl: process.env.DB,
}),
cookie : { maxAge : 180 * 60 * 1000 }
}));
app.set("view engine", "ejs");
app.use(bodyParser.urlencoded({ extended: false }));
app.use(express.static("public"));
app.use(bodyParser.json());
app.use(passport.initialize());
app.use(passport.session());
app.get("/", (req, res) => {
res.render("index");
});
app.use("/admin", require("./routes/admin"));
app.use("/user", require("./routes/user"));
app.use("/task", require("./routes/task"));
// PORT
const PORT = process.env.PORT || 5000;
app.listen(PORT, console.log(`Server started on port ${PORT}`));
User.js file -
const express = require("express");
const bodyParser = require("body-parser");
const router = express.Router();
const bcrypt = require("bcryptjs");
const passport = require("passport");
const User = require("../models/User");
const Task = require("../models/Task");
var LocalStrategy = require('passport-local');
// var bcrypt = require('bcryptjs');
var strategy = new LocalStrategy(function verify(email, password, done) {
try{
console.log(email);
User.findOne({email: email}, function (err, user) {
console.log(email);
if (err)
console.log(err);
if (!user) {
console.log("doen exist")
return done(null, false);
}
bcrypt.compare(password, user.password, function (err, isMatch) {
if (err)
console.log(err);
if (isMatch) {
return done(null, user);
} else {
console.log("galat password");
return done(null, false);
}
});
});
}catch(err){
console.log(err);
}
});
passport.use('epass',strategy);
passport.serializeUser((user, done) => {
done(null, user);
});
passport.deserializeUser((user, done) => {
done(null, user);
});
// User login
router.get("/login", (req, res) => {
res.render("user-login");
});
router.post("/login", (req,res) => {
try{
passport.authenticate('epass', { failureRedirect: '/user/login' }),
function(req, res,next) {
res.redirect('/user');
}
}catch(err){
console.log(err);
}
});
router.get("/", (req, res) => {
res.render("user")
})
module.exports = router;
I have searched everywhere and tried all the available possible solutions but nothing is solving this.
passport.authenticate() should be used as a middleware, not as a regular function:
router.post("/login",
passport.authenticate('epass', { failureRedirect: '/user/login' }),
function(req, res,next) {
res.redirect('/user');
}
);
The way you were using it causes the request to POST /user/login to never finish, because it's not sending back any response.
EDIT: also, make sure that you either use the default field names of username and password for logging in, or add the relevant options to the constructor of LocalStrategy to tell it which fields it should be expecting.
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);
This code is same to the tutorial which I am following for passport configuration. It does not got error but I am facing this:
This is my passport config file in which I have config my passport-local. I had use bcrypt package to secure password. This is not the main file.
const LocalStrategy = require('passport-local').Strategy;
const User = require("../model/user");
const bcrypt = require("bcrypt");
function init(passport){
passport.use(new LocalStrategy({usernameField:'email'}),async(email,password,done)=>{
// check if email exist
const user =await User.findOne({email:email});
if(!user){
return done(null , false , {message : "user doesnot exist"});
}
bcrypt.compare(password, user.password).then(match=>{
if(match){
return done(null , user ,{message : "logged in successfully"});
}
return done(null , false ,{message : "email or password incoorect"});
}).catch(err =>{
return done(null , false ,{message : "Something went wrong"});
})
})
passport.serializeUser((user , done)=>{
done(null , user._id)
})
passport.deserializeUser((id ,done)=>{
user.findById(id,(err,user)=>{
done(err,user);
})
})
}
module.exports = init;
This is my main server file
require("dotenv").config();
const express = require("express");
const path = require("path");
const expressLayout= require("express-ejs-layouts");
const app = express();
const PORT=process.env.PORT || 3000;
const url = process.env.CONNECTION;
const session = require("express-session");
const flash = require("express-flash");
const passport = require("passport");
// defining public and view path
const publicPath = path.join(__dirname,"./public");
const viewPath = path.join(__dirname,"/resources/views");
//setting database
const mongoose = require("mongoose");
mongoose.connect(url, {
useNewUrlParser: true ,
useUnifiedTopology: true,
useCreateIndex:true,
useFindAndModify:true,
useUnifiedTopology:true
})
const connection = mongoose.connection;
connection.once('open',()=>{
console.log("Database COnnected Successfully");
}).catch(err =>{
console.log("Connection failed");
})
// setting session and cookie
app.use(session({
secret:process.env.secret,
resave: false,
saveUninitialized: true,
cookie: {
maxAge:1000*60*60*24 // 24 hours
}
}));
// passport setting
const passportInit = require("./app/config/passport");
passportInit(passport);
app.use(passport.session());
// Global Middle ware
app.use(express.static(publicPath));
app.use(express.json());
app.use(express.urlencoded({extended:false}))
app.use(flash());
app.use(passport.initialize());
app.use((req,res,next)=>{
res.locals.session = req.session;
next();
})
//setting template engine
app.set("views",viewPath);
app.set("view engine" , "ejs");
app.use(expressLayout);
require('./route/web')(app);
app.listen(PORT , ()=>{
console.log(`Listening to Port ${PORT}`);
})
My server file
After searching through a plethora of answers to the same problem, none of the answers work for me. So I am hoping that I can get some help. In Routes/profile.js I make a get request to localhost:8081/profile which gives me the error. I am using Express and mongodb.
server.js
Note:
authRoutes and profileRoutes are used as middleware for the routes
const express = require("express");
const app = express();
const authRoutes = require("./routes/authorize");
const profileRoutes = require("./routes/profile");
require("dotenv/config");
const PORT = process.env.PORT || 8081;
const cors = require("cors");
const morgan = require("morgan");
const bodyParser = require("body-parser");
const mongoose = require("mongoose");
const cookieSession = require("cookie-session");
const passport = require("passport");
const keys = require("./config/key.js");
const passportSetup = require("./config/passport.js");
app.use("/auth", authRoutes);
app.use("/profile", profileRoutes);
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
//Initialize passport
app.use(passport.initialize());
app.use(passport.session());
app.use(
cookieSession({
maxAge: 24 * 60 * 60 * 1000,
keys: [keys.session.cookieKey]
})
);
app.use(cors());
app.use(morgan("combined"));
mongoose.connect(
process.env.DB_CONNECTION,
{
useNewUrlParser: true,
useUnifiedTopology: true
},
() => console.log("mongo atlas")
);
app.listen(PORT, () => {
console.log(`Server is on port ${PORT}`);
});
passport.js
const passport = require("passport");
const GoogleStratedy = require("passport-google-oauth20");
const keys = require("./key.js");
const User = require("../models/userModel");
passport.serializeUser((user, done) => {
done(null, user.id);
});
passport.deserializeUser((id, done) => {
User.findById(id).then(user => {
done(null, user);
});
});
passport.use(
new GoogleStratedy(
{
//options for the google strategy
callbackURL: "/auth/google/redirect",
clientID: keys.google.clientID,
clientSecret: keys.google.clientSecret
},
(accessToken, refreshToken, profile, done) => {
//passport callback function
console.log("passport callback fired");
//Check if user already exist in Db
User.findOne({ googleId: profile.id }).then(currentUser => {
if (currentUser) {
//already have user
console.log(`user is: ${currentUser} ALREADY REGISTERED`);
done(null, currentUser);
} else {
//create new user
new User({
username: profile.displayName,
googleId: profile.id
})
.save()
.then(newUser => {
console.log(`new user created ${newUser}`);
done(null, newUser);
});
}
});
}
)
);
Routes/authorize.js
const express = require("express");
const router = express.Router();
const passport = require("passport");
//auth login
router.get("/login", (req, res) => {
res.send({
message: `Hello ${req.body.email}! Your user was registered`
});
});
//auth logout
router.get("/logout", (req, res) => {
res.send("it works");
});
//auth with google
router.get(
"/google",
passport.authenticate("google", {
scope: ["profile"]
})
);
router.get("/google/redirect", passport.authenticate("google"), (req, res) => {
res.redirect("/profile");
});
module.exports = router;
Routes/profile.js This is for redirect api
const router = require("express").Router();
const passport = require("passport");
router.get("/", (req, res) => {
console.log(req.user.username);
});
module.exports = router;
userModel.js
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const userSchema = new Schema({
username: String,
googleId: String
});
const User = mongoose.model("user", userSchema);
module.exports = User;
You need to register the session middleware (in your case that is cookieSession), which populates the req.session, before you register the passport middlewares. So, you have to change the order of your code to this:
//Initialize passport
app.use(
cookieSession({
maxAge: 24 * 60 * 60 * 1000,
keys: [keys.session.cookieKey]
})
);
app.use(passport.initialize());
app.use(passport.session());
I have implemented passport local strategy and passport google strategy to implement login functionality,my google strategy is working fine but when am login with local strategy its calling the serializable and deserializable method of passport's google strategy.
I have made separate instances for both (i.e both for local and google strategy) , still the serializableUser and deserializableUer method of only google strategy is getting called for both the strategies as the result req.user remains undefined in case of local strategy since the user is not setting in the session
i have visited a lot of stackoverflow questions but i didn't get any solution, finally i am wondering that is it even possible to use passport local strategy and passport google stategy to implement login functionality in the same project?
My Question is similar to this ( the serialize and deserialze methods are not getting called separately )
app.js
here googleS and localS are instances of two different strategies i.e, local and google sttrategies.
const express = require("express");
const path = require("path");
const exphbs = require("express-handlebars");
const bodyParser = require("body-parser");
const mongoose = require("mongoose");
const passport = require("passport");
const Cpassport=require('./config/Cpassport');
const cookieParser = require("cookie-parser");
const session = require("express-session");
const methodOverride = require("method-override");
const flash = require("express-flash");
const mailer = require("express-mailer");
//Handlebars helpers
const {
truncate,
stripTags,
formatDate,
select,
editIcon
} = require("./helpers/hbs");
var googleS = new passport.Passport();
var localS = new passport.Passport();
const app = express();
//set static folder
app.use(express.static(path.join(__dirname, "public")));
//load keys
const keys = require("./config/keys");
//Map global Promises
mongoose.Promise = global.Promise;
//Mongoose Connection
mongoose
.connect(keys.mongoURI)
.then(() => console.log("MongoDB Connected"))
.catch(err => console.log(err));
//load user model
require("./models/User");
//story model
require("./models/Story");
//feedback model
require("./models/Feedback");
//local strategy model
require("./models/CUser");
//session
app.use(cookieParser());
app.use(
session({
secret: "secret",
resave: true,
saveUninitialized: true
})
);
//passport config
require("./config/passport")(googleS);
require("./config/Cpassport")(localS);
//Passport Middleware
app.use(passport.initialize());
app.use(passport.session());
//flash middleware
app.use(flash());
//set global variables
app.use((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;
// res.locals.userr = req.userr || null;
console.log("this is requested user");
console.log(res.locals.user);
// console.log(res.locals.userr);
next();
});
// Load Routes
const auth = require("./routes/auth");
const index = require("./routes/index");
const stories = require("./routes/stories");
const mailOptions = require("./helper/mailer");
//body-parser middleware
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
//method overriding body parser
app.use(methodOverride("_method"));
//mailer
mailer.extend(app, {
from: "Belle Solutions",
host: "smtp.gmail.com",
secureConnection: true,
port: 465,
transportMethod: "SMTP",
auth: {
user: keys.email,
pass: keys.pass
}
});
//handlebars
app.engine(
"handlebars",
exphbs({
helpers: {
truncate: truncate,
stripTags: stripTags,
formatDate: formatDate,
select: select,
editIcon: editIcon
},
defaultLayout: "main"
})
);
// app.get('*' , function(req ,res ,next){
// res.locals.user=req.user || null;
// console.log(req.user);
// console.log('printing user');
// console.log(res.locals.user);
// next();
// })
app.set("view engine", "handlebars");
//use routes
app.use("/auth", auth);
app.use("/", index);
app.use("/stories", stories);
const port = process.env.PORT || 5000;
app.listen(port, () => {
console.log(`Server started on port ${port}`);
});
google Strategy file
const GoogleStrategy=require('passport-google-oauth20').Strategy;
const mongoose = require('mongoose');
const keys = require('./keys');
const passport = require('passport');
const User =mongoose.model('users');
module.exports=function(googleS){
googleS.use(
new GoogleStrategy({
clientID:keys.googleClientID,
clientSecret:keys.googleClientSecret,
callbackURL:'/auth/google/callback',
proxy:true
},(accessToken,refreshToken,profile,done)=>{
// console.log("This is access token......................................................");
// console.log(accessToken);
// console.log("This is profile...............................");
// console.log(profile);
const image = profile.photos[0].value.substring(0, profile.photos[0].value.indexOf('?'));
const newUser = {
googleID:profile.id,
firstName:profile.name.givenName,
lastName:profile.name.familyName,
email:profile.emails[0].value,
image:image
}
//check for existing model
User.findOne({
googleID:profile.id
}).then( user=>{
if(user){
done(null,user);
}else{
new User(newUser)
.save()
.then(user => done(null,user));
}
} )
})
)
passport.serializeUser( (user,done)=>{
console.log("in serialize of oauth.............")
done(null,user.id);
} );
passport.deserializeUser( (id,done)=>{
console.log("in deserialize of oauth.....................")
User.findById(id).then(user =>done(null,user));
} );
}
local Strategy file
const LocalStrategy=require('passport-local').Strategy;
const mongoose = require('mongoose');
const bcrypt=require('bcryptjs');
const passport=require('passport');
//const User =require('../models/CUser')
//Load user Model
const Strategy =require('../app');
var local=Strategy.localS;
require('../models/CUser');
const CUser = mongoose.model('CUsers');
module.exports=function(localC){
console.log(localC)
//local Strategy
console.log("inside passport...........");
console.log(local);
localC.use(
new LocalStrategy({
usernameField:'email'},(email,password,done)=>{
//match usernaame
console.log(email);
console.log(password)
let query ={email:email};
CUser.findOne(query , function(err,user){
console.log("Before error")
if(err) throw err;
if(!user){
return done(null,false,{message:'No user Found'});
}
bcrypt.compare(password,user.password,function(err,isMatch){
console.log("In compare function......")
if(err) throw err;
if(isMatch){
console.log("here......")
console.log(user)
return done(null,user);
}else{
return done(null,false,{message:'Wrong password'})
}
})
})
}))
passport.serializeUser(function(user, done) {
console.log("in serialize of local strategy............")
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
console.log("in deserialize og local strategy........")
CUser.findById(id, function(err, user) {
done(err, user);
});
});
}
The problem here is that when i am doing login by local strategy its still calling the serialize and deserialize methods of google strategy and as a result unable to set the user of local strategy into session so its returning undefined on req.user.
why its happening , am i wrong anywhere? Please suggest ,I am in the need of an immediate help, i am stuck with this problem from the last three days.
Any help is greatly appreciated and i will be very thankful for the person.