Node authentication, when I submit credentials nothing happens - node.js

I've built a practice authentication app and it originally worked right when I built it. Now when I try to login or register nothing happens. I can see in my database that it registers a new user but it doesn't move me onto the secret page. When I login with correct credentials and submit it just sits on the login page (but removes the credentials from the form). I've tried to use failureFlash in the login post route but it just errors that it's not a function. I'm not sure what else to do to troubleshoot.
user model:
const mongoose = require("mongoose"),
passportLocalMongoose = require("passport-local-mongoose");
var UserSchema = new mongoose.Schema({
username: String,
password: String
});
UserSchema.plugin(passportLocalMongoose);
module.exports = mongoose.model("User", UserSchema);
app.js:
const express = require("express"),
app = express(),
mongoose = require("mongoose"),
bodyParser = require("body-parser"),
passport = require("passport"),
LocalStrategy = require("passport-local"),
passportLocalMongoose = require("passport-local-mongoose"),
expressSession = require("express-session"),
User = require("./models/user"),
mdbUrl = "This is the url and credentials to my database";
app.set("view engine", "ejs");
app.use(bodyParser.urlencoded({extended:true}));
app.use(passport.initialize());
app.use(passport.session());
passport.use(new LocalStrategy(User.authenticate()));
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
app.use(expressSession({
secret: "some string",
resave: false,
saveUninitialized: false
}));
mongoose.connect(mdbUrl,{useNewUrlParser: true, useCreateIndex: true, useUnifiedTopology: true})
.then(()=> {
console.log("mongooooooose");
})
.catch(err=> {
console.log(err);
})
app.get("/", (req, res)=>{
res.render("home");
});
app.get("/secret", isLoggedIn, (req,res)=>{
res.render("secret");
});
app.get("/register", (req,res)=>{
res.render("register");
});
app.post("/register", (req, res)=>{
req.body.username;
req.body.password;
User.register(new User({username: req.body.username}), req.body.password, (err, user)=>{
if(err){
console.log(err);
res.redirect("register");
}
passport.authenticate("local")(req, res, ()=>{
res.redirect("/secret");
});
});
});
app.get("/login", (req, res)=>{
res.render("login");
});
app.post("/login", passport.authenticate("local",{
successRedirect: "/secret",
failureRedirect: "/login",
}), (req,res)=>{});
app.get("/logout", (req, res)=>{
req.logout();
res.redirect("/");
});
function isLoggedIn(req, res, next){
if(req.isAuthenticated()){
return next();
}
res.redirect("/login");
}
app.listen(3000, ()=>{
console.log("auth started");
});
login.ejs:
<h1>Login</h1>
<form action="/login" method="POST">
<input type="text" placeholder="username" name="username">
<input type="password" placeholder="password" name="password">
<button>Submit</button>
</form>
secret.ejs:
<h1>
Secret Page
</h1>
<p>
this is a test page
</p>
<li>Sign Up!</li>
<li>Sign in</li>
<li>log out</li>
register.ejs:
<h1>register</h1>
<form action="/register" method="POST">
<input type="text" placeholder="username" name="username">
<input type="password" placeholder="password" name="password">
<button>Submit</button>
</form>
<li>Sign Up!</li>
<li>Sign in</li><li>log out</li>

Related

How can I enter three field in my database, with passport, passport-local-mongoose, and express-session

