passport.js how to make Multiple req.user - javascript

In my app there are two types of users (seller and buyer) Authentication works fine but I am not able to create seperate req.user so that i can use them in my ejs files, I am new to coding thankyou for helping me out.
both users are diffrent in database but for session they are the same user.
app.js
passport.use('userLocal', new LocalStrategy(User.authenticate()));
passport.use('sellerLocal', new LocalStrategy(Seller.authenticate()));
passport.serializeUser(function (user, done) {
done(null, user);
});
passport.deserializeUser(function (user, done) {
if (user!=null)
done(null, user);
});
app.use((req, res, next) => {
res.locals.currentUser=req.user;
res.locals.success=req.flash('success');
res.locals.error=req.flash('error');
next();
})
Seller.js
route.post('/register/seller', catchAsync(async (req, res, next) => {
try {
const { proprietorname, companyname, address, contactnumber, email, username, password }=req.body;
const seller=new Seller({ proprietorname, companyname, address, contactnumber, email, username });
const registeredSeller=await Seller.register(seller, password);
req.login(registeredSeller, err => { //after registering it logins the registered user
if (err) return next(err);
req.flash('success', 'SELLER LOGIN');
res.redirect('/products');
})
} catch (e) {
req.flash('error', e.message);
res.redirect('/register/seller')
}
}));
route.get('/login/seller', (req, res) => {
res.render('users/sellerLogin')
})
route.post('/login/seller', passport.authenticate('sellerLocal', { failureFlash: true, failureRedirect: '/login/seller', keepSessionInfo: true, }), (req, res) => { //a authentication middleware by passport you can add google fb twiiter too insted of just local
req.flash('success', 'yooooo');
const redirectUrl=req.session.returnTo||"/products";
delete req.session.returnTo;
res.redirect(redirectUrl);
});
user.js
route.post('/register/buyer', catchAsync(async (req, res, next) => {
// res.send(req.body);
try {
const { email, username, password }=req.body;
const user=new User({ email, username });
const registeredUser=await User.register(user, password); //registering user
req.login(registeredUser, err => { //after registering it logins the registered user
if (err) return next(err);
req.flash('success', 'Welcome to SnapBuy');
res.redirect('/products');
})
} catch (e) {
req.flash('error', e.message);
res.redirect('/register/buyer')
}
}));
route.get('/login/buyer', (req, res) => {
res.render('users/buyerLogin')
})
route.post('/login/buyer', passport.authenticate('userLocal', { failureFlash: true, failureRedirect: '/login/buyer', keepSessionInfo: true, }), (req, res) => { //a authentication middleware by passport you can add google fb twiiter too insted of just local
req.flash('success', 'Welcome Back');
const redirectUrl=req.session.returnTo||"/products";
delete req.session.returnTo;
res.redirect(redirectUrl);
});
route.get('/logout', (req, res, next) => {
req.logout();
req.flash('success', "Goodbye!");
res.redirect('/products');
});

Related

Passport only redirect "failureRedirect: '/login?fail=true'"

I'm using Passport js local strategy but I can't redirect from my admin page. it always fails even if the login and password are correct, below is the auth.js and login.js code
login.js
router.get('/', (req, res, next) =>{
if (req.query.fail){
res.render('admin/login', {layout: 'admin.hbs', message: "Usuario e/ou Senha invalidos"});
}else{
res.render('admin/login', {layout: 'admin.hbs', message: null});
}
})
router.post('/',
passport.authenticate('local', { failureRedirect: '/login?fail=true' }),
function(req, res) {
res.redirect('/admin');
});
auth.js
const users = [{
_id: 123,
username: "adm",
password: hashedPassword
}];
console.log(users);
module.exports = function(passport){
function findUser(username){
return users.find(item => item.username === username);
}
function findUserById(id){
return users.find(item => item._id === id);
}
passport.serializeUser((user, done) => {
done(null, user._id);
});
passport.deserializeUser((id, done) => {
try {
const user = findUserById(id);
done(null, user);
} catch (err) {
console.log(err);
return done(err, null)
}
});
passport.use(new localStrategy({
usernameField: 'username',
passwordField: 'password',
},
(username, password, done) => {
try{
const user = findUser(username).then(user);
if(!user) return done(null, false);
const isValid = bcrypt.compare(password, user.password);
if(!isValid) return done(null, false);
return done(null, user);
}
catch(err){
console.log(err);
return done(err, false)
}}));
}
I don't know why it's not working, I wanted help getting into the admin page

Node jS express Authenticate facebook API

