I am trying to use Passport as an authentication middleware with Express - and Angular, if it matters. I have just started to know these frameworks and I experiment with a simple test login in the app. These are the relevant code snippets in my root/app.js that should do the login method:
var express = require('express'),
routes = require('./routes'),
api = require('./routes/api'),
passport = require('passport'),
LocalStrategy = require('passport-local').Strategy;
...
app.configure(function(){
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.static(__dirname + '/public'));
app.use(passport.initialize());
app.use(app.router);
});
...
// Authentication with Passport.js
var testUser = {
username: 'patrik',
password: '123'
}
passport.use(new LocalStrategy(
function(username, password, done) {
if(username == testUser.username) {
if(password == testUser.password) {
return done(null, username);
} else {
return done(null, false, { message: 'Incorrect password.' });
}
} else {
return done(null, false, { message: 'Incorrect username.' });
}
}
));
...
app.post('/login',
passport.authenticate('local', { successRedirect: '/',
failureRedirect: '/login',
failureFlash: true })
);
Here is my template code in index.jade:
form(method='post',action='/login')
div
label Username:
input(type='text',name='username')
div
label Password:
input(type='password',name='password')
div
input(type='submit',value='Log in')
And my problem is that if I try to post, I get this response from the browser:
Response
Cannot POST /login
You have to update some of express and passport requirements for this to work. Such as session, failureflash messages, serialize and deserialize. Here is updated code snippet for you. first you have to install "connect-flash" for this line of codes "failureFlash : true". But it will work without flash.
npm install connect-flash
var express = require('express'),
routes = require('./routes'),
api = require('./routes/api'),
passport = require('passport'),
LocalStrategy = require('passport-local').Strategy,
flash = require('connect-flash');
Then update express environments:
app.configure(function(){
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.static(__dirname + '/public'));
app.use(express.cookieParser());
// required for passport
app.use(express.session({ secret: 'my secret'}));
app.use(passport.initialize());
app.use(passport.session());
app.use(app.router);
});
// Authentication with Passport.js
var testUser = {
username: 'patrik',
password: '123'
}
passport.use(new LocalStrategy(
function(username, password, done) {
if (username === testUser.username && password === testUser.password) {
return done(null, {username: username});
} else {
return done(null, {username: 'username or password incorrect!'});
}
return done(null, false);
}
));
passport.serializeUser(function(user, done) {
done(null, user.username);
});
passport.deserializeUser(function(username, done) {
done(null, {username: username});
});
app.get('/', routes.index);
app.post('/login',
passport.authenticate('local', {
successRedirect: '/',
failureRedirect: '/login',
failureFlash: true })
);
And here is a little update for your routes/index.js file:
exports.index = function(req, res){
var user = '';
if(req.session.passport.user !== undefined) user = req.user.username;
res.render('index', {title: user});
};
I hope these will help you to understand login with passport.
Related
I'm using passport with express framework, but after login using POST the req.isAuthenticated always returns false...
After login an image should be shown (image should be accessible if user is logged in).
Server:
var express = require('express')
, passport = require('passport')
, flash = require('connect-flash')
, LocalStrategy = require('passport-local').Strategy;
var path = require('path');
var app = express();
var users = [
{ id: 1, username: 'bob', password: 'secret', email: 'bob#example.com' }
, { id: 2, username: 'joe', password: 'birthday', email: 'joe#example.com' }
];
function findById(id, fn) {
var idx = id - 1;
if (users[idx]) {
fn(null, users[idx]);
} else {
fn(new Error('User ' + id + ' does not exist'));
}
}
function findByUsername(username, fn) {
for (var i = 0, len = users.length; i < len; i++) {
var user = users[i];
if (user.username === username) {
return fn(null, user);
}
}
return fn(null, null);
}
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
findById(id, function (err, user) {
done(err, user);
});
});
passport.use(new LocalStrategy(
function(username, password, done) {
process.nextTick(function () {
findByUsername(username, function(err, user) {
if (err) { return done(err); }
if (!user) { return done(null, false, { message: 'Unknown user ' + username }); }
if (user.password != password) { return done(null, false, { message: 'Invalid password' }); }
return done(null, user);
})
});
}
));
app.configure(function() {
app.use(express.logger());
app.use(express.cookieParser('keyboard cat'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.session({ secret: 'keyboard cat' }));
app.use(flash());
app.use(passport.initialize());
app.use(passport.session());
app.use(app.router);
app.use('/media', ensureAuthenticated); //commenting this out and it work...
app.use('/media', express.static(path.join(__dirname, 'media')));
});
app.post('/login',
passport.authenticate('local', { failureRedirect: '/login', failureFlash: true }),
function(req, res) {
console.log(req.sessionID);
console.log('login success');
res.send('ok');
}
);
app.listen(3000, function() {
console.log('Express server listening on port 3000');
});
function ensureAuthenticated(req, res, next) {
console.log(req.isAuthenticated());
console.log(req.sessionID);
if (req.isAuthenticated()) { return next(); }
res.status(500).send();
// res.redirect('/login')
}
HTML-File:
<html>
<head>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
<script type="text/javascript" src="js/socket.io.js"></script>
</head>
<body>
<img src="" id="testimage" />
<img src="" id="testimage2" />
<script>
$.post('http://localhost:3000/login', {
username: 'bob',
password: 'secret'
});
setTimeout(function() {
$('#testimage').attr("src","http://localhost:3000/media/01.jpg");
},2000);
setTimeout(function() {
$('#testimage2').attr("src","http://localhost:3000/media/02.jpg");
},5000);
</script>
</body>
</html>
I'm sitting for hours but can't find the problem... What am I doing wrong?
Edit: I found out, that the sessionId (req.sessionId) is different for each request. I modified the html file to load two pictures, also the sessionid of both requests are different. After adding res.status(500).send(); to ensureAuthenticated method the sessionId of both requests is the same, but it's different to the sessionId of the /login post request...
I modified the code above...
Edit2: Found out that app.post(...) always creates new sessionID, app.get(...) uses same sessionID... Why?
How are you serving your HTML? If its not via the same node.js service then that might be your problem.
I tried adding a get('/') route that renders your HTML using ejs and everything is working fine for me. I renamed your html file to index.ejs in the root project dir and made the following changes to your code:
app.configure(function() {
app.use(express.logger());
app.use(express.cookieParser('keyboard cat'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.session({
secret: 'keyboard cat'
}));
app.use(flash());
app.use(passport.initialize());
app.use(passport.session());
app.use(app.router);
app.use('/media', ensureAuthenticated); //commenting this out and it work...
app.use('/media', express.static(path.join(__dirname, 'media')));
// Add EJS rendering
app.set('views', __dirname);
app.set('view engine', 'ejs');
});
app.get('/', function(req, res) {
res.render('index');
});
I'm using PassportJS to create a login/sign-up program. Then to enter I try to include the username of the user in the path of the redirect. To be more precise, when the user does a login with username and password I want to redirect him/her to the page localhost:3000/library?'username'. How can I do it?
var config = require('./config');
var express = require('express');
var path = require('path');
var logger = require('morgan');
var bodyParser = require('body-parser');
var dustjs = require('adaro');
var app = express();
var multer = require('multer');
var passport = require('passport');
LocalStrategy = require('passport-local').Strategy;
var mongoose = require('mongoose');
require('./models');
require('express-session');
// Connect to MongoDB here
var mongoose = require('mongoose');
mongoose.connect(config.mongoUrl + config.mongoDbName);
//passport
// --------------- USER PART --------------------\\
var User = mongoose.model('User');
passport.use(new LocalStrategy({
usernameField:'userName',
passwordField:'password'
},
function(username, password, done) {
User.findOne({userName: username}, function (err, user) {
if (err) { return done(err); }
// Return an error as in Node
if (!user) {
return done(null, false, { message: 'Incorrect username.' });
// If user does not exist return the error and the message
}
user.isValidPassword(password, function(err,isMatch){
if (isMatch==true){
return done(null, true);
// Authentication is good, the password is valid
}else{
return done(null, false, {message:"Incorrect password! "})
}
});
});
}
));
passport.serializeUser(function(users, done) {
done(null, 0);
// Invoke passport with user._id authenticated
});
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user) {
// Deserializza e cerca attraverso l'id
done(err, user);
});
});
// --------------- EDN USER PART --------------------\\
/*--- Configure the multer. used to upload the track from our pc on the server ---*/
app.use(multer({ dest: './public/tracks_folder/',
rename: function (fieldname, filename) {
return filename;
}
}));
// Register model definition here
require('./models');
// dustjs view engine setup
app.engine('dust', dustjs.dust());
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'dust');
// USER
app.use(passport.initialize());
app.use(passport.session());
//configure app
app.use(logger('dev'));
app.use(bodyParser.urlencoded({ extended: false })); // parse application/x-www-form-urlencoded
app.use(bodyParser.json()); // parse application/json
app.use(express.static(path.join(__dirname, 'public')));
// Initialize routers here
var routers = require('./routes/routers');
app.use('/', routers.root);
app.use('/albums', routers.albums);
app.use('/artists', routers.artists);
app.use('/tracks', routers.tracks);
app.use('/users', routers.users);
// USER
app.use('/signup', routers.signup);
app.use('/library', routers.library);
EDIT OF GET
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('/library/' + user.username);
});
})(req, res, next);
});
app.post('/login',
passport.authenticate('local', { successRedirect: '/library',
failureRedirect: '/'}));
// END USER
module.exports = app;
I'm sure, I'm doing something wrong coz of my lack of experience with this technologies.
So here I'm trying to authenticate my user.
in server.js I have the following :
var express = require('express');
var app = express();
var port = process.env.PORT || 8080;
//var configDB = require('./config/database.js');
require('./config/environement.js')(app, express);
require('./config/routes.client.js')(app);
//setting all modules routes
require('./api/oAuth/routes.js')(app);
app.listen(port);
In environement.js :
module.exports = function(app, express) {
app.configure(function() {
var path = require('path');
var mongoose = require('mongoose');
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
/* je pense que ce code n'a rien a faire ici*/
var User = require('./../models/user.js');
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: 'Incorrect username.'
});
}
if (!user.validPassword(password)) {
return done(null, false, {
message: 'Incorrect password.'
});
}
return done(null, user);
});
}));
app.use(express.logger());
app.use(express.static(path.join(__dirname + '/../views')));
app.use(express.cookieParser());
app.use(express.bodyParser());
app.use(express.session({secret: 'm4B1teD4nsTaG0rgE'}));
app.use(passport.initialize());
app.use(passport.session());
app.use(app.router);
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
/*fin*/
mongoose.connect('mongodb://localhost/passport_local_mongoose');
app.set('views', __dirname + '/../views');
app.set('view engine', 'jade'); //extension of views
console.log("config ok");
});
//development configuration
app.configure('development', function() {
app.use(express.errorHandler({
dumpExceptions: true,
showStack: true
}));
});
//production configuration
app.configure('production', function() {
app.use(express.errorHandler());
});
};
And finaly my api/oAuth/routes.js
var User = require('../../models/user.js');
var passport = require('passport');
module.exports = function(app) {
app.get('/register', function(req, res) {
res.render('../api/oAuth/views/register.page.jade');
});
//Route vers /login en get et post
app.get('/login', function(req, res) {
res.render('../api/oAuth/views/login.page.jade');
});
app.post('/api/oAuth/login', function(req, res, next) {
console.log("post login = ok");
passport.authenticate('local',function(req, res) {
// If this function gets called, authentication was successful.
// `req.user` contains the authenticated user.
res.redirect('/users/' + req.user.username);
});
});
app.post('/api/oAuth/register', function(req, res) {
User.register(
new User({
username: req.body.username
}), req.body.password, function(err, user) {
if (err) {
res.send(err);
}
else {
res.send("Success");
}
});
});
}
Edit : Added user.js
var mongoose = require('mongoose'),
Schema = mongoose.Schema,
passportLocalMongoose = require('passport-local-mongoose');
var passport = require('passport');
var User = new Schema({
username: String,
password: String
});
User.plugin(passportLocalMongoose);
passport.serializeUser(function(user, done) {
console.log("serializeUser");
done(null, user);
});
passport.deserializeUser(function(user, done) {
console.log("deserializeUser");
done(null, user);
});
module.exports = mongoose.model('User', User);
When the app goes into passport.authenticate() it does a lot of thing then it return to passport.authenticate() in a loop way. When I use the custom callback I realize that passport.authenticate() is going smoothly but the problem seems to be in req.logIn() function. I don't know what to do in order to make this work, and I tried a lot. I feel like a blind man trying to drive a car :D.
I have a persistent problem with Passport.js in my Express.js small application : whatever I put in the LocalStrategy, I'm always redirected to the failureRedirect, apparently without even pass by the LocalStrategy...
What did I wrong ? And how can I print/display the largest error log to follow the execution ?
var express = require('express'),
passport = require('passport'),
LocalStrategy = require('passport-local').Strategy;
http = require('http'),
path = require('path'),
mysql = require('mysql'),
flash = require('connect-flash');
var app = express();
// SQL connexion
var sqlInfo = {
host: 'localhost',
user: 'root',
password: '',
database: 'mex'
};
global.client = mysql.createConnection(sqlInfo);
client.connect(function(err) {
if(err)
console.log(err);
});
app.configure(function(){
app.set('views', __dirname+'/views');
app.set('port', process.env.PORT || 85);
//app.engine('ejs', engine);
app.use(express.static('public'));
app.use(express.cookieParser());
app.use(express.bodyParser());
// 1 - Session express
app.use(express.session({ secret: 'secretpass' }));
// 2 - Init et session Passeport
app.use(passport.initialize());
app.use(passport.session());
app.use(flash());
app.use(express.logger());
app.use(app.router);
});
// Simple logger
app.use(function(req, res, next){
console.log('%s %s', req.method, req.url);
next();
passport.use(new LocalStrategy(
function(username, password, done) {
console.log("localstrategy ---");
var user = {username: 'w#j.fr', password: 'pwd'};
return done(null, user);
}));
passport.serializeUser(function(user, done) {
// JUST 4 TEST
done(null, user);
});
passport.deserializeUser(function(user, done) {
// JUST 4 TEST
done(null, user);
});
// Home
app.get('/', function(req, res){
//check user session value, is logged in
if(req.user)
res.render('menu_log.ejs', function(err, html){
var data = {
title: 'Home',
menu: html
//req.user['Prenom'] -- à afficher
};
res.render('index.ejs', data);
console.log("index logué");
});
else
res.render('menu_nolog.ejs', function(err, html){
var data = {
title: 'Home',
menu: html
};
res.render('index.ejs', data);
console.log("index PAS logué");
});
});
// Passport's authentication
app.post('/login',
passport.authenticate('local', { successRedirect: '/',
successFlash: 'Bienvenue !',
failureRedirect: '/wrong',
failureFlash: "Email ou mot de passe incorrect." })
);
app.get('/logout', function(req, res){
req.logout();
res.redirect('/');
})
.get('/inscription', function(req, res){
res.render('menu_nolog.ejs', function(err, html){
var data = {
title: 'Register',
menu: html
};
res.render('inscription.ejs', data);
});
});
http.createServer(app).listen(app.get('port'), function () {
console.log('Express server listening on port ' + app.get('port'));
});
LocalStrategy requires two parameters (either passed as POST data, or in a query string) to exist: username and password. If you're not passing those two, Passport doesn't even bother to call the strategy handler.
The field names are configurable by passing an object as first argument to the LocalStrategy constructor:
passport.use(new LocalStrategy({
usernameField : 'username',
passwordField : 'password'
}, function(username, password, done) { ... }));
I'm trying to do twitter oauth in nodejs using passportjs but getting error
Cannot GET /auth/twitter/callback?oauth_token=alksdkalsjdsjd23232378skjdfjsdhf&oauth_verifier=234jjh23j4k234k23h4j2h342k34hj
Here is my node js code
var express = require('express')
, passport = require('passport')
, util = require('util')
, GoogleStrategy = require('passport-google').Strategy
, TwitterStrategy = require('passport-twitter').Strategy;
passport.serializeUser(function(user, done) {
done(null, user);
});
passport.deserializeUser(function(obj, done) {
done(null, obj);
});
passport.use(new TwitterStrategy({
consumerKey: 'xxxxxxxxxxxxxxxxxxxx',
consumerSecret: 'xxxxxxxxxxxxxxxxxxxxxxxxxx',
callbackURL: 'http://127.0.0.1:3000/auth/twitter/callback'
},
function(token, tokenSecret, profile, done) {
process.nextTick(function () {
return done(null, profile);
});
}
));
var app = express();
// configure Express
app.configure(function() {
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.use(express.logger());
app.use(express.cookieParser());
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.session({ secret: 'keyboard cat' }));
// Initialize Passport! Also use passport.session() middleware, to support
// persistent login sessions (recommended).
app.use(passport.initialize());
app.use(passport.session());
app.use(app.router);
app.use(express.static(__dirname + '/../../public'));
});
app.get('/', function(req, res){
res.render('index', { user: req.user });
});
app.get('/login', function(req, res){
res.sendfile('./views/auth.html');
});
app.get('/auth/twitter', passport.authenticate('twitter'));
app.get('auth/twitter/callback',
passport.authenticate('twitter', { successRedirect: '/success',
failureRedirect: '/login' }));
app.get('/success', function(req, res){
res.send("success logged in");
});
app.listen(process.env.PORT || 3000);
EDIT
There is missing / in auth/twitter/callback route definition.
Also for the routers /auth/twitter and auth/twitter/callback, passport.authenticate() as middleware will do the authentication, and you should have route handling functions.
So the definition of your routes should look something like:
app.get('/auth/twitter',
passport.authenticate('twitter'),
function(req, res) {}); // empty route handler function, it won't be triggered
app.get('/auth/twitter/callback',
passport.authenticate('twitter', {
successRedirect: '/success',
failureRedirect: '/login' }),
function(req, res) {}); // route handler
You don't need the empty route handler function(req, res) {} - you can just leave the argument out and express will understand you don't plan on ever using the handler