I am stuck with this code. I want to insert three fields in my database using User.register(), but my passport.authenticate() is giving me bad request and redirect me to register page again and again, but my data got inserted into the database.
Here is my app.js:
require('dotenv').config()
const express = require("express");
const bodyParser = require("body-parser");
const ejs = require("ejs");
const mongoose = require("mongoose");
const _ = require("lodash");
const session = require("express-session");
const passport = require("passport");
const passportLocalMongoose = require("passport-local-mongoose");
const app = express();
app.set("view engine", 'ejs');
app.use(express.static("public"));
app.use(bodyParser.urlencoded({ extended: true }));
app.use(session({
secret: process.env.SECRET,
resave: false,
saveUninitialized: false,
}));
app.use(passport.initialize());
app.use(passport.session());
mongoose.set("strictQuery", true);
mongoose.connect("mongodb://127.0.0.1:27017/My1stProjectDb", (err) => {
if (err) {
console.log(err);
} else {
console.log("Success !!!");
}
});
const userSchema = new mongoose.Schema({
name: String,
email: String,
Password: String
});
userSchema.plugin(passportLocalMongoose);
const User = new mongoose.model("User", userSchema);
passport.use(User.createStrategy());
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
app.get("/", function (req, res) {
res.render("home");
});
app.get("/sell", function (req, res) {
res.render("sell");
});
app.get("/categories", function (req, res) {
res.render("categories");
});
app.get("/register", function (req, res) {
res.render("register");
});
app.get("/login", function (req, res) {
res.render("register")
})
app.get("/secrets", function (req, res) {
if (req.isAuthenticated()) {
res.render("secrets")
} else {
res.render("register")
}
});
app.get("/logout", function (req, res) {
req.logout((err) => {
if (err) {
console.log(err);
} else {
res.redirect("/");
}
});
});
app.post("/register", function (req, res) {
const registerUser = new User({ email: req.body.useremail, username: req.body.username });
User.register(registerUser, req.body.userpassword, function (err, user) {
if (err) {
console.log(err);
} else{
passport.authenticate("local",{ failureRedirect: '/register' })(req, res, function () {
res.redirect("/secrets");
});
}
});
});
app.listen(3000, function () {
console.log("Server started at port 3000");
});
Here is registration page
<form action="/register" method="POST">
<div class="form sign-up">
<h2>Create your Account</h2>
<label>
<span>Name</span>
<input type="text" name="username" />
</label>
<label>
<span>Email</span>
<input type="email" name="useremail" />
</label>
<label>
<span>Password</span>
<input type="password" name="userpassword"/>
</label>
<button type="submit" class="submit">Sign Up</button>
</div>
</form>
I want to make my code compatible for three fields entry in userSchema into database and successfully redirect it to secrets page with authentication.

Struggling to make a Login Authentication for js.node + mongoDB code

Currently attempting to make a register/ login page for a website.
Made a register where it saves username and password to mongoDB.
However i am stuck on the login authentication part, if someone coudld help me out that would be nice.
I attempted to add api passport but I do not have enough knowledge on it to implement a authentication. I want the login screen to verify if the inputed username and password are valid before redirecting the user to the homepage.
This is my server.js code
const express = require('express');
const app = express();
const router = express.Router();
const mongoose = require('mongoose')
const bodyParser = require('body-parser');
const passport = require("passport");
const passportLocalMongoose = require("passport-local-mongoose");
const LocalStrategy = require("passport-local");
var User = require("./models/user");
app.use(express.urlencoded({ extended: false }))
app.use(express.json());
//connect to db
mongoose.connect("mongodb+srv://group4:s0ftwar3#bankdata.tomj87l.mongodb.net/?retryWrites=true&w=majority", { useNewUrlParser: true, useUnifiedTopology: true }, connected());
function connected() {
console.log('Connected to DB');
}
//password
app.use(require("express-session")({
secret: "123",
resave: false,
saveUninitialized: false
}));
//initialize passport
app.use(passport.initialize());
app.use(passport.session());
//routes
//home page
app.get("/", function (req, res) {
res.sendFile(__dirname + "/views/home.html")
});
//login form
app.get('/login', function (req, res) {
res.sendFile(__dirname + "/views/login.html")
})
//
//Handling user login
app.post("/login", passport.authenticate("local", {
successRedirect: "/secret",
failureRedirect: "/login"
}), function (req, res) {
});
//register form
app.get("/register", function (req, res) {
res.sendFile(__dirname + "/views/register.html");
});
app.post("/register", function (req, res) {
const user = new User({
username: req.body.username,
password : req.body.password
});
user.save((err, user) => {
if (err) {
res.status(500)
.send({
message: err
});
return res.sendFile(__dirname + "/views/register.html");;
}
passport.authenticate("local")(
req, res, function () {
res.sendFile(__dirname + "/views/homepage.html");
});
});
});
app.listen(1337)
my user.js
const mongoose = require('mongoose');
const Joi = require('joi');
const userSchema = new mongoose.Schema({
username: {
type: String,
unique: true,
required: true
},
password: {
type: String,
max: 1024,
min: 6,
required: true
}
});
function validateUser(user) {
const schema = {
username: Joi.string().min(5).max(50).required(),
email: Joi.string().min(5).max(255).required().email(),
password: Joi.string().min(5).max(255).required()
};
return Joi.validate(user, schema);
}
module.exports = mongoose.model('User', userSchema);
exports.validate = validateUser;
and my login.html
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type = "text/css" href="login.css" />
<title>Global Teller Machine 2.0</title>
<meta charset="utf-8" />
</head>
<body>
<div id="window">
<a href="setting.html">
<img id="setting_icon" src="../assets/setting_icon.png" alt="Setting" />
</a>
<div>
<h1 class="header">
<b class="header">Welcome to GTM 2.0</b>
</h1>
<h3 class="header">Please sign in to begin</h3>
</div>
<form action="/login" method="post">
<div>
<label>Username</label>
</br>
<input type="text" placeholder="Enter Username" name="username" id="username" required>
</div>
</br>
<div>
<label>Password</label>
</br>
<input type="password" placeholder="Enter Password" name="password" id="password" required>
</div>
</br>
<input id="data" type="submit" value="Login" />
</div>
</form>
</div>
</body>
</html>