hello i new in backend and want to make a Authenticate facebook api with node js using express and i use passport but its not work and give me a page of html code as a response to sign in with facebook account this can handle when use web page the api may use with mobile application
my passport file that i use
const LocalStrategy = require('passport-local').Strategy;
const bcrypt = require('bcryptjs');
const passport = require('passport')
const FacebookStrategy = require('passport-facebook').Strategy;
// Load User model
const User = require('../Schema/user');
// ---------------- Local Auth -------------- //
passport.use(
new LocalStrategy({ usernameField: 'email' },
(email, password, done) => {
// Search For Match user
User.findOne({ email: email }).then(user => {
if (!user) {
console.log("That email is not registered")
return done(null, false, { message: 'That email is not registered' });
}
// Compare the Two Password password
bcrypt.compare(password, user.password, (err, isMatch) => {
// if (err) throw err;
if (err) {
console.log(err)
return done(err);
}
if (isMatch) {
console.log("matching email");
return done(null, user);
} else {
console.log("Password incorrect");
return done(null, false, { message: 'Password incorrect' });
}
});
});
})
);
//------------------ Facebook Auth ---------------//
passport.use(new FacebookStrategy({
clientID: process.env.FACEBOOK_APP_ID,
clientSecret: process.env.FACEBOOK_APP_SECRET,
ccallbackURL: "/auth/facebook/callback",
profileFields: ['id', 'emails', 'name'],
},
async (accessToken, refreshToken, profile, done) => {
try {
const userData = {
firstName: profile._json.first_name.toLowerCase(),
lastName: profile._json.last_name.toLowerCase(),
email: profile._json.email,
isConfirmed: true,
};
// const user = await userService.registerWithThirdParty(userData);
done(null, user);
} catch (error) {
console.error(error.message);
done(null, false);
}
}
));
passport.serializeUser(function (user, done) {
done(null, user.id);
});
passport.deserializeUser(function (id, done) {
User.findById(id, function (err, user) {
done(err, user);
});
});
module.exports = passport;
my index.js file
router.get("/auth/facebook", passport.authenticate("facebook"));
router.get("/auth/facebook/callback",
function (req, res, next) {
passport.authenticate('facebook', function (err, user, info) {
if (err) { return next(err); }
if (!user) { return res.json({ message: info.message }) }
req.logIn(user, function (err) {
if (err) { return next(err); }
return res.json({ msg: "succes Login", user: user });
});
})(req, res, next);
}
);
when i use local signup or login it work but when i use facebook login dont work and give me a full html to sign in and i cant handled it in my api.
hint : i use passport-facebook
you can use this script to make authentication to facebook + passport js:
user.controller.js
import passport from "passport";
import dotenv from "dotenv";
import strategy from "passport-facebook";
import userModel from "../user/user.model";
const FacebookStrategy = strategy.Strategy;
dotenv.config();
passport.serializeUser(function(user, done) {
done(null, user);
});
passport.deserializeUser(function(obj, done) {
done(null, obj);
});
passport.use(
new FacebookStrategy(
{
clientID: process.env.FACEBOOK_CLIENT_ID,
clientSecret: process.env.FACEBOOK_CLIENT_SECRET,
callbackURL: process.env.FACEBOOK_CALLBACK_URL,
profileFields: ["email", "name"]
},
function(accessToken, refreshToken, profile, done) {
const { email, first_name, last_name } = profile._json;
const userData = {
email,
firstName: first_name,
lastName: last_name
};
new userModel(userData).save();
done(null, profile);
}
)
);
user.router.js
import express from "express";
import passport from "passport";
import userController from "./user.controller";
const userRouter = express.Router();
userRouter.get("/auth/facebook", passport.authenticate("facebook"));
userRouter.get(
"/auth/facebook/callback",
passport.authenticate("facebook", {
successRedirect: "/", // to add check you can use this value successRedirect also the next value failureRedirect
failureRedirect: "/fail"
})
);
userRouter.get("/fail", (req, res) => {
res.send("Failed attempt");
});
userRouter.get("/", (req, res) => {
res.send("Success");
});
export default userRouter;
index.js
import express from "express";
import { json } from "body-parser";
import passport from "passport";
import { connect } from "./utils/db";
import userRouter from "./user/user.routes";
const app = express();
const port = 3000;
app.use(passport.initialize());
app.use(json());
app.use("/", userRouter);
app.listen(port, async () => {
await connect();
console.log(`Server listening on ${port}`);
});

req.isAuthenticated() never evaluates to true

