Im running a local strategy in passport and I have had an issue where it seems to authenticate users fine and I can have that user persisted across the site in a session, but not admins. I have the user and admin account under separate collections in MongoDB.I have tried plenty of different routes like having different passports for admin and user and having different databases for admin and users to no avail. I have come to a stand still. I would appreciate an advice!
//Passport.js
const LocalStrategy = require('passport-local').Strategy;
const mongoose = require('mongoose')
const bcrypt = require('bcrypt')
// Loads in user model
const User = require('../models/userModel')
//Loads in the admin model
const Admin = require('../models/adminModel')
module.exports = function (authUser){
authUser.use(
'authUser',new LocalStrategy({usernameField: 'username'}, (username, password, done)=>{
//Match user
const user = User.findOne({username: username})
.then(user=>{
if(!user){
return done(null, false, {message: 'Incorrect Username'})
}
//Match password
bcrypt.compare(password, user.password, (err, isMatch)=>{
if(err) throw err;
if (isMatch) {
return done(null, user)
}else {
return done(null, false, {message: 'Incorrect password'})
}
})
})
.catch(err=>console.log(err));
})
)
authUser.serializeUser((user, done) =>{
done(null, user.id);
});
authUser.deserializeUser((id, done) =>{
User.findById(id, (err, user) => {
done(err, user);
});
});
authUser.use(
'admin',new LocalStrategy({usernameField: 'username'}, (username, password, done)=>{
//Match user
const admin = Admin.findOne({username: username})
.then(admin=>{
if(!admin){
return done(null, false, {message: 'Incorrect Username'})
}
//Match password
bcrypt.compare(password, admin.password, (err, isMatch)=>{
if(err) throw err;
if (isMatch) {
return done(null, admin)
}else {
return done(null, false, {message: 'Incorrect password'})
}
})
})
.catch(err=>console.log(err));
})
)
authUser.serializeUser((admin, done) =>{
done(null, admin.id);
});
authUser.deserializeUser((id, done) =>{
Admin.findById(id, (err, admin) => {
done(err, admin);
});
});
}
//Authenticate.js
module.exports = {
checkAuthenticated: function(req, res, next) {
if (req.isAuthenticated()) {
return next()
}
// req.flash('error_msg', 'please login to view this resource')
res.redirect('/Users/Login')
},
checkNotAuthenticated: function(req, res, next) {
if (req.isAuthenticated()) {
return res.redirect('/')
}
// req.flash('error_msg', 'please login to view this resource')
return next()
},
checkAdminAuthenticated: function(req, res, next) {
if (req.isAuthenticated()) {
return next()
}
// req.flash('error_msg', 'please login to view this resource')
res.redirect('http://localhost:3000/Admin/SignIn')
}
}
//Snippet from adminRoute.js
const passport = require('passport')
require('../config/passport.js')(passport)
app.get("/SignIn", checkNotAuthenticated,(req,res) =>{
res.render("adminLogin.ejs")
})
app.get('/Orders', checkAdminAuthenticated, (req, res) => {
Request.find({}).then(results => {
res.render('orders.ejs', {
Orders: results
});
})
})
// Login Handle
app.post('/SignIn', checkNotAuthenticated, (req,res, next)=>{
passport.authenticate('admin',{
successRedirect: '/AdminPage', //On success redirect to home
failureRedirect: '/Admin/SignIn', //On failure redirect back to login page
session: true,
failureFlash: true
})(req,res,next);
})
module.exports = app
//Snippet from userRoute.js
const passport = require('passport')
const authUser = new passport.Passport();
require('../config/passport.js')(authUser)
// DB config
const userDB = require('../config/keys').MongoURI
const User = require('../models/userModel')
app.get("/Login", checkNotAuthenticated,(req,res) =>{
res.render("login.ejs")
})
app.delete('/logout', (req, res) => {
req.logOut()
res.redirect('/Users/Login')
})
app.get('/Register', checkNotAuthenticated, (req,res)=>{
res.render("register.ejs")
})
// Login Handle
app.post('/Login', checkNotAuthenticated,(req,res, next)=>{
authUser.authenticate('authUser',{
successRedirect: '/', //On success redirect to home
failureRedirect: '/Users/Login', //On failure redirect back to login page
session: true,
failureFlash:true
})(req,res,next);
})
module.exports = app
// snippet from app.js
const passport = require('passport')
const authUser = new passport.Passport();
require('./config/passport.js')(authUser)
app.use(authUser.initialize())
app.use(authUser.session())
app.use('/Users', require('./routes/userRoute'))
app.use('/Admin', require('./routes/adminRoute'))
Related
I have the following code to authenticate through the passport-local strategy:
routes.post("/login", passport.authenticate("local"), (req, res) => {
res.json(req.user);
});
function ensureAuth(req, res, next) {
console.log(req.isAuthenticated());
if (req.isAuthenticated()) {
next();
} else {
req.flash("info", "You must be logged in to see this page");
res.redirect("/login");
}
}
routes.get("/edit", ensureAuth, (req, res) => {
res.sendStatus(200);
});
routes.post("/edit", ensureAuth, (req, res, next) => {
req.user.username = req.body.username;
req.user.bio = req.body.bio;
req.user.email = req.body.email;
req.user.save((err) => {
if (err) {
return next(err);
} else {
res.send({
success: "true",
info: "Profile updated",
});
}
});
});
I can't figure out why this is happening? Why won't it authenticate?
I can't see your passport local configuration and I send a sample for local Authentication by passport local I hope help you :)
login route:
router.post('/login', loginController.process);
controller loginController.process :
async process(req, res, next) {
try {
passport.authenticate('local.login', async (err, user) => {
// User not Exist
if (!user) return this.back(req, res);
req.logIn(user, (err) => {
if (req.body.remember) {
user.setRememberToken(res);
}
return res.redirect('/');
});
})(req, res, next);
} catch (e) {
next(e);
}
}
}
passport configuration :
passport.use('local.login', new localStrategy({
usernameField: 'email',
passwordField: 'password',
passReqToCallback: true,
}, async (req, email: string, password: string, done) => {
// Select User Where email
const user = await userService.findOne({email});
// Check user Exist or Incorrect Password
if (!user || !user.comparePassword(password)) return done(req.flash('global_error', req.__('typeScript.app.passport.passport-local.wrong')), null);
done(null, user);
}));
As a beginner I was following a tutorial to make my first website with node.js but when I try to test a login with 100% valid information I get the following error:
Error: Failed to serialize user into session
Something weird I found is that when the error pops up I go back to the previous page, in this case the login page, and a welcome message I added on /profile.hbs/ pops up as if I was in a session.
This is my passport.js
const res = require('express/lib/response');
const passport = require('passport');
const pool = require('../database');
const router = require('../routes/usuario');
const LocalStrategy = require('passport-local').Strategy;
//const helpers = require('../lib/helpers')
passport.use('local.signin', new LocalStrategy({
usernameField: 'username',
passwordField: 'password',
passReqToCallback: true
}, async (req, username, password, done) => {
const rows = await pool.query('SELECT * FROM userr WHERE username = ?', [username])
if (rows.length > 0) {
const user = rows[0];
const validPassword = user.password == password
if (validPassword) {
done(null, user, req.flash('success', 'Bienvenido, ' + user.username))
}else{
done(null, false, req.flash('message', 'ContraseƱa incorrecta'))
}
} else {
return done(null, false, req.flash('message', 'El usuario no existe'))
}
}));
passport.use('local.signup', new LocalStrategy({
usernameField: 'username',
passwordField: 'password',
passReqToCallback: true
}, async (req, username, password, done) => {
const newUser = {
username: username,
password: password
};
//newUser.password = await helpers.encryptPassword(password);
const result = await pool.query('INSERT INTO userr SET ?', [newUser])
newUser.id_user = result.insertId;
return done(null, newUser);
}));
passport.serializeUser((user, done) => {
console.log(user)
done(null, user.id_user)
});
passport.deserializeUser(async (id_user, done) => {
const rows = await pool.query('SELECT * FROM userr WHERE ID = ?', [id_user]);
done(null, rows[0]);
});
And this is my authentication.js
const express = require('express');
const router = express.Router();
const passport = require('passport');
const { route } = require('./usuario');
router.get('/signup', (req, res) => {
res.render('auth/signup')
});
router.post('/signup', passport.authenticate('local.signup', {
successRedirect: '/profile',
failureRedirect: '/signup',
failureFlash: true
}));
router.get('/signin', (req, res) => {
res.render('auth/signin')
});
router.post('/signin', (req, res, next) => {
passport.authenticate('local.signin',{
successRedirect: '/profile',
failureRedirect: '/signin',
failureFlash: true
})(req, res, next);
})
router.get('/profile', (req, res) => {
res.render('profile');
});
module.exports = router;
I tried to use a different route, I forced out a session (it worked with a deserialize error I had), I redid the login step with completely different variables and a different database but I still got the same response.
I am new to building REST API's, and I am trying to enter new user information into a collection called 'Users', however, when I submit the information I get Cannot POST /register
Below is my code
server.js
require('dotenv').config()
const express = require('express')
const app = express()
const mongoose = require('mongoose')
const expressValidator = require('express-validator')
mongoose.connect(process.env.DATABASE_URL, { useNewUrlParser: true , useUnifiedTopology: true })
const db = mongoose.connection
db.on('error', (error) => console.error(error))
db.once('open', () => console.log('Connected to Database'))
app.use(express.json())
const articlesRouter = require('./routes/articles')
app.use('/articles', articlesRouter)
const userRouter = require('./routes/users')
app.use('/register', userRouter)
app.set('view-engine', 'ejs')
app.use(express.urlencoded({ extended: false }))
app.get('/', (req, res) => {
res.render('index.ejs')
})
app.get('/login', (req, res) => {
res.render('login.ejs')
})
app.post('/login', (req, res) => {
})
app.get('/register', (req, res) => {
res.render('register.ejs')
})
app.listen(3000, () => console.log('Server Started'))
Users model
const mongoose = require('mongoose')
const bcrypt = require('bcrypt')
var userSchema = new mongoose.Schema({
firstName: String,
lastName: String,
email: String,
password: String,
permissionLevel: Number,
created: Date},
{ collection: 'Users'});
module.exports = mongoose.model('Users', 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.getUserByEmail = function(email, callback){
var query = {email: email};
User.findOne(query, callback);
}
module.exports.getUserById = function(id, callback){
user.findById(id, callback);
}
module.exports.comparePassword = function(candidatePassword, hash, callback) {
bcrypt.compare(candidatePassword, hash, function(err, isMatch){
if(err) throw err;
callback(null, isMatch)
});
}
users routes
const express = require('express')
const router = express.Router()
const Users = require('../models/users')
const passport = require('passport')
const LocalStrategy = require('passport-local').Strategy
//Register Page - GET
router.get('/register', (req, res) => {
res.render('register.hbs', {
pageTitle: 'register'
});
});
//Login Page - GET
router.get('/login', (req, res) => {
res.render('login.hbs', {
pageTitle: 'login'
});
});
//Register - POST
router.post('/', (req, res) => {
var firstName = req.body.firstName;
var lastName = req.body.lastName;
var email = req.body.email;
var password = req.body.password;
//validations
req.checkBody('firstName', 'Your First Name is Required').notEmpty();
req.checkBody('lastName', 'Your Last Name is Required').notEmpty();
req.checkBody('email', 'A valid email is required').isEmail();
req.checkBody('password', 'An Account Passowrd Is Required').notEmpty();
var errors = req.validationErrors();
if (errors) {
res.render('register', {
errors:errors
});
} else {
var newUser = new newUser({
firstName: firstName,
lastName: lastName,
email: email,
password: password,
});
User.createUser(newUser, function(err, user) {
if(err) throw(err);
console.log(user);
});
req.flash('success_message', "You are now registered!");
res.redirect('/login');
}
});
passport.use(new LocalStrategy({
email: 'email'
},
function(email, password, done){
Users.getUserByEmail(email, function(err, Users){
if(err) throw err;
if(!Users){
return done(null, false, {message: 'Unknown Email Address'});
}
Users.comparePassword(password, user.password, function(err, ismatch){
if(err) throw err;
if(ismatch){
return done (null, user);
} else {
return done(null, false, {message: 'Invalid Passowrd'});
}
});
});
}));
passport.serializeUser(function(user, done){
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
Users.getUserByID(id, function(err, user) {
done(err, user)
});
});
router.post('/login', passport.authenticate('local', {
successRedirect: '/dashboard',
failureRedirect: '/login',
successFlash: 'Welcome',
failureFlash: 'Invalid Email or Passowrd!'
}), function(req, res) {
res.redirect('/');
});
router.get('/logout', function(req, res) {
req.logout();
req.flash('Success_message', 'You are now logged out!')
res.redirect('/');
});
module.exports = router
I suspect the conflict is between the router /register and the my 'Users' collection. I'm just unable to pinpoint what the issue could be.
Any help would be greatly appreciated
Your userRouter is mounted on /users (from your code: app.use('/users', userRouter), meaning that all the routes you declared in the router are prefixed by /users).
Try calling POST /users/register.
You're using users routes file at /users route, so when you declare /register route in users routes file it become /users/register please send your REST API request to /users/register endpoint
I am currently trying to develop a role based administration. If a user is created at the moment, a "1" is stored in the database at "Admin". If it is a normal user, a "2" will be entered here. I want this to be read from the database and the distinction to be made so that the corresponding start page is displayed.
What I have:
user.js:
const express = require('express');
const router = express.Router();
const bcrypt = require('bcryptjs');
const passport = require('passport');
// Load User model
const User = require('../DB/models/User');
const { forwardAuthenticated } = require('../DB/config/auth');
//User Models
//const User = require('../DB/models/user');
// Login Page
router.get('/login', (req, res) => res.render('login'));
//New User MA
router.get ('/neuerUser_MA', (req, res) => res.render ('neuerUser_MA'));
// Register
router.post('/neuerUSer_MA', (req, res) => {
const { username, admin, password, password2 } = req.body;
let errors = [];
if (password != password2) {
errors.push({ msg: 'Passwords do not match' });
}
if (password.length < 6) {
errors.push({ msg: 'Password must be at least 6 characters' });
}
if (errors.length > 0) {
res.render('neuerUser_MA', {
errors,
username,
admin,
password,
password2
});
} else {
User.findOne({email: email}).then(user => {
if (user) {
errors.push({msg: 'Email or Username already exists'});
res.render('neuerUser_MA', {
errors,
username,
admin,
password,
password2
});
} else {
const newUser = new User({
username,
admin,
password
});
bcrypt.genSalt(10, (err, salt) => {
bcrypt.hash(newUser.password, salt, (err, hash) => {
if (err) throw err;
newUser.password = hash;
newUser
.save()
.then(user => {
req.flash(
'success_msg',
'You are now registered and can log in'
);
res.redirect('/users/login');
})
.catch(err => console.log(err));
});
});
}
});
}
});
// HOW I TRIED THE LOGIN:
router.post('/login', (req, res, next) => {
if(User.admin=="1"){
passport.authenticate('local', {
successRedirect: '/buchungen/startseite_breuninger',
failureRedirect: '/users/login',
failureFlash: true
})(req, res, next);
}
else {
passport.authenticate('local', {
successRedirect: '/buchungen/startseite_spediteur',
failureRedirect: '/users/login',
failureFlash: true
})(req, res, next);
}
});
module.exports = router;
But reading from the database does not work. Regardless of what value is stored under "Admin", the start page from else{} is always shown.
Maybe my approach is too simple. I'm still a beginner ;)
Thanks already now for help!
You can achieve your goal by change your router method like this
router.post(
'/login',
passport.authenticate('local', {
failureRedirect: '/login'
}), (req, res) => {
if (req.user.admin == "1") {
res.redirect('/buchungen/startseite_breuninger');
}
else {
res.redirect('/buchungen/startseite_spediteur');
}
});
I'm have a route to authenticate logins and i need to compare the current user access IP with the user IP that was registered.
router.post('/login', passport.authenticate('local', {
successRedirect: '/index',
failureRedirect: '/login?fail=true'
})
)
On my auth.js file i have this...
const bcrypt = require('bcryptjs')
const LocalStrategy = require('passport-local').Strategy
module.exports = passport => {
passport.use(
new LocalStrategy({
usernameField: 'username',
passwordField: 'password',
passReqToCallback: true
},
(req, username, password, done) => {
console.log(req.headers)
findUser(username, (err, user) => {
if (err) {
return done(err)
}
if (!user) {
return done(null, false)
}
bcrypt.compare(password, user.password, (err, isValid) => {
if (err) return done(err)
if (!isValid) return done(null, false)
return done(null, user)
})
})
}
)
)
}
The x-forwarded-for key on req in callback is undefined, so I check the headers and I saw that the x-forwarded-for is not present.
how can I get it?
`