NodeJS csrf protection gives ForbiddenError invalid csrf token only on one POST request form

I have been unsuccessfully trying to find a solution on Google for the past several hours for the following issue:
I have csurf set up and working well. It works for POST requests related to signing up/in users. I am trying to create a form in the user profile, that updates the user's data, but when I hit submit, I get ForbiddenError: invalid csrf token.
On further testing, the csrt token is created on the profile page, but for some reason, it is invalid.
(I have only recently picked up programming, I'm willing to provide additional information if I have missed something.)
Tools used:
Node.js v10.16.3
Express v4.17.1
ejs v2.7.1
csurf v1.10.0
Express session v1.16.2
Passport v^0.4.0
cookie-parser 1.4.4
body-parser v1.19.0
My app.js
let express = require("express"),
app = express(),
bodyParser = require("body-parser"),
cookieParser = require('cookie-parser'),
session = require("express-session"),
mongoose = require("mongoose"),
passport = require("passport"),
flash = require('connect-flash'),
validator = require('express-validator'),
LocalStrategy = require("passport-local"),
csrf = require('csurf'),
csrfProtection = csrf({ cookie: true }),
MongoStore = require('connect-mongo')(session);
let indexRoutes = require('./routes/index');
let userRoutes = require('./routes/user');
let User = require("./models/user");
// APP CONFIGURATION
mongoose.connect("mongodb://localhost:27017/azax", { useNewUrlParser: true, useUnifiedTopology: true, }).then(() => {
console.log("Connected to MongoDB");
}).catch((error) => {
console.log("Something is wrong...");
});
require('./config/passport');
// View engine setup
app.set("view engine", "ejs");
app.use(express.static(__dirname + "/public"));
// Initial setup
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(validator());
// Session setup
app.use(cookieParser());
app.use(session({
secret: 'somesecretforbytox',
resave: false,
saveUninitialized: false
}));
app.use(flash());
// Initialize passport
app.use(passport.initialize());
app.use(passport.session());
app.use(csrf());
// CSRF
app.use(function (req, res, next) {
var token = req.csrfToken();
res.cookie('XSRF-TOKEN', token);
res.locals.csrfToken = token;
next();
});
app.use(function (req, res, next) {
res.locals.currentUser = req.user;
res.locals.session = req.session;
next();
});
// ======================
// Connect to route files
// ======================
app.use('/user', userRoutes);
app.use(indexRoutes);
app.listen(3033, function () {
console.log("Listening at port 3033...");
});
My passport.js:
let passport = require('passport');
let User = require('../models/user');
let LocalStrategy = require('passport-local').Strategy;
passport.serializeUser(function (user, done) {
done(null, user.id);
});
passport.deserializeUser(function (id, done) {
User.findById(id, function (err, user) {
done(err, user);
});
});
passport.use('local-signup', new LocalStrategy({
usernameField: 'email',
passwordField: 'password',
passReqToCallback: true
}, function (req, email, password, done) {
req.checkBody('username', 'Invalid username').notEmpty();
req.checkBody('email', 'Invalid email').notEmpty().isEmail();
req.checkBody('password', 'Invalid password').notEmpty().isLength({ min: 4 });
let errors = req.validationErrors();
if (errors) {
let messages = [];
errors.forEach(function (error) {
messages.push(error.msg);
});
return done(null, false, req.flash('error', messages));
}
User.findOne({ 'email': email }, function (err, user) {
if (err) {
return done(err);
}
if (user) {
return done(null, false, { message: 'Вече има акаунт с този имейл.' })
}
let username = req.body.username;
let newUser = new User();
newUser.username = username;
newUser.email = email;
newUser.password = newUser.encryptPassword(password);
newUser.country = 'България';
newUser.save(function (err, result) {
if (err) {
return done(err);
}
return done(null, newUser);
});
});
}));
passport.use('local-signin', new LocalStrategy({
usernameField: 'email',
passwordField: 'password',
passReqToCallback: true
}, function (req, email, password, done) {
// req.checkBody('username', 'Invalid username').notEmpty();
req.checkBody('email', 'Invalid email').notEmpty();
req.checkBody('password', 'Invalid password').notEmpty();
let errors = req.validationErrors();
if (errors) {
let messages = [];
errors.forEach(function (error) {
messages.push(error.msg);
});
return done(null, false, req.flash('error', messages));
}
User.findOne({ 'email': email }, function (err, user) {
if (err) {
return done(err);
}
if (!user) {
return done(null, false, { message: 'Акаунтът не е намерен.' });
}
if (!user.validPassword(password)) {
return done(null, false, { message: 'Грешна парола.' });
}
return done(null, user);
});
}));
HTML...:
<form action="/user/profile" method="POST" class="form-validate form-horizontal" enctype="multipart/form-data">
<fieldset>
<legend>Edit address</legend>
<!-- email -->
<div class="control-group">
<div class="control-label">
<label id="jform_email1-lbl" for="jform_email" class="hasPopover required" title="" data-content="Enter new email address." data-original-title="Email Address">
Email<span class="star"> *</span></label>
</div>
<div class="controls">
<input type="email" name="email" class="validate-email required" id="jform_email" value="<%= (typeof currentUser.email != 'undefined' ? currentUser.email : '') %>" size="30" autocomplete="email" required aria-required="true">
</div>
</div>
<!-- name -->
<div class="control-group">
<div class="control-label">
<label id="jform_fname-lbl" for="jform_fname" class="hasPopover required" title="" data-content="Enter new name." data-original-title="Name">
Name<span class="star"> *</span></label>
</div>
<div class="controls">
<input type="text" name="firstName" id="jform_fname" value="<%= (typeof currentUser.firstName != 'undefined' ? currentUser.firstName : '') %>" class="required" size="30" required aria-required="true">
</div>
</div>
</fieldset>
<div class="form-actions">
<input type="hidden" name="_csrf" value="<%= csrfToken %>">
<button type="submit" class="btn btn-primary validate">
<span>Save</span>
</button>
<a class="btn" href="/" title="Cancel">Cancel</a>
</div>
</form>
user.js:
let express = require('express'),
router = express.Router(),
csrf = require('csurf'),
csrfProtection = csrf(),
passport = require('passport');
router.use(csrfProtection);
let User = require("../models/user");
// user profile
router.get("/profile", isLoggedIn, csrfProtection, function (req, res) {
res.render("user/profile", { csrfToken: req.csrfToken(), currentUser: req.user });
});
router.post('/profile', (req, res) => {
updateRecord(req, res);
res.redirect('/profile');
});
// update user data
function updateRecord(req, res) {
User.findOne({ _id: req.user.id }, (err, doc) => {
doc.name = req.body.name;
doc.save(function (err, doc) {
});
});
}
router.get("/profile/edit", isLoggedIn, csrfProtection, function (req, res) {
res.render("user/edit", { csrfToken: req.csrfToken(), currentUser: req.user });
});
// sign up form works with csrf
// signup form
router.get("/signup", csrfProtection, function (req, res) {
let messages = req.flash('error');
res.render("user/signup", { csrfToken: req.csrfToken(), messages: messages, hasErrors: messages.length > 0 });
});
// ... more routes
module.exports = router;
// middleware
function isLoggedIn(req, res, next) {
if (req.isAuthenticated()) {
return next();
}
res.redirect('/user/login');
}
What worked for me was adding the below hidden field to every form:
<input type="hidden" name="_csrf" value="<%= csrfToken %>">
and sending the token to every get request to the template page displaying the form.
{csrfToken: req.csrfToken()}
like
router.get('/user/login',function(req,res){
res.render('pages/login', {csrfToken: req.csrfToken()});
})
this fixed the error in whole app.

passport authentication always fails

I'm trying to setup a simple login page using express framework , mongodb and passport for authentication.
My authentication always goes to the failstate. Where am I wrong ?
my sever.js:
var express = require("express");
var app = express();
var bodyParser = require('body-parser');
var cors = require('cors');
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
//var router = express.Router();
var path = require('path');
var mongoose = require('mongoose');
var User = require('./model');
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(cors());
app.use(passport.initialize());
app.use(passport.session());
passport.use(new LocalStrategy(
function(username, password, done) {
users.findOne({
username : 'username'
}, function(err, user) {
if (err) {
return done(err);
}
if (!user) {
return done(null, false);
}
if (user.password != password) {
return done(null, false);
}
return done(null, user);
});
}
));
app.post('/login',
passport.authenticate('local', { failureRedirect: '/error' }),
function(req, res) {
res.redirect('/success?username='+req.user.username);
});
//app.use("/",router);
//app.use(bodyParser());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(cors());
app.get('/success', (req, res) => res.send("Welcome "+req.query.username+"!!"));
app.get('/error', (req, res) => res.send("error logging in"));//ALWAYS LAND HERE
passport.serializeUser(function(user, cb) {
cb(null, user.id);
});
/*passport.deserializeUser(function(id, cb) {
User.findById(id, function(err, user) {
cb(err, user);
});
});
*/
//app engine
app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, 'views'));
mongoose.connect('mongodb://localhost:27017/UserSchema');
/*
router.use(function (req,res,next) {
console.log("/" + req.method);
next();
});*/
app.get("/",function(req,res){
res.render('index');
});
app.post("/user",function (req, res) {
var u = new User();
//console.log(req.body);
u.email = req.body.email;
u.name = req.body.name;
u.password = req.body.password;
//p.photo = req.body.photo;
u.save(function (err) {
if (err) {
res.send(err);
}
res.render('login');
});
});
app.get("/login",function (req, res) {
res.render('login');
});
app.get("/all",function (req, res) {
User.find(function (err, products) {
if (err) {
res.send(err);
}
res.send(products);
});
});
/*
router.get("/about",function(req,res){
res.sendFile(path + "about.html");
});
router.get("/contact",function(req,res){
res.sendFile(path + "contact.html");
});
app.use("*",function(req,res){
res.sendFile(path + "404.html");
});
*/
app.listen(3000,function(){
console.log("Live at Port 3000");
});
sorry for the junk comments
here is my mongoose schema (model.js):
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var UserSchema = new Schema({
email: String,
name: String,
password: String,
//photo: String,
});
module.exports = mongoose.model('User', UserSchema);
my login.ejs :
<!DOCTYPE html>
<html>
<<title>Login</title>
<body>
<form action="/login", method="post">
Email:<br>
<input type="text" name="username">
<br>
Password:
<br>
<input type="text" name="password">
<br><br>
<input type="submit" value="Submit">
</form>
</body>
</html>
and my registration page which is able to register and insert in db:
<!DOCTYPE html>
<html>
<body>
<form action="/user", method="post">
Email:<br>
<input type="text" name="email">
<br>
Name:<br>
<input type="text" name="name" >
<br>
Password:
<br>
<input type="text" name="password">
<br><br>
<input type="submit" value="Submit">
</form>
<a href="/login"/><input type="submit" value="Login">
</body>
</html>
You imported your MongoDB User model as:
var User = require('./model');
However, you are calling the .findOne() method on "users"
passport.use(new LocalStrategy(
function(username, password, done) {
users.findOne({
username : 'username'
}, function(err, user) {
Should it not be User.findOne()
If that doesn't resolve the issue then you should elaborate more on what you mean by "my application always go to the failstate".

Nodejs - Registering/Loggin a user in error = "Cannot read property '_id' of undefined"

I'm creating authentication in NodeJs. When I try to log in a user/register a user I get the error.
Cannot read property '_id' of undefined
The method findById is only used in one get route. This is the secret get route, so only a user who is of a particular user type can access this page
I'm using passportjs also. It sends data to the databases.
This is my registration and login code
var express = require("express"),
app = express(),
bodyParser = require("body-parser"),
mongoose = require("mongoose"),
passport = require("passport"),
User = require("./models/user"),
localStrategy = require("passport-local"),
passportLocalMongoose = require("passport-local-mongoose"),
User = require("./models/user");
mongoose.Promise = global.Promise;
mongoose.connect("mongodb://localhost/ww", {useMongoClient: true});
app.use(bodyParser.urlencoded({extended:true}));
app.set("view engine", "ejs");
/*=========================
Setting up PassportJS
==========================*/
app.use(passport.initialize());
app.use(passport.session());
app.use(require("express-session")({
secret: "King Nidge",
resave: false,
saveUninitialized: false
}));
passport.use(new localStrategy(User.authenticate()));
passport.serializeUser(User.serializeUser()); //Put it back in session
passport.deserializeUser(User.deserializeUser()); //Reading session, taking in data and decoding.
/*=========================
Routes
==========================*/
app.get("/", function(req, res){
res.render("landing");
});
app.get("/secret", function(req, res){
User.findById(req.user._id, function(err, user){
if(err){
console.log(err);
}
else {
if(user.role === "Landlord"){
res.render("secret");
}
else {
res.redirect("/");
}}
});
});
/*=========================
Authentication Routes
==========================*/
//Register
app.get("/register", function(req, res){
res.render("register");
});
app.post("/register", function(req, res){
User.register(new User({username: req.body.username, email: req.body.email, role: req.body.role}), req.body.password, function(err, user){
if(err){
console.log(err);
return res.render('register');
} else {
passport.authenticate("local")(req, res, function(){
res.redirect("/secret");
});
}
});
});
//Login
app.get("/login", function(req, res) {
res.render("login");
});
app.post("/login", passport.authenticate("local", {
successRedirect: "/secret",
failureRedirect: "/login"
}) ,function(req, res){
});
This is my schema for the users.
var mongoose = require("mongoose");
var passportLocalMongoose = require("passport-local-mongoose");
var UserSchema = new mongoose.Schema({
username: String,
password: String,
email: String,
role: String
});
UserSchema.plugin(passportLocalMongoose);
module.exports = mongoose.model("User", UserSchema);
This is my registration form
<h1>Sign Up Form</h1>
<form action="/register" method="POST">
<input type="text" name="username" placeholder="username">
<input type="password" name="password" placeholder="password">
<input type="email" name="email" placeholder="email">
<input type="radio" name="role" value="Administrator">
<input type="radio" name="role" value="User">
<button>Submit</button>
</form>
Any tips to overcome this error?
Please check this.
Express-session should be declared before passport initialization and the declaration of passport.session usage.
app.use(require("express-session")({
secret: "King Nidge",
resave: false,
saveUninitialized: false
}));
app.use(passport.initialize());
app.use(passport.session());

Resources