I'm trying to use express session to login users. I'd like users to be able to go to a profile page and view their user data if they have logged in.
I've been stuck here for days. On line 33 of my routes.js file, in my /profile GET route, req.user is undefined. But on line 27 of my routes.js, in my /login POST, req.user works as it should.
'use strict'
var User = require('mongoose').model('User')
module.exports = function(app, passport){
console.log('passport', passport)
app.route('/')
.get(function(req, res){
res.render('index')
})
app.get('/signUp', function(req, res){
res.render('signup')
})
app.route('/user')
.get(function(req, res){
})
.post(passport.authenticate('local-signup', { successRedirect: '/',
failureRedirect: 'signup' }))
app.route('/login')
.get(function(req, res){
res.render('login')
})
.post(passport.authenticate('local-login', { successRedirect: '/',
failureRedirect: '/login'}), function(req, res){
/* *** LINE 27 *** */ console.log('req.user', req.user)
})
app.route('/profile')
.get(function(req, res){
/* *** LINE 33 *** */ console.log('req.user', req.user)
if(!req.user){
res.render('profile', {user: "You're not logged in"})
}
if(req.user){
res.render('profile', {user: req.user})
}
})
}
Why isn't req.user defined in all my routes? Shouldn't express session populate a persisting req.user object?
Any help appreciated. Thanks!
You should define isLoginedIn funtion in routes.js as follow:
// route middleware to ensure user is logged in
function isLoggedIn(req, res, next) {
if (req.isAuthenticated())
return next();
res.redirect('/');
}
Then replace:
app.route('/profile')
.get(function(req, res){
console.log('req.user', req.user)
if(!req.user){
res.render('profile', {user: "You're not logged in"})
}
if(req.user){
res.render('profile', {user: req.user})
}
})
by:
// PROFILE SECTION =========================
app.get('/profile', isLoggedIn, function(req, res) {
res.render('profile.ejs', {
user : req.user
});
});
Related
I am trying to flash the message "Welcome back "username here" " to a user once they have successuly logged in to the website.
The problem is that logging in with passport is not a regular request and response, the authentication happens as an argument to the post request. Below you can find my code:
var express = require("express");
var router = express.Router();
var user = require("../models/user");
var passport = require("passport");
router.get('/register', (req,res) =>{
res.render('register');
});
router.post('/register', (req,res) =>{
user.register(
new user({username: req.body.username}),
req.body.password,
(err, newUser) => {
if(err){
req.flash("error", err.message);
return res.redirect("/register");
}
passport.authenticate("local")(req, res, function(){
req.flash("success", "Successfully registered, welcome "+user.username.charAt(0).toUpperCase() + user.username.slice(1)+"!");
res.redirect("/");
});
}
);
});
router.get('/login', (req,res) =>{
res.render('login');
});
router.post('/login', passport.authenticate("local",{
successRedirect: "/",
failureRedirect: "/login",
failureFlash: true,
successFlash: 'Welcome back!'//HERE IS WHERE I AM INTERESTED
}), (req,res) =>{
});
router.get('/logout', (req,res) =>{
req.logout();
req.flash("success", "Successfully Logged Out")
res.redirect("/");
});
module.exports = router;
In the second argument to router.post, call passport.authenticate to handle the failureRedirect and failureFlash message. Then, for the third argument, write your callback function with req and res. In the body of this function is where you'll handle the "success" flash message and you'll have access to your username on the request object. And then you can do your res.redirect.
router.post(
"/login",
passport.authenticate("local", {
failureRedirect: "/login",
failureFlash: true
}),
(req,res) => {
req.flash("success", "Welcome back!"//add your username variable here);
res.redirect("/home");
});
This works perfectly fine in the server.js:
app.get('/auth/google/callback',
passport.authenticate('google', {
failureRedirect: '/login'
}),
(req, res) => {}
);
But the following doesn't when used in route.js:
exports.googleCallback = function(req, res, next) {
passport.authenticate('google', { failureRedirect: '/login' });
const handler = function(req, res) {
// Successful authentication, redirect home.
res.redirect('/');
};
handler(req, res, next);
};
I have the following in route.js:
app.route(path + 'auth/google').get(auth.googleLogin);
What happens:
The second code directly goes to / path without waiting for Passport Google strategy to completely execute.
If I remove res.redirect('/'); It does not go anywhere and keep loading.
This worked just fine:
exports.googleCallback = function(req, res, next) {
passport.authenticate('google', { failureRedirect: '/login' })(req, res, next);
};
Added callback method on the passport.
I'm using React Router with Passport.js to set up Facebook login. I've set up the express routes and passport config, but every time I hit the
<a href="/api/auth/facebook"> link on my client side, it makes a request to RR because of my express app with this line:
app.get('/*', function(req, res) {
res.sendFile(path.resolve(__dirname, '../client', 'build', 'index.html'))
});
As I am making a call to the server side route, it returns this error:
Warning: [react-router] Location "/api/auth/facebook" did not match any routes
How can I bypass React Router for this one particular route?
my user_routes.js file looks like:
'user strict';
var bodyparser = require('body-parser');
var User = require('../models/User.js');
module.exports = function loadUserRoutes(router, passport) {
router.use(bodyparser.json());
router.get('/auth/facebook', passport.authenticate('facebook', {
session: false,
successRedirect: '/chat',
failureRedirect: '/'
}));
router.get('/auth/facebook/callback', passport.authenticate('facebook', {
session: false,
successRedirect: '/chat',
failureRedirect: '/'
}));
router.post('/sign_up', passport.authenticate('local-signup', { session: false}), function(req, res) {
res.json(req.user);
});
router.post('/sign_in', passport.authenticate('local-login', { session: false}), function(req, res) {
res.json(req.user);
});
router.get('/signout', function(req, res) {
req.logout();
res.end();
});
//get auth credentials from server
router.get('/load_auth_into_state', function(req, res) {
res.json(req.user);
});
// get usernames for validating whether a username is available
router.get('/all_usernames', function(req, res) {
User.find({'local.username': { $exists: true } }, {'local.username': 1, _id:0}, function(err, data) {
if(err) {
console.log(err);
return res.status(500).json({msg: 'internal server error'});
}
res.json(data);
});
})
};
In express routes are matches in the order they get defined.
So before your /* route you need something to handle api requests.
app.get('/api/auth/facebook', passport.authenticate('facebook'))
app.get('/*', function(req, res) {
res.sendFile(path.resolve(__dirname, '../client', 'build', 'index.html'))
});
I am trying to write a unit-test for the authentication route of my web application. For some reason, it times out. What is more, the test user is not created in the database. What am I doing wrong? Should I be specifying the database connection as well?
Here is the code of the test:
var user;
var mongoose = require("mongoose");
var userSchema = require("../../models/user.js");
var User = mongoose.model("User", userSchema);
var request = require("supertest");
var server = request.agent("http://localhost:3000");
describe('User', function () {
beforeEach(function(done) {
user = new User({
email : "user#user.com",
firstName: "Full Name",
lastName : "Last Name",
password : "pass11"
});
user.save(done)
});
describe('Login test', function () {
it('should redirect to /', function (done) {
agent
.post('/login')
.field('email', 'user#user.com')
.field('password', 'pass11')
.expect('Location','/')
.end(done)
})
afterEach(function(done) {
User.remove().exec();
return done();
});
});
})
routes/index.js
//module.exports = router;
var express = require('express');
var router = express.Router();
module.exports = function(passport){
var isAuthenticated = function (req, res, next) {
// if user is authenticated in the session, call the next() to call the next request handler
// Passport adds this method to request object. A middleware is allowed to add properties to
// request and response objects
if (req.isAuthenticated()){
//console.log(next());
return next();
}
// if the user is not authenticated then redirect him to the login page
res.redirect('/login');
}
/* GET login page. */
router.get('/login', function(req, res) {
// Display the Login page with any flash message, if any
res.render('login', { message: req.flash('message') });
});
/* Handle Login POST */
router.post('/login', passport.authenticate('login', {
successRedirect: '/',
failureRedirect: '/login',
failureFlash : true
}));
/* GET Registration Page */
router.get('/signup', function(req, res){
res.render('register',{message: req.flash('message')});
});
/* Handle Registration POST */
router.post('/signup', passport.authenticate('signup', {
successRedirect: '/',
failureRedirect: '/signup',
failureFlash : true
}));
/* GET Home Page when logged in */
router.get('/', isAuthenticated, function(req, res){
res.render('index', { user: req.user });
});
router.get('/user', function(req, res) {
var data = {
firstName: req.user.firstName,
lastName: req.user.lastName,
email: req.user.email,
/* ... */
};
res.send([
data
]);
});
/* Handle Logout */
router.get('/signout', function(req, res) {
req.logout();
res.redirect('/login');
});
return router;
}
I'm using Cloud 9 to setup a basic social media website and I am having trouble with registration and authentication of users. I'm using Node.js, express and passport for authentication, and mongoDB as a database.
// PASSPORT Setup //
app.use(require("express-session")({
secret: "I am the best",
resave: false,
saveUninitialized: false
}));
app.use(passport.initialize());
app.use(passport.session());
passport.use(new LocalStrategy(User.authenticate()));
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
// INDEX Page
app.get("/", function(req, res) {
res.render("landing-page");
});
// REGISTER NEW
app.get("/register", function(req, res) {
res.render("user/register");
});
// REGISTER CREATE
app.post("/register", function(req, res) {
var user = req.body.user;
var newUser = new User({
username: user.email,
firstName: user.firstName,
lastName: user.lastName,
});
User.register(newUser, user.password, function(err, user) {
if(err) {
console.log(err);
return res.render("user/register");
}
passport.authenticate("local")(req, res, function() {
res.redirect("/");
});
});
});
// Login routes
app.get("/login", function(req, res) {
res.render("login");
});
app.post("/login", passport.authenticate("local", {
successRedirect: "/",
failureRedirect: "/login"
}) , function(req, res) {
});
// Logout route
app.get("/logout", function(req, res) {
req.logout();
res.redirect("/");
});
However whenever I run this, when I sign up a new user, it gives me a webpage with just "Bad Request", however the user is created in the database.
Look at this answer; the bad request is not a problem with your passport method: that indicates the request you try to make is not correct:
Did you set the head at: Content-Type: application-json?
Also update the bodyParser to the last version. This solved a similar problem I had.