Good day, Please help me find the error in my code for level one authentication I could create a database, register users and store in their inputs using body parser, but I couldn't login already registered users. the login page keeps loading till it tells me a connection error, please help me out
const express = require("express");
const bodyParser = require("body-parser");
const ejs = require("ejs");
const mongoose = require("mongoose");
const app = express();
app.use(express.static("public"));
app.set('view-engine', 'ejs');
app.use(bodyParser.urlencoded({
extended: true
}));
mongoose.connect("mongodb://localhost:27017/User", {useNewUrlParser: true});
const userSchema = ({
email: String,
password: String
});
const User = new mongoose.model("User", userSchema);
const users = []
app.get("/", function(req, res){
res.render("first.ejs");
});
app.get("/login", function(req, res){
res.render("login.ejs");
});
app.get("/register", function(req, res){
res.render("register.ejs");
});
app.post("/register", function(req, res){
const newUser = new User({
email: req.body.username,
password: req.body.password
});
newUser.save(function(err){
if (err) {
console.log(err);
} else {
res.render("home.ejs");
}
});
});
app.post("/login", function(req, res){
const username = req.body.username;
const password = req.body.password;
User.findOne({email: username}, function(err, foundUser){
if (err) {
console.log(err);
} else {
if (foundUser) {
if (foundUser.password === password) {
res.send("hi");
}
}
}
});
});
app.listen(3000, function() {
console.log("Server started on port 3000.");
});
Related
I am new to the Passport.js. Whenever I login or register through the routes, req.isAuthenticated() always returns false and the secrets view is never rendered. Here is my app.js:
`
require("dotenv").config();
const express = require("express");
const bodyParser = require("body-parser");
const session = require("express-session");
const passport = require("passport");
const LocalStrategy = require("passport-local")
const passportLocalMongoose = require("passport-local-mongoose");
const mongoose = require("mongoose");
mongoose.set("strictQuery", true);
uri = "mongodb://localhost:27017/usersDB";
const userSchema = new mongoose.Schema({
username: String,
password: String
});
userSchema.plugin(passportLocalMongoose);
const User = new mongoose.model("User", userSchema);
passport.use(new LocalStrategy(User.authenticate()));
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
const app = express();
app.use(bodyParser.urlencoded({extended: true}));
app.use(express.static("public"));
app.set("view engine", "ejs");
app.use(session({
secret: "MyLittleSecret",
resave: false,
saveUninitialized: false
}));
app.use(passport.initialize());
app.use(passport.session());
app.get("/", function(req, res) {
res.render("home");
});
app.get("/secrets", function(req, res) {
if(req.isAuthenticated) {
res.render("secrets");
} else {
res.redirect("/login");
}
});
app.route("/register")
.get(function(req, res) {
res.render("register");
})
.post(async function(req, res) {
await User.register({username: req.body.username}, req.body.password, function(err, user) {
console.log("In the User.register callback function");
if(err) {
console.log(err);
res.redirect("/register");
} else {
passport.authenticate("local")(req, res, function() {
res.redirect("/secrets");
});
}
});
});
app.route("/login")
.get(function(req, res) {
res.render("login",{
errorMessage: ""
});
})
.post(async function(req, res) {
const userInstance = new User({
username: req.body.username,
password: req.body.password
});
req.login(userInstance, function(err) {
if(err) {
console.log(err);
} else {
passport.authenticate("local")(req,res,function() {
res.redirect("/secrets");
});
}
});
});
app.listen(3000, function() {
console.log("Server started listening to port 3000");
});
I searched on the web and tried the various orders of middleware. I could not solve the problem.
I get a 401 'Unauthorized' being sent through even on new user being created.
I've tried refactoring my code many times and checking SO as well as Googleing all over but with no success.
user.js
const mongoose = require("mongoose");
const passportLocalMongoose = require('passport-local-mongoose');
const userSchema = new mongoose.Schema({
username: String,
password: String
});
userSchema.plugin(passportLocalMongoose);
module.exports = mongoose.model('User', userSchema);
auth.js
const express = require("express");
const router = express.Router();
const passport = require('passport');
const session = require('express-session');
router.use(session({
secret: process.env.SECRET,
resave: false,
saveUninitialized: false
}));
router.use(passport.initialize());
router.use(passport.session());
const User = require("../models/user");
passport.use(User.createStrategy());
passport.serializeUser(User.serializeUser())
passport.deserializeUser(User.deserializeUser());
router.get('/register', (req, res) => {
res.render('register', { title: 'Casa Lugano Immobiliare SA | Registrati' });
})
router.post('/register', (req, res) => {
User.register({ username: req.body.username }, 'password', (err, user) => {
if (err) {
console.error(err);
res.redirect('/register');
} else {
passport.authenticate('local')(req, res, () => {
console.log('user authenticated')
res.redirect('/');
})
}
})
});
module.exports = router;
app.js
mongoose.connect('mongodb://localhost:27017/DB', { useNewUrlParser: true });
//REQUIRING ROUTES
const authRoute = require("./routes/auth");
app.use(authRoute);
I would like the user to be authenticated after registration! I've been stuck for many hours so any help would be very appreciated!
I've found the bug, I had to pass an User object instead of the username only:
User.register({ username: req.body.username }
becomes:
const newUser = new User({ username: req.body.username });
User.register(newUser, req.body.password, function (err, user) { [...]
Thanks for the attention!
I am trying to get some data from Mongoose using Express. I have created a username and password form to log in to my site. It is supposed to check the credentials and let them in if the credentials are the same as the ones stored on the database, but it is letting anything in (even if I put the wrong password). My source files seem fine, and the console is not throwing any errors. The Gists to the files are below:
login.ejs
register.ejs
And the app.js file (can't gist it due to my reputation):
var bodyParser = require('body-parser');
var express = require('express');
var mongoose = require('mongoose');
var app = express();
var options = {
server: {
socketOptions: {
keepAlive: 300000, connectTimeoutMS: 30000
}
},
replset: {
socketOptions: {
keepAlive: 300000,
connectTimeoutMS : 30000
}
}
};
var db = mongoose.connect('db_uri', options);
var Schema = mongoose.Schema;
var UserSchema = new Schema({
email: String,
password: String
});
var User = mongoose.model('Users', UserSchema);
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.static(__dirname+'/public'));
app.set('view engine', 'ejs');
app.set('views', __dirname+'/public/templates');
app.get('/', function (req, res) {
res.render('index');
});
app.get('/registerPage', function (req, res) {
res.render('register') ;
});
app.get('/loginPage', function (req, res) {
res.render('login');
});
app.post('/register', function (req, res) {
var email = req.body.email;
var password = req.body.password;
var user = new User({
email: email,
password: password
});
user.save(function (err) {
if (err) throw err;
console.dir(user);
res.send('Account created successfully (email): ' + email);
});
});
app.post('/login', function (req, res) {
var email = req.body.email;
var password = req.body.password;
User.findOne( {email: email, password: password}, function (err) {
if (err) throw err;
res.render('portal');
});
});
app.listen(3000, function () {
console.log('Express server listening on http://localhost:3000');
});
Thanks for your help!
In the login handler, you're not actually checking if the query matches a user.
Perhaps you assume that err will be set in that case, but it won't be, because the query itself was performed successfully (it just didn't return any records).
You need to add an additional check to see if the query returned a valid user:
User.findOne( {email: email, password: password}, function (err, user) {
if (err) throw err;
if (! user) return res.send(401);
res.render('portal');
});
This will return a 401 ("Unauthorized") when the query didn't match a user.
I'm using nodejs and MongoDB for the first time and I'm having trouble when I want to connect to the DB.
I read the quickstart from mongoosejs but it still doesn't work, here is my code (right now, all my code is only in one file) :
/***** Utilities *****/
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var path = require('path');
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var mongo = require('mongodb');
var mongoose = require('mongoose');
app.listen(8080);
mongoose.connect('mongodb://localhost:8080/users');
var db = mongoose.connection;
db.on('error', function (error) {
console.log('/**************** ERROR **************\\');
console.log(error);
});
db.on('open', function () {
console.log("Hello World!");
});
var Schema = mongoose.Schema;
var UserSchema = new Schema({
pseudo: String,
password: String,
email: String
});
var Users = mongoose.model('users', UserSchema);
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(express.static(path.join(__dirname, 'public')));
app.set('views', __dirname + '/views');
app.use(passport.initialize());
app.use(passport.session());
/***** Passport *****/
passport.serializeUser(function (user, done) {
done(null, user);
});
passport.deserializeUser(function (user, done) {
done(null, user);
});
/***** Building routes *****/
app.get('/', function (req, res) {
res.send('Hello World!');
});
app.post('/', function (req, res) {
var pseudo = req.body.pseudo;
console.log("/******************************\\") console.log(pseudo);
res.send('Hello ' + pseudo + '!');
});
app.get('/users', function (req, res) {
Users.find(function (error, users) {
if (error) console.log(error);
else res.render('users.jade', {
users: users
})
});
})
app.post('/create_user', function (req, res) {
var user = new Users({
pseudo: req.body.pseudo,
password: req.body.password,
email: req.body.email
});
user.save(function (error, user) {
if (error) console.log(error);
else res.render('create_user.jade');
});
});
app.get('/login', function (req, res) {
passport.authenticate('users', {
successRedirect: '/create_user',
failureRedirect: '/login',
}) res.render('login.jade
);
});
I'm trying to get data from the login page and store them into one mongo database but I'm when I start this file, mongo returns the following message:
MongoError: server localhost:8080 sockets closed
name: 'MongoError',
message: 'server localhost:8080 sockets closed'
I really don't know how to correct this error.
Where am I wrong? Is it because of a possible asynchronous problem?
The code
app.js:
var express = require('express');
var session = require('express-session');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var mongoStore = require('connect-mongo')(session);
var mongoose = require('mongoose');
var passport = require('passport');
var config = require('./config');
var routes = require('./routes');
var mongodb = mongoose.connect(config.mongodb);
var app = express();
// view engine setup
app.set('views', config.root + '/views');
app.set('view engine', 'jade');
app.engine('html', require('ejs').renderFile);
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: false
}));
app.use(cookieParser());
app.use(express.static(config.root + '/public'));
app.use(session({
name: 'myCookie',
secret: 'tehSecret',
resave: true,
saveUninitialized: true,
unset: 'destroy',
store: new mongoStore({
db: mongodb.connection.db,
collection: 'sessions'
})
}));
app.use(passport.initialize());
app.use(passport.session());
app.use('/', routes);
app.set('port', config.port);
var server = app.listen(app.get('port'), function() {
if (config.debug) {
debug('Express server listening on port ' + server.address().port);
}
});
routes.js:
var express = require('express');
var router = express.Router();
var config = require('../config');
var userController = require('../controllers/user');
var authController = require('../controllers/auth');
router.get('/', function(req, res) {
res.render('index', {
title: config.app.name
});
});
router.route('/users')
.post(userController.postUsers)
.get(authController.isAuthenticated, userController.getUsers);
router.get('/signout', userController.signout);
module.exports = router;
models/user.js:
var mongoose = require('mongoose');
var bcrypt = require('bcrypt-nodejs');
var UserSchema = new mongoose.Schema({
username: {
type: String,
unique: true,
required: true
},
password: {
type: String,
required: true
}
});
// Execute before each user.save() call
UserSchema.pre('save', function(callback) {
var user = this;
// Break out if the password hasn't changed
if (!user.isModified('password')) return callback();
// Password changed so we need to hash it
bcrypt.genSalt(5, function(err, salt) {
if (err) return callback(err);
bcrypt.hash(user.password, salt, null, function(err, hash) {
if (err) return callback(err);
user.password = hash;
callback();
});
});
});
UserSchema.methods.verifyPassword = function(password, cb) {
bcrypt.compare(password, this.password, function(err, isMatch) {
if (err) return cb(err);
cb(null, isMatch);
});
};
// Export the Mongoose model
module.exports = mongoose.model('User', UserSchema);
controllers/user.js:
var config = require('../config');
var User = require('../models/user');
exports.postUsers = function(req, res) {
if (config.debug)
console.log("user.postUsers()");
var user = new User({
username: req.body.username,
password: req.body.password
});
user.save(function(err) {
if (err)
return res.send(err);
if (config.debug)
console.log("saved");
res.json({
message: 'New user created!'
});
});
};
exports.getUsers = function(req, res) {
if (config.debug)
console.log("user.getUsers()");
User.find(function(err, users) {
if (err)
return res.send(err);
if (config.debug)
console.log("users", users);
res.json(users);
});
};
exports.signout = function(req, res) {
if (config.debug)
console.log("user.signout()");
res.clearCookie('myCookie');
req.session.destroy(function(err) {
req.logout();
res.redirect('/');
});
};
controllers/auth.js:
var passport = require('passport');
var BasicStrategy = require('passport-http').BasicStrategy;
var config = require('../config');
var User = require('../models/user');
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(new BasicStrategy(
function(username, password, done) {
User.findOne({
username: username
}, function(err, user) {
if (err) {
return done(err);
}
// No user found with that username
if (!user) {
return done(null, false);
}
// Make sure the password is correct
user.verifyPassword(password, function(err, isMatch) {
if (err) {
return done(err);
}
// Password did not match
if (!isMatch) {
return done(null, false);
}
// Success
return done(null, user);
});
});
}
));
exports.isAuthenticated = passport.authenticate('basic', {
session: false
});
The problem
/signout route does not end the current session. In the req.session.destroy callback the req.session is undefined, yet a new GET request to /users acts like the session is valid.
Can someone help clear this problem out?
If, like me, you came here as a result of question title rather than full details- the answer is req.session.destroy(). I think the logout function is particular to passport.js and will not work if you are using standard express-session.
Solution
controllers/user.js:
exports.signout = function(req, res) {
if (config.debug)
console.log("user.signout()");
req.logout();
res.send(401);
};
Btw. don't mind the session(s) still being in DB immediately after the logout. Mongod checks and clears those out after 60 s.
in sign out api without using req.session.destroy() try req.logout();. I hope it will work.
In my case the server-side code was fine. It was the client-side code where I wasn't including the withCredentials parameter when making the http request.
Below is the correct working code.
// server side (nodejs)
authRouter.post("/logout",
passport.session(),
checkAuthenticationHandler,
async (req, res, next) => {
req.logOut(err => {
if (err) next(err)
res.status(http.statusCodes.NO_CONTENT).end()
})
})
// client side (reactjs)
export const logout = async () => {
const _response = await axios({
method: 'post',
url: `${authApi}/auth/logout`,
withCredentials: true
})
}