I'm trying to implement user authentication as below:
userRouter.post("/login", passport.authenticate("local", { session: false }), (req, res) => {
if (req.isAuthenticated()) {
const { _id, username } = req.user;
const token = signToken(_id);
res.cookie("access_token", token, { httpOnly: true, sameSite: true });
res.status(200).json({ isAuthenticated: true, user: { username } });
}
});
But to be able to add some custom messages I'm using the alternative below:
userRouter.post('/login', (req, res, next) => {
passport.authenticate('local',{ session: false }, (err, user, info) => {
if (req.isAuthenticated()) {
const { _id, username } = req.user;
const token = signToken(_id);
res.cookie("access_token", token, { httpOnly: true, sameSite: true });
res.status(200).json({ isAuthenticated: true, user: { username } });
}
if (err) return next(err)
if (info)
res.status(400).json({ message: { msgBody: info.message, msgError: true } });
})(req, res, next);
});
However, in the second alternative, it seems like req.isAuthenticated() is never evaluated to true.
Can anyone help me understand why?
Thanks
The passport docs say "Note that when using a custom callback, it becomes the application's responsibility to establish a session (by calling req.login()) and send a response." (http://www.passportjs.org/docs/authenticate/)
With the follow code as an example:
app.get('/login', function(req, res, next) {
passport.authenticate('local', 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); }
return res.redirect('/users/' + user.username);
});
})(req, res, next);
});
I wonder if it says you are not authenticated because you need to call the login method?

req.user not defined when calling from android application

I am making an android app in partnership with a colleague, he is an Android developer and I know very little about android dev. I do the backend stuff, I made the login and auth using node.js, express, and passport.js.
I hosted the server locally and used postman to check the auth and registration processes, all were working fine. I am getting the status codes my friend wanted for his Front-end. In the authentication part using passport.js when success I am passing req.user which should return the user body, so that my friend on the Front-end can use the field user.firstName from user object to display a welcome message.
Through Postman, the user body is getting defined and I am getting a user object with all fields in the Postman window, but through the app it is giving an error.
firstName is undefined property.
Passport.js logic:
const LocalStrategy = require('passport-local').Strategy;
const mongoose = require('mongoose');
const bcrypt = require('bcryptjs');
//load user model
const User = require('../models/UserSchema');
module.exports = function(passport){
passport.use(
new LocalStrategy({usernameField: 'roll'}, (roll, password, done) => {
//find user
User.findOne({roll: roll})
.then(user =>{
if(!user){
return done(null, false, {message: 'Roll number not registered'});
}
//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: 'Password incorrect'});
}
})
})
.catch(err => console.log(err));
})
);
/*passport.serializeUser( function(id, done) {
done(null, User.roll);
});
passport.deserializeUser(function(id, done){
User.findById(roll, function(err, user){
done(err, user);
});
});*/
passport.serializeUser(function(user, done) {
done(null, user);
});
passport.deserializeUser((_id, done) => {
User.findById( _id, (err, user) => {
if(err){
done(null, false, {error:err});
} else {
done(null, user);
}
});
});
}
Login Route:
//Login Handle
router.post('/login', (req, res, next) =>{
console.log('/user/login')
passport.authenticate('local', {
successRedirect: '/success',
failureRedirect: '/failure',
session: true,
failureFlash: false
})(req, res, next);
//res.json(pass.user.name);
});
/success route:
router.get('/success', (req, res) => {
console.log(req);
let message = 'Login Succesful';
//let user = req.user.firstName
res.status(200).json({'message':message, 'user': req.user.firstName});
})
I guess you are also using body-parser or express.json() to parse the incoming body request to JSON. If this is the case you should send the response back like this:
req.body.user.firstName
For POST requests: req.body
For GET parameters: req.params
For GET query strings: req.query

how to send error message to client?

I am using passport with local strategy .but I want to send message and status when credential is not match or (user is not exit is DB)
here is code
router.js
const passport = require('passport');
const passportConfig = require('../passport')
const passportSignIn = passport.authenticate('local', { session: false });
router.route('/login',)
.post(passportSignIn,controller.login)
on controller file
login: async (req, res, next) => {
console.log(req.body);
res.json({status:200})
}
passport.js
passport.use(new LocalStrategy({
usernameField: 'email'
}, async (email, password, done) => {
const user = await db.User.findOne({where: {email: email}});
if (!user) {
return done(null, false,{message:"No user exit"});
}
const isMatch = await bcrypt.compare(password, user.dataValues.password);
console.log(isMatch, 'isMatch');
if (!isMatch) {
return done(null, false);
}
// Otherwise, return the user
done(null, user);
}))
Client code
when user click on login button it goes to /login path first it goes to passportSignIn function or below function.
`new LocalStrategy({
usernameField: 'email'
}, async (email, password, done) => {`
now if user not found I want to send this message on the client as the response ("No user exit")
return done(null, false,{message:"No user exit"});
You have to update your login controller, like so:
login: (req, res, next) => {
console.log(req.body);
passport.authenticate('yourStrategy', function(err, user, info) {
if (err) {
return res.status(500).json("Internal Server Error");
}
if (!user) {
// This 'info' variable below would be - { message: "No user exit" }
// as you passed in the done() callback as the third param
return res.status(404).json(info.message);
}
}
}

Categories