I am using passport-local to authenticate users for my website.
passport.use('login', new LocalStrategy({
passReqToCallback : true
},
function(req, username, password, done) {
User.findOne({'local.username': username}, function(err, user) {
if(err)
return done(err);
if(!user){
console.log('User Not Found with username ');
return done(null, false);
}
if(!isValidPassword(user, password)){
console.log('Invalid Password');
return done(null, false); // redirect back to login page
}
console.log('Successfully logged in user ');
return done(null, user);
});
}
));
And this is how it routes:
router.get('/success', function(req, res){
res.send({state: 'success', user: req.user ? req.user : null});
});
router.post('/login', passport.authenticate('login', {
successRedirect: '/auth/success',
failureRedirect: '/auth/failure'
}));
router.get('/profile', function(req, res){
res.render('profile.ejs', { user: req.user });
});
This is how I am calling the above login function in a .ts file:
let data = {
username: this.username,
password: this.password
};
this.http.post('http://127.0.0.1:3000/auth/login', data).pipe(
map(res => res.json())
).subscribe(res=> {
let alert = this.alertCtrl.create({
title: 'Login Successful!',
subTitle: 'You are logged in',
buttons: ['Okay']
});
alert.present();
this.http.get('http://127.0.0.1:3000/auth/profile', res);
Here I should get all of the user's data while user logs in res, Shouldn't I? If not so then how to get all of the user's data while logging in and send it to /profile?
Hope your passport and model is configured properly.
Try something like -
module.exports = function(app, passport) {
// HOME PAGE
app.get('/', function(req, res) {
res.render('index.ejs'); // load the index.ejs file
});
// LOGIN
app.get('/login', function(req, res) {
res.render('login.ejs', { message: req.flash('loginMessage') });
});
// PROFILE SECTION
app.get('/profile', isLoggedIn, function(req, res) {
res.render('profile.ejs', {
user : req.user // get the user out of session and pass to template
});
});
};
// route middleware to make sure a user is logged in
function isLoggedIn(req, res, next) {
// user authentication in the session, carry on
if (req.isAuthenticated())
return next();
// user not authenticated, take to home page
res.redirect('/');
}
And then something like -
app.post('/login', passport.authenticate('local-login', {
successRedirect : '/profile', // redirect to profile
failureRedirect : '/login'
}));
You can try accessing user object inside your template like - something similar to <%= user.local.email %> depending on your template engine.
Related
Everyone, I am a new user and learner for express and passport, sorry for any mistakes in this post.
Currently, the below code is generating the same session cookie for all the users.
passport.use(User.createStrategy());
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
app.get("/", function(req,res) {
res.render("index");
});
app.get("/login", function(req,res) {
res.render("login");
});
app.get("/register", function(req,res) {
res.render("register");
});
app.get("/logout", function(req, res) {
req.logout();
res.redirect("/");
});
app.post("/register", function(req, res) {
//We will be using Passport-local-mongoose for all registration and authentication as a middleman for us
User.register({username: req.body.username}, req.body.password, function(err, user) {
if (err) {
console.log(err);
res.redirect("/register")
} else {
//If registered successfully, perform LOCAL Authentication - Nothing to UNDERSTAND here
passport.authenticate("local")(req, res, function(){
res.send("Done");
});
}
});
});
app.post("/login", function(req,res) {
const user = new User({
username: req.body.username,
password: req.body.password
});
//Login method from Passport
req.login(user, function(err) {
if (err) {
console.log(err);
res.redirect("/login");
} else {
passport.authenticate("local")(req, res, function(){
res.redirect("/users/" + user.username);
});
}
});
});
app.get("/users/:username", function(req,res) {
if(req.isAuthenticated()) {
User.findOne({username: req.params.username}, function(err,results) {
if(!err){
res.render("users/profile", {name: results.username});
}
});
} else {
res.redirect("/login");
}
In this code at app.post("/register"), I am able to successfully register user say xyz#gmail.com and the same user(xyz#gmail.com( can also login successfully, and upon login xyz#gmail.com their URL in their browser changes to localhost:3000/users/xyz#gmail.com and can view their profile which contains order history and map as mentioned in the code, but however there is another registered user say 123#gmail.com which tries to enter localhost:3000/users/123#gmail.com who is automatically logged in and redirected to 123#gmail.com/profile because a session is already made for the user XYZ who was successfully logged in using the login page. So I am facing a problem that if one user is authenticated that session persists for all the other registered users also.
what I want to achieve that if once the user is logged in it should have a unique session id and other registered users if they try to enter localhost:3000/users/123#gmail.com should be redirected to the login page and not automatically login.
I'm using passport.js in my app for authentication(local). I have two types of user - User and Admin. Both has passport-local-mongoose plugged in. Authentication for User was working fine. Then I applied the same authentication process to Admin.
It doesn't work neither the User which was working fine just before adding auth code to Admin. Instead of redirecting to Admin dashboard, it shows Unauthorized on the way of registering Admin.
I've found a exactly similar problem like mine here. I tried the solution given there but it gets worse. My whole app get crashed and shows some strategy.authenticate is not a function error.
So, Why this error is showing and how can I authenticate, serialize and deserialize both Admin and User in same app?
This is what I've done so far.
here is my app.js
const passport = require("passport"),
localStrategy = require("passport-local").Strategy;
const User = require("./models/user"),
Admin = require("./models/admin");
passport.use(require("express-session") ({
secret : "Wubba lubba dub dub",
saveUninitialized : false,
resave : false
}));
app.use(flash());
app.use(passport.initialize());
app.use(passport.session());
passport.use("user", new localStrategy(User.authenticate()));
passport.use("admin", new localStrategy(Admin.authenticate()));
passport.serializeUser((user, done) => {
done(null, user);
});
passport.deserializeUser(function(user, done) {
if(user!=null)
done(null,user);
});
app.use(function(req, res, next) {
res.locals.currentUser = req.user;
res.locals.error = req.flash("error");
res.locals.success = req.flash("success");
next();
});
user.js login, logout and sign up routes
router.get("/userLogin", (req, res) => {
res.render("user/userLogin");
});
router.post("/userLogin", passport.authenticate("user", {
successRedirect : "/user/1",
failureRedirect : "/userLogin",
}), (req, res)=> {
});
//user sign up handler
router.get("/signUp", (req, res) => {
res.render("user/userSignup");
});
router.post("/signUp", (req, res) => {
const newUser = new User({
firstName : req.body.firstName,
lastName : req.body.lastName,
username : req.body.username,
email : req.body.email,
gender : req.body.gender,
address : req.body.address,
});
User.register(newUser, req.body.password, (err, user) =>{
if(err) {
return res.render("user/userSignup");
}
passport.authenticate("local")(req, res, ()=> {
res.redirect("/user/1");
});
});
});
admin.js login, logout and signup routes
/admin login handler
router.get("/adminLogin", (req, res) => {
res.render("admin/adminLogin");
});
router.post("/adminLogin", passport.authenticate("admin", {
successRedirect : "/admin",
failureRedirect : "/adminLogin",
}), (req, res)=> {
});
//admin logout handler
router.get("/adminLogout", (req, res) => {
res.redirect("/");
});
// sign up
router.get("/adminSignup", (req, res) => {
res.render("signup");
});
router.post("/adminSignup", (req, res) => {
const newAdmin = new Admin({
username : req.body.username,
email : req.body.email,
});
Admin.register(newAdmin, req.body.password, (err, user) =>{
if(err) {
return res.render("signup");
}
passport.authenticate("local")(req, res, function() {
res.redirect("/admin");
});
});
});
and isLoggedIn middleware
middleware.isLoggedIn = function(req, res, next) {
if(req.isAuthenticated()) {
return next();
}
req.flash("error", "You need to be logged in first");
res.redirect("/");
};
I am using MEAN Stack and mongoose. Using passport for authentication. I want to get the currently logged in user and display his details. For example if I am logged in and if I go to the profile page I want to get my details. There were only few resources on the internet.
Login.js (passport and routes are here)
var express = require('express');
var router = express.Router();
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var User = require('../models/user');
var ConnectRoles = require('connect-roles');
router.get('/', function(req, res, next) {
res.render('Login', { title: 'Login' });
});
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 LocalStrategy(
function(username, password, done) {
User.findOne({ username: username }, function(err, user) {
if (err) { return done(err); }
if (!user) {
return done(null, false,
{ message: "No user has that username!" });
}
user.checkPassword(password, function(err, isMatch) {
if (err) { return done(err); }
if (isMatch) {
return done(null, user);
} else {
return done(null, false,
{ message: "Invalid password." });
}
});
});
}));
router.use(function(req, res, next) {
res.locals.currentUser = req.user;
res.locals.errors = req.flash("error");
res.locals.infos = req.flash("info");
next();
});
router.post("/", passport.authenticate("/", {
successRedirect: "/SubmitSurvey",
failureRedirect: "/",
session: false,
failureFlash: true
}));
router.get("/AdminDatabase", function(req, res) {
res.render('AdminDatabase', { title: 'AdminDatabase' });
});
router.get('/CreateSurvey', function(req, res, next) {
res.render('CreateSurvey', { title: 'CreateSurvey' });
});
router.get('/SubmitSurvey', function(req, res, next) {
res.render('SubmitSurvey', { title: 'SubmitSurvey' });
});
router.get('/profile', function(req, res, next) {
res.render('profile', { title: 'profile' });
});
router.get("/Logout", function(req, res) {
req.logout();
res.redirect("/");
});
module.exports = router;
How can I do this in nodejs
It's on the req.user object
router.get('/profile', function(req, res, next) {
//here it is
var user = req.user;
//you probably also want to pass this to your view
res.render('profile', { title: 'profile', user: user });
});
passport fills the req.user object with the current user through middlewares pipelines so you can extract it from there.
As Alex said, you may explicitly pass some variable (e.g. your req.user) when calling res.render:
router.get('/profile', function(req, res, next) {
res.render('profile', { title: 'profile', user: req.user });
});
Instead, maybe you'd like some variables (like that req.user) to be accessible in all calls to res.render without bothering to specify them every time? In that case, you can use res.locals, e.g. by adding this middleware:
app.use(function(req, res, next){
res.locals.user = req.user;
next();
});
And finally, for completeness -- in both of the approaches above, the variable user is available for you in the view. For example, if you're using a pug template, you may now do something like:
if user
p Hello, #{user.id}, good to see you!
else
p Please log in...
I have the following working code to authenticate through the passport-local strategy:
app.post('/api/login', passport.authenticate('local-login', {
successRedirect : '/api/login/success',
failureRedirect : '/api/login/error',
failureFlash : true
}));
app.get('/api/login/error', function(req, res) {
res.send(401, {error: req.flash('loginMessage')});
});
app.get('/api/login/success', function(req, res) {
res.send(200, {user: req.user});
});
However, ideally I want to handle the errors and success messages from one express route, and not redirect to two extra routes.
Is this possible? I tried using a 'custom callback' but that seemed to error out on serializing users for some reason.
You can use custom callback, such as:
passport.authenticate('local', function (err, account) {
req.logIn(account, function() {
res.status(err ? 500 : 200).send(err ? err : account);
});
})(this.req, this.res, this.next);
In err object you can find all needed errors, which was appeared at authentication.
Are you using Mongoose?
Try adding this to your server.js/index.js
var User = mongoose.model('User');
passport.use(new LocalStrategy(User.authenticate()));
passport.use(User.createStrategy());
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
This to your routes index.js
var auth = require('./auth');
app.post('/api/auth/login', passport.authenticate('local'),auth.login);
auth.js:
var UserModel = require('../models/user');
var User = new UserModel();
exports.login = function(req, res) {
var user = req.user;
req.login(user, function(err) {
//if error: do something
return res.status(200).json(user)
});
};
Add this to model index.js
var passportLocalMongoose = require('passport-local-mongoose');
userSchema.plugin(passportLocalMongoose, {
usernameField: 'email',
usernameLowerCase: 'true'
});
I'm making a lot of assumptions on structure and packages here. but this should work
EDIT
For custom callbacks:
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);
});
Here you instead of res.redirect you can use something like return res.status(404).json("Not Found)
See docs for more information : http://passportjs.org/guide/authenticate/
Im using NodeJS, ExpressJS, Mongoose, passportJS & connect-ensure-login. Authenticating users works perfectly.
....
var passport = require('passport')
, LocalStrategy = require('passport-local').Strategy
, ensureLoggedIn = require('connect-ensure-login').ensureLoggedIn;
var app = express();
...
app.use(passport.initialize());
app.use(passport.session());
...
passport.use(new LocalStrategy({usernameField: 'email', passwordField: 'password'},
function(email, password, done) {
User.findOne({ 'email': email, 'password': password },
{'_id': 1, 'email':1}, function(err, user) {
if (err) { return done(err); }
if (!user) {
return done(null, false, { message: 'Incorrect username.' });
}
return done(null, user);
});
}));
passport.serializeUser(function(user, done) {
done(null, user);
});
passport.deserializeUser(function(user, done) {
done(null, user);
});
app.post('/login', passport.authenticate('local',
{ successReturnToOrRedirect: '/home', failureRedirect: '/login' }));
app.get('/logout', function(req, res){
req.logout();
res.redirect('/');
});
Now, I want to add restrictions to some routes to be accessible only by admin. How can I do that? e.g. /admin/*
var schema = new mongoose.Schema({
name: String,
email: String,
password: String,
isAdmin: { type: Boolean, default: false }
});
mongoose.model('User', schema);
Any hint? Thanks
You could attach a custom middleware to the /admin/* route that would check for admin status before passing the request on the any of the more specific /admin/ routes:
var ensureLoggedIn = require('connect-ensure-login').ensureLoggedIn;
...
var requiresAdmin = function() {
return [
ensureLoggedIn('/login'),
function(req, res, next) {
if (req.user && req.user.isAdmin === true)
next();
else
res.send(401, 'Unauthorized');
}
]
};
app.all('/admin/*', requiresAdmin());
app.get('/admin/', ...);
//Add following function to your app.js above **app.use(app.router)** call;
//This function will be called every time when the server receive request.
app.use(function (req, res, next) {
if (req.isAuthenticated || req.isAuthenticated())
{
var currentUrl = req.originalUrl || req.url;
//Check wheather req.user has access to the above URL
//If req.user don't have access then redirect the user
// to home page or login page
res.redirect('HOME PAGE URL');
}
next();
});
I have not tried it but i think it will work.