I am using Passport js for authentication in my project. At server side i am using Express js. In app.js i have configuration for passport js and the code is:
passport.use(new Strategy({
passReqToCallback: true
},
function (req, username, password, done) {
req.models.users.find({ 'user_id' : username }, function (err, user) {
if (err) { return done(err); }
if (!user[0]) {
console.log("The username is Incorrect");
return done(null, false, { message: 'Incorrect username.' });
}
if (user[0].default_password!=password) {
console.log("The Password is Incorrect");
return done(null, false, { message: 'Incorrect password.' });
}
return done(null, user);
});
}
));
passport.serializeUser(function(user, done) {
done(null, user);
});
passport.deserializeUser(function(user, done) {
done(null, user);
});
and after this i am verifying the client request like this:
app.post('/login',
passport.authenticate('local', { failureRedirect: '/login' }),
function(req, res) {
res.redirect('/');
});
Till here everything is working fine.
Now i want to place this route app.post('/login',... in routes folder so i have given the path of the route in app.js like this:
var users = require('./routes/users/users');
app.use('/users', users);
My problem is: in this user route file i don't have passport configuration and i don't want to rewrite it again for all my other routes so i am thinking to place the passport configuration in a common file and reuse it but i don't know how to do it. If you have any idea please help. Thanks.
You can write a middleware, lets call it auth.js, that checks for session info and mount this for every route that you need.
'use strict';
const qs = require('querystring'),
router = require('express').Router();
router.use(function (req, res, next) {
// set this in res.locals
if (!req.user) {
return res.redirect('/?' + qs.stringify({
'r': req.originalUrl
}));
}
next();
});
module.exports = router;
If you use the above approach, you will need to add res.locals.user = req.user; in your server/app.js.
After this, you can require the above middleware on every route that needs to be authenticated.
router.verb('/path', require('./path-to-auth'));
router.verb('/path', (req, res, next) => {
// this route will only be executed if the user is authenticated
});
Related
I have a tremendous headche with a problem when I try to login using Passport.
I'm making a post request to /login with an email and password. Passport authenticates it correctly, err isn't called and then return res.redirect('/user') gets called too but it returns 404 and doesn't redirect.
I don't know why this is happening. Here's my code:
Server (index.js):
const
express = require('express'),
app = express(),
mongoose = require('mongoose'),
passport = require('passport'),
cookieSession = require('cookie-session'),
bodyParser = require('body-parser'),
keys = require('./config/keys'),
user = require('./models/User'),
passportService = require('./services/passport'),
authRoutes = require('./routes/auth');
mongoose.connect(keys.mongoURI);
app.use(bodyParser.json());
app.use(
cookieSession({
maxAge: 15 * 24 * 60 * 60 * 1000,
keys: [keys.cookieKey]
})
);
app.use(passport.initialize());
app.use(passport.session());
passportService(passport);
authRoutes(app);
const PORT = process.env.PORT || 5000;
app.listen(PORT, () => {
console.log(`App listening on port ${PORT}`);
});
passportService (passport.js):
const LocalStrategy = require('passport-local').Strategy;
const mongoose = require('mongoose');
const User = mongoose.model('users');
module.exports = (passport) => {
passport.serializeUser((user, done) => {
done(null, user._id);
});
passport.deserializeUser((id, done) => {
User.findById(id).then(user => {
done(null, user);
});
});
passport.use(
new LocalStrategy(
{
usernameField: 'emailaddr',
passwordField: 'passwd'
},
function(username, password, done) {
User.findOne({ email: username }, function(err, user) {
if(err){
return done(err);
}
if(!user) {
console.log('User not found with email: ', username);
return done(null, false);
}
if(user.password != password) {
console.log('Invalid password');
return done(null, false)
}
return done(null, user);
});
}));
}
Authentication route:
const passport = require('passport');
module.exports = app => {
app.post('/api/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('/user');
});
})(req, res, next);
});
}
There is not route for /user because I'm working with React and React Router in the client.
Please I need your help!!!
I would suggest not using the custom callback on your authenticate function. Instead, check to see if after the api is called and authentication is run if you have a user attached to the request object.
// calling redirects from your api will be problematic with react router
// allow your front end to decide what route to call based on the response
app.post('/api/login', passport.authenticate('local'), function(req, res, next) {
if(req.user) {
res.json(req.user);
} else {
// handle errors here, decide what you want to send back to your front end
// so that it knows the user wasn't found
res.statusCode = 503;
res.send({message: 'Not Found'})
}
});
Look, i've made a mean stack app with register/login using passportjs, and it was fine, when i change to angular2(the other was on angularjs) i've made the backend side and i think it works but i dont know how to test it on the fronted side, i know it has to be something with the url in the <a href=""> but when i put the route that passport gives me, example: /auth/facebook, my aplication does nothing... well it does something, send me to the homepage :c
here is my code so far on the backend side
const FacebookStrategy = require('passport-facebook').Strategy;
const session = require('express-session');
const secret = require('../config/database')
const user = require('../models/user')
module.exports = function(app, passport){
app.use(passport.initialize());
app.use(passport.session());
app.use(session({
secret: 'keyboard cat',
resave: false,
saveUninitialized: true,
cookie: { secure: false }
}));
passport.serializeUser(function(user, done) {
token = jwt.sign({email: user.email}, secret, {expiresIn : '24h'});
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user) {
done(err, user);
});
});
passport.use(new FacebookStrategy({
clientID: '350645212059140',
clientSecret: '8a990aec6db37cc3535f4223c235c427',
callbackURL: "http://localhost:4200/auth/facebook/callback",
profileFields: ['id','displayName','email']
},
function(accessToken, refreshToken, profile, done) {
console.log(profile);
// User.findOrCreate(..., function(err, user) {
// if (err) { return done(err); }
// done(null, user);
// });
done(null, profile)
}
));
app.get('/auth/facebook',passport.authenticate('facebook', { scope: 'email' }));
app.get('/auth/facebook/callback' , passport.authenticate('facebook', {failureRedirect: '/login'}), function(res, res){
if (err) {
console.log(err)
}else{
res.send('wi')
}
})
return passport;
}
my question is, how can i implement this on the fronted side, remember angular 4 :)
Here is pseudo code for this.
Step 1: When you are submitting your form using ngSubmit call a function for instance passportLogin().
Step 2: Now in your component use this function and do an HTTP post request to your node js(express js) URL, for example, auth/login.
Step 3: In the server side write a routing
var express = require('express'),
router = express.Router();
module.exports = function(passport){
router.post('/login', passport.authenticate('local-login', {
successRedirect: '/auth/success',
failureRedirect: '/auth/failure'
}));
}
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.
Following the tutorial here
Auth.js
var passport = require("passport"),
LocalStrategy = require("passport-local").Strategy;
passport.use(new LocalStrategy(
function(username, password, done){
console.log("----", username, password, "----"); //this works fine, get the proper values here.
if(username === "admin" && password === "sw") {
return done(null, {username: "admin"});
}
return done(null, false);
}
));
passport.serializeUser(function(user, done){
done(null, user.username);
});
passport.deserializeUser(function(username, done){
done(null, {username: username});
});
module.exports = passport;
app.js (the relevant bits)
var passport = require("./auth")
var users = require('./routes/users');
.
.
.
app.use('/users', users);
app.post('/', passport.authenticate("local", {
failureRedirect: "/",
successRedirect: "/users"
}));
user route
var express = require('express');
var router = express.Router();
/* GET users listing. */
router.get('/', function (req, res, next) {
console.log(req.user);
res.render('users', {
title: 'Routed !'
});
});
module.exports = router;
Most of the code works fine, it posts and routes correctly, but, req.user is undefined in the users route, and I'm not able to figure out why.
I have an express app that I am trying to authenticate with passport-local. Here is my express app:
app.use(express.bodyParser());
app.use(express.cookieParser());
app.use(express.session({ secret: 'this is a string' }));
app.use(passport.initialize());
app.use(passport.session());
client = new pg.Client(connectionString);
client.connect();
passport.use(new LocalStrategy(
function(username, password, done) {
var query = client.query('SELECT * FROM users WHERE EMAIL = $1', [username], function(err, result){
if(err) {
console.log("Error");
return done(err);
}
if(!result.rows.length > 0) {
console.log("No users");
return done(null, false, { message: 'User not found'});
}
if(result.rows[0].password !== password) {
console.log("incorrect password");
return done(null, false, { message: 'Password Incorrect'});
}
console.log('authenticated');
return done(null, result.rows[0]);
});
}
));
passport.serializeUser(function(user, done) {
'use strict';
console.log('serialize');
console.log(user);
done(null, user.email);
});
passport.deserializeUser(function(id, done) {
'use strict';
console.log('deserialize');
User.findById(id, function(err, user) {
done(err, user);
});
});
app.post('/login', passport.authenticate('local'), function(req, res) {
'use strict';
console.log(req.user.username);
});
app.listen(port, function() {
'use strict';
console.log('Listening on:', port);
});
I then hit the /login url with this json in my body: {username: 'jason#gmail.com', password: 'password }. I go through the LocalStrategy function and then in the serialize function it makes it to the done function and then just hangs. I get no errors or additional logging, the connection just stays open and control is not given back to the caller. I never receive a http status, it just hangs.
I think it is a problem with my session, but I do not understand what to do next?
Ok, could you try a redirect there? It looks like your session / auth is ok, if you get a proper username at that point.
app.post('/login', passport.authenticate('local', {
successRedirect: '/somewhere_intern',
failureRedirect: '/login'
}));