I'm trying to figure out where the error lies in my authentication code that is creating an endless loop every time I try to login. I think it is within the local strategy passport.use('local', new LocalStrategy section of my code because my console.log(req.body.email); passes back the correct value that was inputted in the field and a query is logged that uses the findOne value, but none of the other console.log are being triggered (one for a email error, another for password error and one for success).
Example: trying to login with test#test.com email address
test#test.com
Executing (default): SELECT `user_id`, `first_name` AS `firstName`, `last_name` AS `lastName`, `email`, `password`, `createdAt`, `updatedAt` FROM `user` AS `user` LIMIT 1;
user.js:
module.exports = function(sequelize, DataTypes) {
var User = sequelize.define('user', {
user_id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true
},
firstName: {
type: DataTypes.STRING,
field: 'first_name'
},
lastName: {
type: DataTypes.STRING,
field: 'last_name'
},
email: DataTypes.STRING,
password: DataTypes.STRING,
}, {
freezeTableName: true
});
return User;
}
db-index.js:
var Sequelize = require('sequelize');
var path = require('path');
var config = require(path.resolve(__dirname, '..', '..','./config/config.js'));
var sequelize = new Sequelize(config.database, config.username, config.password, {
host:'localhost',
port:'3306',
dialect: 'mysql'
});
sequelize.authenticate().then(function(err) {
if (!!err) {
console.log('Unable to connect to the database:', err)
} else {
console.log('Connection has been established successfully.')
}
});
var db = {}
db.User = sequelize.import(__dirname + "/user");
db.sequelize = sequelize;
db.Sequelize = Sequelize;
sequelize.sync();
module.exports = db;
site-routes.js:
var express = require('express');
var siteRoutes = express.Router();
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var models = require('../models/db-index');
/*==== Passport Configuration ====*/
// Serialize sessions
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
model.User.find({where: {id: id}}).success(function(user){
done(null, user);
}).error(function(err){
done(err, null);
});
});
passport.use('local', new LocalStrategy({
passReqToCallback : true,
usernameField: 'email'
},
function(req, email, password, done) {
console.log(req.body.email);
//Find user by email
models.User.findOne({ email: req.body.email }, function(err, user) {
//If there is an error, return done
if (err) { return done(err); }
//If user does not exist, log error and redirect
if (!user) {
console.log('No email')
return done(null, false, req.flash('message', 'Email not found.'));
}
//If user exists, but wrong password
if (!user.validPassword(password)) {
console.log('Password fail');
return done(null, false, { message: 'Incorrect password.' });
}
//If all credentials match, return user
console.log('Attempting login');
return done(null, user);
console.log('Successful login');
});
}
));
/*==== Index ====*/
siteRoutes.get('/', function(req, res){
res.render('pages/index.hbs');
});
/*==== Login ====*/
siteRoutes.route('/login')
.get(function(req, res){
res.render('pages/login.hbs');
})
.post(passport.authenticate('local', {
successRedirect: '/',
failureRedirect: '/sign-up',
failureFlash: true
}));
siteRoutes.route('/sign-up')
.get(function(req, res){
res.render('pages/sign-up.hbs');
})
.post(function(req, res){
models.User.create({
firstName: req.body.firstName,
lastName: req.body.lastName,
email: req.body.email,
password: req.body.password
}).then(function() {
res.redirect('/');
}).catch(function(error){
res.send(error);
})
});
module.exports = siteRoutes;
login.hbs:
<!DOCTYPE html>
<head>
{{> head}}
</head>
<body>
{{> navigation}}
<div class="container">
<div class="col-md-6 col-md-offset-3">
<form action="/login" method="post">
<label for="login-username">Username</label>
<input type="text" class="form-control" id="login-username" name="email" placeholder="username or email">
<br />
<label for="login-password">Password</label>
<input type="password" class="form-control" id="login-password" name="password">
<div class="login-buttons">
<button type="submit">Login</button>
</div>
</form>
Don't have an account? Then register here!
<br />
Forgot your password?
</div>
</div>
</body>
You are passing a callback function as a second argument to models.User.findOne, but Sequelize functions don't take callbacks. Instead they return a promise. Your code in site-routes.js should look something like this:
passport.use('local', new LocalStrategy({
passReqToCallback: true,
usernameField: 'email'
},
function(req, email, password, done) {
console.log(req.body.email);
//Find user by email
models.User.findOne({
email: req.body.email
})
.then(function(user) {
// handle login here, user will be falsey if no user found with that email
})
.catch(function(err) {
// either findOne threw an exception or it returned a rejected promise
});
}
));
For a full-fledged example of local authentication using passport.js and Sequelize you can see my login-fiddle. Here is a perma-link to the passport local authentication strategy.
Related
I'm a new programmer :)
I'm trying to build an authentication system using passport.js.
Now, I want to determine the expiration of the cookies, depend on "Remember me" checkbox - For the example I chose: if “remember me” cookie expires after 2 minutes, otherwise cookie expires after 1 minute.
The problem is that it doesn't change the cookie's maxAge (it still 1 minute)
my code:
login.hbs
<body class="border border-2 border" style="margin-top: 15%; margin-right: 30%; margin-left: 30%">
<form action="/login" method="POST" class="form-signing container" style="max-width: 30rem">
<div class="text-center">
<!-- <img class="mb-4" src="public/images/wine4u_logo.jpeg" alt="" width="72" height="72"> -->
<h1 class="h3 mb-3 font-weight-normal">Login</h1>
<p>Please Enter your credentials in order to enter our store.</p>
</div>
<hr>
{{#if error}}
<div class="alert alert-danger">{{error}}</div>
{{/if}}
<div class="mb-3 text-left">
<label for="email" class="form-label"><b>Email</b></label>
<input type="email" placeholder="Enter Email" class="form-control" id="email" name="email" required>
</div>
<div class="mb-3">
<label for="password" class="form-label"><b>Password</b></label>
<input type="password" placeholder="Enter Password" class="form-control" id="password" name="password" required>
</div>
<div class="checkbox mb-3 text-center">
<label>
<input type="checkbox" class="form-label" name="rememberMe" value="remember-me"> Remember me
</label>
<!-- <label for="checkbox"><b>Remember Me?</b></label> -->
<!-- <input type="checkbox" name="rememberMe"> -->
</div>
<div class="text-center">
<button type="submit" class="btn btn-lg btn-primary btn-block">Login</button>
</div>
</form>
<hr>
<form action="/register" class="text-center">
<button type="" class="btn btn-lg btn-secondary btn-block">Sign up page</button>
</form>
<!-- Register -->
</body>
app.js:
if (process.env.NODE_ENV !== "production") {
require("dotenv").config();
}
const express = require("express");
const path = require("path");
const bodyParser = require("body-parser");
const exphbs = require("express-handlebars");
const bcrypt = require("bcrypt");
const passport = require("passport");
const flash = require("express-flash");
const session = require("express-session");
const initializePassport = require("./public/javascript/passport-config");
const methodOverride = require("method-override");
initializePassport(
passport,
(email) => users.find((user) => user.email === email),
(id) => users.find((user) => user.id === id)
);
const app = express();
let users = [];
let cookieLength = 60 * 1000;
// handleBars middleware
app.engine(".hbs", exphbs.engine({ defaultLayout: "main", extname: ".hbs" }));
app.set("view engine", ".hbs");
app.use(bodyParser.json());
app.use(express.urlencoded({ extended: false }));
app.use(flash());
app.use(
session({
secret: process.env.SESSION_SECRET,
resave: false,
saveUninitialized: false,
rolling: true,
cookie: { maxAge: cookieLength },
})
);
app.use(passport.initialize());
app.use(passport.session());
app.use(methodOverride("_method"));
app.get("/", checkAuthenticated, async (req, res) => {
res.render("index", { title: "Welcome to my site" });
});
app.get("/login", checkLoggedIn, async (req, res) => {
res.render("pages/login", {
title: "login page",
noHeader: true,
error: req.flash("error"),
csrf: "CSRF token goes here",
});
});
app.post(
"/login",
checkLoggedIn,
defineCookieLength,
passport.authenticate("local", {
successRedirect: "/",
failureRedirect: "/login",
failureFlash: true,
})
);
app.get("/register", checkLoggedIn, (req, res) => {
res.render("pages/register", { title: "register page", noHeader: true });
});
app.post("/register", async (req, res) => {
try {
const hashedPassword = await bcrypt.hash(req.body.password, 10);
users.push({
id: Date.now().toString(),
username: req.body.name,
email: req.body.email,
password: hashedPassword,
});
console.log("after:", users);
res.redirect("login");
} catch {
res.redirect("/register");
}
});
app.delete("/logout", function (req, res, next) {
req.logout(function (err) {
if (err) {
return next(err);
}
res.redirect("/login");
});
});
app.get("/about", checkAuthenticated, async (req, res) => {
// console.log("users in /login:", users)
res.render("pages/about", { title: "About us" });
});
function defineCookieLength(req, res, next) {
if (req.body.rememberMe === "on") {
req.session.cookie.maxAge = 120 * 1000;
next();
return;
}
next();
}
// validate that the user is already logged in before let him see other pages
function checkAuthenticated(req, res, next) {
if (req.isAuthenticated()) {
return next();
}
res.redirect("/login");
}
// validate that user can't use login/register pages if he is already logged in
function checkLoggedIn(req, res, next) {
if (req.isAuthenticated()) {
return res.redirect("/");
}
next();
}
const PORT = process.env.PORT || 8000;
app.listen(PORT, () => {
console.log(`Server Running on port: http://localhost:${PORT}`);
});
passport-config.js
const LocalStrategy = require("passport-local").Strategy;
const bcrypt = require("bcrypt");
function initialize(passport, getUserByEmail, getUserById) {
const authenticateUser = async (email, password, done) => {
const user = getUserByEmail(email);
if (user == null) {
return done(null, false, { message: "No user with that email" });
}
try {
if (await bcrypt.compare(password, user.password)) {
return done(null, user);
} else {
return done(null, false, { message: "Password incorrect" });
}
} catch (err) {
return done(err);
}
};
passport.use(new LocalStrategy({ usernameField: "email" }, authenticateUser));
passport.serializeUser((user, done) => done(null, user.id));
passport.deserializeUser((id, done) => {
return done(null, getUserById(id));
});
}
module.exports = initialize;
I created a server with express and have some get/post routes.
In the login page, I have a page that shows the form to login:
app.get("/login", (req, res) => {
res.send(`<h1>Iniciar sesión</h1>
<form method='post' action='/login'>
<input type='email' name='email' placeholder='Email' required />
<input type='password' name='password' placeholder='Contraseña' required />
<input type='submit' value='Ingresar' />
</form>
<a href='/register'>Registrarse</a`);
});
Then I have a Post method in which I set the cookies:
app.post("/login", (req, res) => {
const { email, password } = req.body;
const user = users.filter(
(e) => e.email === email && e.password === password
);
if (user.length >= 1) {
res.cookie("userId", user.id);
res.cookie("password", user.password);
res.redirect("/home");
} else {
console.log("contraseña incorrecta");
res.redirect("/login");
}
});
The problem is that when I go to this route, the user.name and user.email are undefined. In other words, I can´t acces to the cookie:
app.get("/home", (req, res) => {
const id = req.cookies.userId;
console.log(id); //this is undefined
const user = users.filter((u) => u.id === id);
//console.log(user);
res.send(`
<h1>Bienvenido ${user.name}</h1>
<h4>${user.email}</h4>
<a href='/'>Inicio</a>
`);
});
Advices?
Here is the complete code:
const express = require("express");
const morgan = require("morgan");
const cookieparser = require("cookie-parser");
const bodyparser = require("body-parser");
const app = express();
const users = [
{ id: 1, name: "Franco", email: "Franco#mail.com", password: "1234" },
{ id: 2, name: "Toni", email: "Toni#mail.com", password: "1234" },
];
app.use(morgan("dev"));
app.use(cookieparser());
app.use(bodyparser.urlencoded({ extended: true }));
app.use((req, res, next) => {
console.log(req.cookies);
next();
});
app.get("/", (req, res) => {
res.send(`
<h1>Bienvenidos a Henry!</h1>
${
req.cookies.userId
? `<a href='/home'>Perfil</a>
<form method='post' action='/logout'>
<button>Salir</button>
</form>
`
: `
<a href='/login'>Ingresar</a>
<a href='/register'>Registrarse</a>`
}
`);
});
app.get("/register", (req, res) => {
res.send(`<h1>Registrarse</h1>
<form method='post' action='/register'>
<input name='name' placeholder='Nombre' required />
<input type='email' name='email' placeholder='Email' required />
<input type='password' name='password' placeholder='Contraseña' required />
<input type='submit' value='Registrarse' />
</form>
<a href='/login'>Iniciar sesión</a>`);
});
app.get("/login", (req, res) => {
res.send(`<h1>Iniciar sesión</h1>
<form method='post' action='/login'>
<input type='email' name='email' placeholder='Email' required />
<input type='password' name='password' placeholder='Contraseña' required />
<input type='submit' value='Ingresar' />
</form>
<a href='/register'>Registrarse</a`);
});
app.post("/login", (req, res) => {
const { email, password } = req.body;
const user = users.filter(
(e) => e.email === email && e.password === password
);
if (user.length >= 1) {
res.cookie("userId", user.id);
res.cookie("password", user.password);
res.redirect("/home");
} else {
console.log("contraseña incorrecta");
res.redirect("/login");
}
});
app.get("/home", (req, res) => {
const id = req.cookies;
console.log(id);
const user = users.filter((u) => u.id === id);
//console.log(user);
res.send(`
<h1>Bienvenido ${user.name}</h1>
<h4>${user.email}</h4>
<a href='/'>Inicio</a>
`);
});
app.listen(3000, (err) => {
if (err) {
console.log(err);
} else {
console.log("Listening on localhost:3000");
}
});
Part of your problem is that this code:
const user = users.filter(
(e) => e.email === email && e.password === password
);
produces an Array. So, user is an array.
Therefore when you do this:
res.cookie("userId", user.id);
res.cookie("password", user.password);
Both user.id and user.password are ignoring the match you got in user[0] and are referring to non-existent properties on the user array object. They will end up undefined and thus why res.cookie() is not setting a meaningful value.
You should, instead be doing this:
res.cookie("userId", user[0].id);
res.cookie("password", user[0].password);
But, please don't put a password in a user's cookie. There should be no reason to ever do that. Even more so when it's in plain text. If you want to know if the previous user is logged in or not, then use a cryptographically secure token in the cookie (like something express-session uses). Don't put their password in a cookie.
I am having trouble getting user data and making user data reactive after the user has logged In.
Without using Store i am getting the user information but I am unable to make it reactive. So I tried storing user information in store. Now I am having getting that data as well.
I have a login form in LOGINCOMPONENT.VUE that has two input fields email and password.
<form #submit.prevent="login">
<input placeholder="Email" type="email" v-model="formData.email">
<input placeholder="Password" type="password" v-model="formData.password">
</form>
Script portion:
export default {
name: 'LoginPage',
data() {
return {
formData: {},
};
},
methods: {
login() {
this.$axios.post('login', this.formData).then(async (res) => {
await localStorage.setItem('user', JSON.stringify(res));
await localStorage.setItem('token', res.token);
this.$router.push('/');
console.log(res);
this.$store.dispatch('userDataAction', res); --->>> Using Store to take user data
}).catch((error) => {
console.log(error);
});
},
},
};
Login process goes well and user token is generated.
This is my store.
const state = {
token: localStorage.getItem('token') || null,
userData: {},
};
const getters = {
getUserData: state => state.userData,
loggedIn: state => state.token != null,
};
const mutations = {
userDataMutation(state, userData) {
state.userData = userData;
},
};
const actions = {
userDataAction(context, credentials) {
const userData = {
username: credentials.username,
email: credentials.email,
firstName: credentials.first_name,
lastName: credentials.last_name,
};
context.commit('userDataMutation', userData);
},
};
Finally in my HEADERCOMPONENT.VUE where i am showing "SIGN IN" if user is not logged In and "HELLO USERNAME" if user is logged in.
export default {
name: 'HeaderComponent',
computed: {
...mapGetters(['getUserData', 'loggedIn']),
},
};
Template:
<div> {{ loggedIn ? getUserData.username : 'Sign In' }} </div>
I use VueJS (cli 3) & axios, and NodeJS - ExpressJS in the back-end. I am trying to secure my post user edit using CSRF token.
Vue View (edit user - focus to mySubmitEd):
<template>
<div class="one-user">
<h1>this user</h1>
<h2>{{name}} - {{surname}} - {{ perm }}</h2>
<h2>Edit</h2>
<input type="text" v-model="name">
<input type="text" v-model="surname">
<input type="text" v-model="perm">
<button #click="mySubmitEd">Edit</button>
<button #click="mySubmit">Delete</button>
</div>
</template>
<script>
import axios from 'axios'
import io from 'socket.io-client'
export default {
name: 'one-user',
data () {
return {
name: '',
surname: '',
perm: '',
csrf: '',
id: this.$route.params.id,
socket: io('localhost:7000')
}
},
mounted () {
axios.get('http://localhost:7000/api/get-user/' + this.id)
.then(res => {
const data = res.data.user
this.name = data.name
this.surname = data.last_name
this.perm = data.permalink
this.csrf = res.data.csrfToken
axios.defaults.headers.common['X-CSRF-TOKEN'] = this.csrf
})
.catch(error => console.log(error))
},
methods: {
mySubmit () {
const formData = {
_id: this.id
}
axios.post('http://localhost:7000/api/delete-user', formData)
.then(this.$router.push({ name: 'get-user' }))
.catch(error => console.log(error))
},
mySubmitEd () {
const formData = {
_id: this.id,
name: this.name,
last_name: this.surname,
permalink: this.perm,
_csrf: this.csrf
}
console.log(formData._csrf)
axios.post('http://localhost:7000/api/update-user', formData)
.catch(error => console.log(error))
}
}
}
</script>
server.js file:
...
const cookieParser = require('cookie-parser');
const csurf = require('csurf');
...
app.use(cookieParser());
const csrfProtection = csurf({ cookie: true });
app.use(csrfProtection);
...
back-end controller which get the user:
controller.getOneUser = function(req, res) {
User.findOne({ _id: req.params.userId }).exec(function(err, user) {
res.json({user, csrfToken: req.csrfToken()});
});
};
back-end update post:
controller.updateUser = function(req, res) {
User.findById(req.body._id, function(err, user) {
user.set({
name: req.body.name,
last_name: req.body.last_name,
permalink: req.body.permalink,
price: req.body.price
});
user.save();
res.send(user);
});
};
My errors in NodeJS-exress console:
ForbiddenError: invalid csrf token
My errors in browser:
POST http://localhost:7000/api/update-user 403 (Forbidden)
I don't know what is happened because I see in network tab(chrome) the csrf token is the same in the headers and what I send (ex.):
X-CSRF-TOKEN: PddyOZrf-AdHppP3lMuWA2n7AuD8QWFG3ta0
_csrf: "PddyOZrf-AdHppP3lMuWA2n7AuD8QWFG3ta0"
I don't know what I have miss here. I can't find where is the problem.
If you want more information please asked me to help you.
I had to pass in the headers the cookie correctly, so I did 2 corrections:
First in Vue view:
I passed credentials:
axios.create({withCredentials: true}).get(...)
and
axios.create({withCredentials: true}).post(...)
and secondly in server.js file before routes I put this:
...
const corsOptions = {
origin: 'http://localhost:8080',
credentials: true,
}
app.use(cors(corsOptions));
app.use(bodyParser.json());
app.use(cookieParser());
const csrfProtection = csurf({ cookie: true });
app.use(csrfProtection);
app.use(function (req, res, next) {
res.cookie('XSRF-TOKEN', req.csrfToken());
res.locals._csrf = req.csrfToken();
next();
});
...
I am new to express and I was able to get most of it to work until I wanted to create a delete button.
I am having difficulty getting my delete button to work all the time. It works at random moment and other times it does not work and when it does not work the following error appears:
{ CastError: Cast to ObjectId failed for value "undefined" at path "_id" for model "User"
Code below:
Both index.js and users.js files are in routes directory
//user - file in module directory
var mongoose = require('mongoose');
var bcrypt = require('bcryptjs');
var UserSchema = mongoose.Schema({
username: {
type: String,
index: true
},
password: {
type: String
},
email: {
type: String
},
name: {
type: String
},
isAdmin: {
type: Boolean,
default: false
}
});
var User = module.exports = mongoose.model('User', UserSchema);
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.getUserByUsername = function(username, callback){
var query = {username: username};
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);
});
}
<!--page with delete button-->
<section class="jumbotron">
<div class="container">
<h1 class="jumbotron-heading text-center">Users Page</h1>
</div>
<div>
<ul class="list-group">
{{#each users}}
<li class="list-group-item">{{this.name}}</li>
{{/each}}
</ul>
</div>
</secion>
//main.js - file in the javascript directory
$(document).ready(function(){
$('.delete-user').on('click', function(e) {
$target = $(e.target);
const id = $target.attr('data-id');
$.ajax({
type: 'DELETE',
url: '/users/user/'+id,
success: function(response){
alert('Deleting User');
window.location.href='/users/users';
},
error: function(err){
console.log(err);
}
});
});
});
//users.js - file
var express = require('express');
var router = express.Router();
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var User = require('../modules/user');
// Admin Page
router.get('/admin', function(req, res){
res.render('admin');
});
// Login Page
router.get('/login', function(req, res){
res.render('login');
});
// Registeration Page
router.get('/register', function(req, res){
res.render('register');
});
// Users
router.get('/users', function(req, res) {
User.find({}, function(err, users) {
if(err) {
console.log(err);
} else {
res.render('users', {
users: users
});
}
});
});
// Individual Users
router.get('/user/:id', function(req, res) {
User.findById(req.params.id, function(err, users) {
res.render('user', {
users: users
});
});
});
// Delete Users
router.delete('/user/:id', function(req, res) {
let query = {_id:req.params.id};
User.remove(query, function(err){
if(err){
console.log(err);
}
res.send('Success');
});
});
// Create post request from form to server
router.post('/register', function(req, res){
var name = req.body.name;
var email = req.body.email;
var username = req.body.username;
var password = req.body.password;
var password2 = req.body.password2;
var adminCode = req.body.adminCode;
//Validation
req.checkBody('name', 'Name is required').notEmpty();
req.checkBody('email', 'Email is Required').notEmpty();
req.checkBody('email', 'Email is not valid').isEmail();
req.checkBody('username', 'Username is required').notEmpty();
req.checkBody('password', 'Password is required').notEmpty();
req.checkBody('password2', 'Passwords do not match').equals(req.body.password);
var errors = req.validationErrors();
if(errors){
res.render('register',{
errors:errors
});
} else {
var newUser = new User({
name: name,
email: email,
username: username,
password: password
});
if(adminCode === 'secretcode123') {
newUser.isAdmin = true;
}
User.createUser(newUser, function(err, user){
if(err) throw err;
console.log(user);
});
req.flash('success_msg', 'You are registered and can now login');
res.redirect('/users/register');
}
});
passport.use(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: '/users/login', failureFlash: true }),
function(req, res) {
res.redirect('/');
});
router.get('/logout', function(req, res){
req.logout();
req.flash('success_msg', 'You are logged out');
res.redirect('/users/login');
});
module.exports = router;
//indexjs - file
var express = require('express');
var router = express.Router();
// Home Page
router.get('/', ensureAuthenticated, function(req, res){
res.render('index');
});
function ensureAuthenticated(req, res,next){
if(req.isAuthenticated()){
return next();
} else {
//req.flash('error_msg', 'You are not logged in');
res.redirect('/users/login');
}
}
module.exports = router;
code here
can someone please advise what i am doing wrong.
It seems like i was able to correct the error. I had to move my data-id element from from my div tag to my anchor tag: see code below:
<section class="jumbotron">
<div class="container">
<h1 class="jumbotron-heading text-center">User Page</h1>
<h1 class="text-center">{{users.name}}</h1>
</div>
<div class="button">
<button class="btn btn-danger delete-user"/*it was here first*/><a href="#" /*now it is here*/data-id={{users._id}}>Delete</a></button>
</div>
</secion>