I test my routes in Advanced Rest Client, and with my code the output is 401, Unauthorized. I don't understand why this is happening.
I packaged my authentication in one module. Then, I invoke it in my server file with wagner-core(dependency injector):
wagner.invoke(require('./passport-init'),{ app: app })
passport.js:
'use strict'
const bCrypt = require('bcryptjs')
const passport = require('passport')
const LocalStrategy = require('passport-local').Strategy
const session = require('express-session')
module.exports = (User, app) => {
passport.serializeUser((user, done) => {
done(null, user._id)
})
passport.deserializeUser((id, done) => {
User.findOne({ _id: id }).exec(done)
})
passport.use('login', new LocalStrategy({ passReqToCallback: true }, (req, username, password, done) => {
User.findOne({ username: username }, (err, user) => {
if (err) { return done(err) }
if (!user) { return done(null, false, { message: 'Invalid username' }) }
if (!isValidPassword(user, password)) {
return done(null, false, { message: 'Invalid password' })
}
return done(null, user)
})
}))
app.use(session({
secret: process.env.SESSION_SECRET || 'secret',
resave: false,
saveUninitialized: false
}))
app.use(passport.initialize())
app.use(passport.session())
app.post('/login', passport.authenticate('login'), (req, res) => {
res.redirect('/users/' + req.user.username)
})
}
function isValidPassword (user, password) {
return bCrypt.compareSync(password, user.password)
}
I figured it out. It was something to do with my routes, and isValidpassword function.
Heres the amended code:
'use strict'
const bCrypt = require('bcryptjs')
const passport = require('passport')
const LocalStrategy = require('passport-local').Strategy
const session = require('express-session')
module.exports = (User, app) => {
passport.serializeUser((user, done) => {
done(null, user._id)
})
passport.deserializeUser((id, done) => {
User.findById(id, (err, user) => {
done(err, user)
})
})
passport.use('login', new LocalStrategy({ passReqToCallback: true }, (req, username, password, done) => {
process.nextTick(() => {
User.findOne({ username: username }, (err, user) => {
if (err) { return done(err) }
if (!user) { return done(null, false, { message: 'Invalid username' }) }
if (!user.password) {
bCrypt.compareSync(password, user.password)
return done(null, false, { message: 'Invalid password' })
}
return done(null, user)
})
})
}))
passport.use('signup', new LocalStrategy({ passReqToCallback: true }, (req, username, password, done) => {
process.nextTick(() => {
User.findOne({ username: username }, (err, user) => {
if (err) { return done(err) }
if (user) {
return done(null, false, { message: 'User already exists' })
} else {
let newUser = new User()
newUser.username = req.body.username
newUser.password = createHash(req.body.password)
newUser.save((err) => {
if (err) throw err
return done(null, newUser)
})
}
})
})
}))
app.use(session({
secret: 'secret',
resave: false,
saveUninitialized: false
}))
app.use(passport.initialize())
app.use(passport.session())
app.get('/success', (req, res) => {
res.send({ state: 'success', user: req.user ? req.user : null })
})
app.post('/login', passport.authenticate('login', {
successRedirect: '/success',
failureRedirect: '/fail'
}))
app.post('/signup', passport.authenticate('signup', {
successRedirect: '/success',
failureRedirect: '/fail'
}))
}
function createHash (password) {
return bCrypt.hashSync(password, bCrypt.genSaltSync(10), null)
}
Related
I am using passport for authentication. The code doesn't giving any errors but does nothing when I use the right credentials. I tried console log in the authenticateUser function and serializeUser function, it does print statements in both.
My passportConfig.js file
const LocalStrategy = require('passport-local').Strategy;
const db = require('../postgresql');
const bcrypt = require('bcrypt');
function initialize(passport) {
const authenticateUser = async (email, password, done) => {
try {
const user = await db.oneOrNone('SELECT * FROM users WHERE email = $1', [email]);
if(user) {
if(!bcrypt.compareSync(password, user.password)) {
return done(null, false, { message: "Email or password is incorrect"});
}
else {
console.log('Authenticated user');
return done(null, user);
}
}
else {
return done(null, false, { message: "Email or password is incorrect"});
}
}
catch (err) {
console.log(err);
}
}
passport.use(
new LocalStrategy({
usernameField: 'email',
passwordField: 'password'
}, authenticateUser
)
);
passport.serializeUser((user, done) => {
console.log('Serialized user');
done(null, user.id)
});
passport.deserializeUser(async (id, done) => {
try {
const user = await db.oneOrNone('SELECT * FROM users WHERE id = $1', [id]);
return done(null, user);
}
catch(err) {
console.log(err);
}
});
}
module.exports = initialize;
Snippet of my route file
router.post('/login', passport.authenticate('local', {
successRedirect: '/',
failureRedirect: '/login',
failureFlash: true
}));
Create a new type of login for a different type of user (another list in the database), the login succeeds but it doesn't serialize me grow and then show it (just like it does for user). Any idea what it could be ?
Passport Config:
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
var User = require('../model/User')();
var Grow = require('../model/Grow')();
passport.use('local', new LocalStrategy({
usernameField: 'email'
}, async (email, password, done) => {
// Match Email User
const user = await User.findOne({ email: email });
if (!user) {
return done(null, false, { message: 'No se encontro el usuario' });
} else {
// Match Password User
const match = await user.matchPassword(password);
if (match) {
return done(null, user);
} else {
return done(null, false, { message: 'ContraseƱa incorrecta' });
}
}
}));
passport.serializeUser((user, done) => {
done(null, user.id);
});
passport.deserializeUser((id, done) => {
User.findById(id, (err, user) => {
done(err, user);
});
});
passport.use('growlocal', new LocalStrategy({
usernameField: 'email'
}, async (email, password, done) => {
const grow = await Grow.findOne({ email: email });
if (!grow) {
return done(null, false, { message: 'No se encontro el usuario' });
} else {
const match = await grow.matchPassword(password);
if (match) {
return done(null, grow);
} else {
return done(null, false, { message: 'ContraseƱa incorrecta' });
}
}
}));
passport.serializeUser((grow, done) => {
console.log(grow)
done(null, grow.id);
});
passport.deserializeUser((id, done) => {
console.log(grow)
Grow.findById(id, (err, grow) => {
done(err, grow);
});
});
Router Config:
// Login Grow
router.get('/grows/signin', (req, res) => {
res.render('growlogin');
});
router.post('/grows/signin', passport.authenticate('growlocal', {
successRedirect: '/',
failureRedirect: '/grows/signin',
failureFlash: true
}));
EJS:
<% if (grow){ %>
Gato
<%}%>
Error:
If anyone has any idea how to fix it, please let me know. It is very important for the development of my application. Thank you very much <3
How use nuxt auth Module (front-end) with passport-local using JWT (back-end express) ?
defining jwt strategy for verify jwt token (express)
var JwtStrategy = require('passport-jwt').Strategy,
ExtractJwt = require('passport-jwt').ExtractJwt;
var opts = {}
opts.jwtFromRequest = ExtractJwt.fromAuthHeaderAsBearerToken();
opts.secretOrKey = 'secret';
opts.issuer = 'accounts.examplesoft.com';
opts.audience = 'yoursite.net';
passport.use(new JwtStrategy(opts, function(jwt_payload, done) {
User.findOne({id: jwt_payload.sub}, function(err, user) {
if (err) {
return done(err, false);
}
if (user) {
return done(null, user);
} else {
return done(null, false);
// or you could create a new account
}
});
}));
defining local strategy for verify username nad password (express)
passport.use(new LocalStrategy(
function(username, password, done) {
User.findOne({ username: username }, function (err, user) {
if (err) { return done(err); }
if (!user) { return done(null, false); }
if (!user.verifyPassword(password)) { return done(null, false); }
return done(null, user);
});
}
));
code for issuing token after verifying username and password (expresss)
app.post('/login',
passport.authenticate('local', { failureRedirect: '/login' }), //need to update from nuxt auth.
function(req, res) {
res.redirect('/');
});
nuxt auth local strategy consume username and passsword returns a JWT token (nuxt)
this.$auth.loginWith('local', {
data: {
username: 'your_username',
password: 'your_password'
}
})
It can work independently how do i combine these ?
code for express
Create passport strategies
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
const JwtStrategy = require('passport-jwt').Strategy;
passport.use(
new LocalStrategy(
{
usernameField: 'username',
passwordField: 'password'
},
function(username, password, done) {
users.findOne({ email: username }, function(err, user) {
if (err) {
return done(err);
}
if (!user) {
return done(null, false, { error: 'Invalid username' });
}
if (!user.checkPassword(password)) {
return done(null, false, { error: 'invalid password' });
}
const info = { scope: '*' };
done(null, user, info);
});
}
)
);
const opts = {};
opts.jwtFromRequest = ExtractJwt.fromAuthHeaderAsBearerToken();
opts.secretOrKey = 'JWT_SECRET_OR_KEY';
passport.use(
new JwtStrategy(opts, function(payload, done) {
users.findById(payload, function(err, user) {
if (err) {
return done(err, false);
}
if (user) {
return done(null, user);
}
return done(null, false);
});
})
);
use passport strategies
const express = require('express');
const passport = require('passport');
const app = express();
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(passport.initialize()); // Used to initialize passport
// Routes
app.post(
'/login',
passport.authenticate('local', { session: false }),
function(req, res) {
const token = jwt.sign(req.user.userId, 'JWT_SECRET_OR_KEY');
return res.json({ token });
}
);
app.get(
'/me',
passport.authenticate(['jwt', 'bearer'], { session: false }),
function(req, res, next) {
const { userId } = req.user;
users.findOne({ _id: userId }, (err, data) => {
if (err) {
res.status(500).send(err);
} else if (data) {
const userData = data;
res.status(200).send(userData);
} else {
res.status(500).send('invalid token');
}
});
}
);
configuration for nuxt
inside nuxt.config.js
auth: {
resetOnError: true,
redirect: {
login: '/login', // User will be redirected to this path if login is required.
home: '/app/dashboard', // User will be redirect to this path after login. (rewriteRedirects will rewrite this path)
logout: '/login', // User will be redirected to this path if after logout, current route is protected.
user: '/user/profile',
callback: '/callback // User will be redirect to this path by the identity provider after login. (Should match configured Allowed Callback URLs (or similar setting) in your app/client with the identity provider)
},
strategies: {
local: {
endpoints: {
login: {
url: '/login',
method: 'post',
propertyName: 'token'
},
logout: false,
user: {
url: '/me',
method: 'GET',
propertyName: false
}
},
tokenRequired: true,
tokenType: 'Bearer'
}
}
inside Login .vue
this.$auth
.loginWith('local', {
data: {
username: this.user.email,
password: this.user.password
}
})
.catch(err => {
console.error(err );
});
My signup and login works completely fine until I want to return user to the front end. User ends up being undefined.
Here is my passport.js
const passport = require('passport');
const localStrategy = require('passport-local').Strategy;
const mongoose = require('mongoose');
const User = mongoose.model('users');
passport.serializeUser((user, done) => {
done(null, user._id)
})
passport.deserializeUser((id, done) =>
User.findById(id).then((user) => {
if (user) {
done(null, user)
} else {
}
})
);
passport.use(new localStrategy((username, password, done) => {
User.findOne({ username: username }, (err, user) => {
console.log(user)
if (err) { return done(err); }
if (!user) {
return done(null, false, { message: 'Username not found' });
}
if (!user.comparePassword(password, user.password)) {
return done(null, false, { message: 'Incorrect password.' });
}
return done(null, user);
});
}));
Here is my login route:
const passport = require('passport');
const mongoose = require('mongoose');
const User = mongoose.model('users');
module.exports = (app) => {
app.get('/test', (req, res) => {
res.send('elo')
})
app.post('/login',
passport.authenticate('local', {
successRedirect: '/loginSuccess',
failureRedirect: '/loginFailed',
})
);
app.get('/loginSuccess', (req, res) => {
console.log(req.user)
res.send({ success: true, test:'test', user: req.user })
})
app.get('/loginFailed', (req, res) => {
res.send({ success: false, error: "Incorrect credentials" })
})
};
In passport.js the user exists and should be returnet correctly. It's just getting lost somewhere along the way. Whats funnier, I used the exact same code in my other app few months ago and it worked properly.
Edit:
Turns out it works on postman, so I dont know whats going on now
I have a problem with passport.js, when I try to log into my account, I get an error: Error: Unknown authentication strategy "local-login". ". What's wrong with my code, thank you.
config/Passport.js
var passport = require('passport');
var request = require('request');
var LocalStrategy = require('passport-local').Strategy;
var User = require('../models/user'); // model 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('local-login', new LocalStrategy(function(username, password,
done) {
User.findOne({ username: username }, function(err, user) {
if (err) { return done(err); }
if (!user) {
return done(null, false, { msg: "Username" + username + "not found."
});
}
user.comparePassword(password, function(err, isMatch) {
if (err) { return done(err); }
// Make sure the user has been verified
if (isMatch) {
return done(null, user);
}
return done(null, false, { msg: 'Invalid email or password.' });
});
});
}));
app.js
var session = require('express-session');
var passport = require('passport');
app.use(session({
secret: config.secret,
resave: true,
saveUninitialized: true,
cookie: { maxAge: 1*15*1000 }
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(function(req, res, next) {
res.locals.user = req.user;
next();
});
routes/authRoutes.js
app.post('/login', function(req, res, next) {
passport.authenticate('local-login', function(err, user, info) {
if (err) { return next(err); }
if (!user) {
return res.redirect('/login');
}
req.login(user, function(err) {
if (err) { return next(err); }
res.redirect('/');
});
})(req, res, next);
});
It must be 'local' instead of 'local-login'
module.exports.login_post = passport.authenticate('local', {
successRedirect: '/',
failureRedirect: '/',
failureFlash: true
});
I Use MySQL. It's the complete code:
passport.use(new LocalStrategy({
passReqToCallback: true
}, function(req, username, password, done) {
pool.query("SELECT * FROM user WHERE username = ?",[username], function(err, rows, fields) {
if (err) throw err;
console.log('checked');
if(!isExist(username) || !isExist(password)){
return done(null, false, req.flash('message_err', 'Username and password cant be emptied!.'));
}
if (!rows[0]) {
return done(null, false, req.flash('message_err', 'Oops! Username or password didnt match.'));
}
if (!bcrypt.compareSync(password, rows[0].password)) {
return done(null, false, req.flash('message_err', 'Oops! Username/password didnt match.'));
}
return done(null, rows[0]);
});
}));
passport.deserializeUser(function(user, done) {
console.log('user : ' + user);
pool.query("SELECT * FROM user WHERE username = ?", [user], function(err, rows, fields) {
if(err) throw err;
console.log('deserialized');
done(err, rows[0]);
});
});
//serialize and deserialize passport
passport.serializeUser(function(req, user, done) {
console.log('serialized');
done(null, user.username, req.flash('message_success', 'Welcome, '+user.username + "!"));
});
module.exports.login_post = passport.authenticate('local', {
successRedirect: '/',
failureRedirect: '/',
failureFlash: true
});