How to configure Passportjs with SQL Server? - sql-server

I am writing an app based on SQL Server, ExpressJs, NodeJS, AngularJs, I am an express beginner, I need to handle sessions so I have been thinking on PassportJs, I can't find documentation to integrate SQL Server with PassportJs so I am pretty confused, I have been trying but I don't get it yet, I have built my app with express-generator so this is my app.js
Passport requires:
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var session = require('express-session');
Routes:
var routes = require('./routes/index');
var login = require('./routes/login');
express-session:
app.use(session({secret: 'xXxXxXXxX'}));
app.use(passport.initialize());
app.use(passport.session());
app.use('/', routes);
app.use('/login', login);
passport-init:
var initPassport = require('./r12_modulos/sesion/passport-init.js');
initPassport(passport);
This is what I have in passport-init.js:
var conex = require('../conexion_bd/conex_mssql.js');
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
module.exports = function () {
passport.serializeUser(function (user, done) {
console.log('serializing user:', user.username);
done(null, user.username);
});
passport.deserializeUser(function (username, done) {
done(null,username);
});
passport.use('login', new LocalStrategy({
passReqToCallback: true
},
function (req, username, password, done) {
var _cParameters = [];
_cParameters.push({ name: 'usuario', type: 'VarChar', value: username });
_cParameters.push({ name: 'password', type: 'NVarChar', value: password });
conex.sp_recordset(conex.mssql_conect, 'dbo.sp_sis_loginR12', _cParameters, function (data) {
if (data[0].response == 1) {
return done(null, data[0].usuario);
}
else {
return done(null, false);
}
});
}
));
};
As you can see I have wrote a module to execute SQL Server stored procedures, when I am searching on internet passportjs is commonly integrated with Mongo, I don't know how to handle the passport.serializeUser and passport.deserializeUser functions with SQL Server.
This is What I have in the route login.js:
var express = require('express');
var passport = require('passport');
var router = express.Router();
router.post('/', passport.authenticate('login', {
successRedirect: '/',
failureRedirect: '/login'
}));
module.exports = router;
When I send a post request the server does not return an error but do not run my LocalStrategy.

Googling I have found this post Understanding passport.js authentication flow, As the link says the autor explains which is the passportJs flow, I had some errors, unless you define the name of the username and password fields you must to send them in the post like this req.body.username and req.body.password, that was one of my errors, I handle the Serialize and Deserialize functions on this way:
serializeUser function
passport.serializeUser(function (user, done) {
console.log('serializing user:', user);
done(null, user);
});
deserializeUserfunction
passport.deserializeUser(function (username, done) {
console.log('deserializing user:', username);
done(null,username);
});

Related

While executing passport.authenticate, displays as unauthorized 404 in get post

File router.js contains the routers that are used.
In the ionic2, providers are made with the post method by giving uri as http://localhost:8080/api/auth/login which gives 400 bad request error in the debugger tools.
I have found that when I removerequireLoginthen the post is working fine.But I needrequireLogin` for authenticating the local login of passport.
router.js
//require the passport strategy from the folder in the project.
var passport = require('passport');
var x = require('./usefile/file');
var requireLogin = passport.authenticate('local',{session: false});
module.exports = function(app){
var auth = express.Router();
app.use('/api/auth', auth);
auth.post('/login', requireLogin, function(req, res){
x.login(req, res)});
}
passport.js
var passport = require('passport');
var JwtStrategy = require('passport-jwt').Strategy;
var ExtractJwt = require('passport-jwt').ExtractJwt;
var LocalStrategy = require('passport-local').Strategy;
var config = require('./auth');
var User = require('../models/user');
var localOptions = {
usernameField: 'email',
};
var localLogin = new LocalStrategy(localOptions, function (email, password, done) {
User.find(
{ email: email }, function (err, user) {
if (err) {
return done(err);
}
if (!user) {
return done(null, false, { error: 'Login failed,Please try again.' });
}
if (!isMatch) {
return done(null, false, { error: 'Login failed, Please try again.' });
}
user.comparePassword(function(password, isMatch){
if(err){
return done(err);
}
if(!isMatch){
return done(null, false, {error:'Login failed, Please try again.'});
}
return done(null, user);
});
});
});
passport.use(localLogin);
Note: My code is not using the requireLogin which is used to authenticate from the passport, So it is showing 400 bad request error.
Please Help.
have you required your local passport file? You seem to be requiring the npm passport module, and not your local file.
You should change the first line of code in router.js to
//require the passport strategy from the folder in the project.
var passport = require('./passport');//<--change this line
var x = require('./usefile/file');
var requireLogin = passport.authenticate('local',{session: false});
module.exports = function(app){
var auth = express.Router();
app.use('/api/auth', auth);
auth.post('/login', requireLogin, function(req, res){
x.login(req, res)});
}
Let me know how that goes.

Node req.user undefined after login while using Angular

I know that there has been another answer to this found here but I cannot for the life of me get my req.user to populate anything other than undefined while using angularjs.
I have tried cookieParser, including the session secret in cookieParser, making sure the order of my express session comes before the passport session, I have User serialzed and deserialized. Nothing is working.
here is my code, hope someone could help!
var HelperController = require('./controllers/helpers.js');
app.use("/helper", HelperController);
var passport = require('passport');
var cookieParser = require('cookie-parser');
var session = require('express-session');
//PASSPORT
//=================================
app.use(cookieParser('keyboard cat'));
app.use(session({
secret: 'keyboard cat',
resave: false,
saveUninitialized: false
}));
app.use(passport.initialize());
app.use(passport.session());
//To be used when user is created ********
passport.use(User.createStrategy());
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
//USER HOME REGISTER
//=================================
app.post('/register', function(req, res){
console.log(req.body);
User.register(new User({
username: req.body.username
}),
req.body.password,
function(err, user){
req.login(user, function(err){
if (err) {console.log(err); }
return res.json(user);
});
});
});
//USER HOME LOGIN
//=================================
app.post('/login', passport.authenticate('local'), function(req, res){
res.json(req.user);
});
//ROUTER SETUP
//=========================================
var express = require('express');
var router = express.Router();
router.get('/get-user', function(req, res){
var user = req.user;
console.log(user);
res.json({user: user});
});
module.exports = router;

When button is clicked "Undefined" data is being written to the DB (Angular, Jade, Heroku, Node and PostgreSQL are being used)

My program is trying to add data to a PostgreSQL db on Heroku, but when I click the appropriate button it writes the data as "Undefined". Am I making a mistake in the way I call the variables?
The app is using Node.js. My approach for writing to the db was copied from from http://www.jitendrazaa.com/blog/webtech/how-to-use-postgresql-in-nodejs/, but I'm using Jade instead of html.
Here's the Jade page that shows the data and has a button to add to the db. The $scope.addRecord function is defined here:
extends layout
block content
div(id="container", ng-controller="postgreSQLCtrl")
h2 Your Business Card's Data
h3 You can edit any of the fields below. Just click on the field and type whatever you like. To add to the database click the button at the bottom.
p.lead Name:
input(value=name, id="name", maxlength="30", width="600", ng-model="name", type="text")
p.lead Description:
input(value=description, id="description", maxlength="30", width="600", ng-model="description", type="text")
p.lead Location:
input(value=location, id="location", maxlength="30", width="600", ng-model="location", type="text")
p.lead Company:
input(value=company, id="company", maxlength="30", width="600", ng-model="company", type="text")
p.lead Title:
input(value=jtitle, id="jtitle", maxlength="30", width="600", ng-model="jtitle", type="text")
p.lead URL for Your Photo:
input(value=photo, id="photo", maxlength="200", width="600", ng-model="photo", type="text")
img(src= photo)
| <button ng-click="addRecord()" id="btnAdd" name="btnAdd" class="btn btn-danger">Add to db</button>
script(src='//ajax.googleapis.com/ajax/libs/angularjs/1.2.6/angular.min.js')
script.
var myApp = angular.module('postgreSQL',[ ]);
myApp.controller('postgreSQLCtrl', ['$scope' ,'$http', function($scope,$http) {
$scope.addRecord = function(){
var url = '/db/addRecord?name='+$scope.name+'&description='+$scope.description+'&location='+$scope.location+'&company='+$scope.company+'&jtitle='+$scope.jtitle+'&photo='+$scope.photo;
console.log(url);
$http({method: 'GET', url: '/db/addRecord?name='+$scope.name+'&description='+
$scope.description+'&location='+$scope.location+'&company='+
$scope.company+'&jtitle='+$scope.jtitle+'&photo='+$scope.photo}).
success(function(data, status) {
alert('Record Added');
});
}
}]);
Here is the app's main js file. A lot of this code deals with passport and might not be relevant.
var express = require('express');
var app = express();
var path = require('path');
// Express middleware
var bodyParser = require('body-parser');
var cookieParser = require('cookie-parser');
var session = require('express-session');
var logger = require('morgan');
// Passport
var passport = require('passport');
var LinkedInStrategy = require('passport-linkedin-oauth2').Strategy; // source of strategy: https://github.com/auth0/passport-linkedin-oauth2
var config = require('./config.json');
var pg = require('pg');
var http = require('http');
var request = require('request');
var dbOperations = require("./dbOperations.js");
var logFmt = require("logfmt");
// View engine
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
// Middleware
app.use(express.static('public')); // Put your static files here
app.use(cookieParser());
app.use(bodyParser());
app.use(session({ secret: 'shhhsupersecret' }));
app.use(passport.initialize());
app.use(passport.session());
// Logger
app.use(logger('dev'));
// heroku tells us to use this
/*
pg.connect(process.env.DATABASE_URL, function(err, client) {
if (err) throw err;
console.log('Connected to postgres! Getting schemas...');
client
.query('SELECT table_schema,table_name FROM information_schema.tables;')
.on('row', function(row) {
console.log(JSON.stringify(row));
});
});
*/
// Passport session setup.
// to support persistent login sessions, passport needs to be able to
// serialize users into and deserialize users out of the session. Typically,
// this will be as simple as storing the user ID when serializing, and finding
// the user by ID when deserializing. However, since this example does not
// have a database of user records, the complete LinkedIn profile is
// serialized and deserialized.
passport.serializeUser(function(user, done) {
done(null, user);
});
passport.deserializeUser(function(obj, done) {
done(null, obj);
});
passport.use(new LinkedInStrategy({
clientID: config.LINKED_IN_CLIENT_ID,
clientSecret: config.LINKED_IN_CLIENT_SECRET,
callbackURL: "http://shrouded-reef-9087.herokuapp.com/auth/linkedin/callback",
scope: [ 'r_basicprofile' ],
passReqToCallback: true
}, function(req, accessToken, refreshToken, profile, done) {
// asynchronous verification, for effect...
req.session.accessToken = accessToken;
process.nextTick(function () {
// To keep the example simple, the user's LinkedIn profile is returned to
// represent the logged-in user. In a typical application, you would want
// to associate the LinkedIn account with a user record in your database,
// and return that user instead.
done(null, profile);
});
}));
// Routes
app.get('/', function (req, res) {
res.render('index', {title: 'LinkedIn Test Authorization'});
});
/*
from http://www.jitendrazaa.com/blog/webtech/how-to-use-postgresql-in-nodejs/
app.get('/' , function(req,res) {
res.sendfile('views/index.html');
} );
*/
app.get('/db/readRecords', function(req,res){
dbOperations.getRecords(req,res);
});
app.get('/db/addRecord', function(req,res){
dbOperations.addRecord(req,res);
});
app.get('/db/delRecord', function(req,res){
dbOperations.delRecord(req,res);
});
app.get('/db/createTable', function(req,res){
dbOperations.createTable(req,res);
});
app.get('/db/dropTable', function(req,res){
dbOperations.dropTable(req,res);
});
app.get('/user', function(req, res) {
console.log('User Object: ', req.user);
var name = req.user.displayName;
var description = req.user._json.headline;
var location = req.user._json.location.name;
var company = req.user._json.positions.values[0].company.name;
var jtitle = req.user._json.positions.values[0].title;
var photo = req.user.photos[0];
console.log('-----Desired data: ',name,description,location,company,jtitle,photo);
console.log('-----Desired data length: ',name.length,description.length,location.length,company.length,jtitle.length,photo.length);
res.render('user', {name: name, description: description, location: location, company: company, jtitle: jtitle, photo: photo, title: 'Your Business Card'});
});
// This sends the user to authenticate with linked-in
app.get('/auth/linkedin',
passport.authenticate('linkedin', { state: 'asdfqwertlkjhz91xcv' }),
function(req, res){
// The request will be redirected to LinkedIn for authentication, so this
// function will not be called.
});
// This is where we handle the callback and redirect the user
app.get('/auth/linkedin/callback',
passport.authenticate('linkedin', { failureRedirect: '/' }),
function (req,res) {
res.redirect('/user');
});
// The server
var server = app.listen(process.env.PORT || 3000, function () {
var host = server.address().address;
var port = server.address().port;
console.log('LinkedIn Test app listening at http://%s:%s', host, port);
});
This is the dbOperations.js file, which defines the "addRecord" function that I'm trying to call with the angular $scope.addRecord function.
module.exports = {
getRecords: function(req, res) {
var pg = require('pg');
//You can run command "heroku config" to see what is Database URL from Heroku belt
var conString = process.env.DATABASE_URL || "postgres://postgres:Welcome123#localhost:5432/postgres";
var client = new pg.Client(conString);
client.connect();
var query = client.query("select * from cards");
query.on("row", function (row, result) {
result.addRow(row);
});
query.on("end", function (result) {
client.end();
res.writeHead(200, {'Content-Type': 'text/plain'});
res.write(JSON.stringify(result.rows, null, " ") + "\n");
res.end();
});
},
addRecord : function(req, res){
var pg = require('pg');
console.log("--------------req=",req);
var conString = process.env.DATABASE_URL || "postgres://postgres:Welcome123#localhost:5432/postgres";
var client = new pg.Client(conString);
client.connect();
var query = client.query("insert into cards (name,description,location,company,jtitle,photo) "+
"values ('"+req.name+"','"+req.description+"','"+
req.location+"','"+req.company+
"','"+req.jtitle+"','"+req.photo+
"')");
query.on("end", function (result) {
client.end();
res.write('Success');
res.end();
});
},
delRecord : function(req, res){
var pg = require('pg');
var conString = process.env.DATABASE_URL || "postgres://postgres:Welcome123#localhost:5432/postgres";
var client = new pg.Client(conString);
client.connect();
var query = client.query( "Delete from cards Where id ="+req.query.id);
query.on("end", function (result) {
client.end();
res.write('Success');
res.end();
});
},
createTable : function(req, res){
var pg = require('pg');
var conString = process.env.DATABASE_URL || "postgres://postgres:Welcome123#localhost:5432/postgres";
var client = new pg.Client(conString);
client.connect();
var query = client.query( "CREATE TABLE cards"+
"("+
"name character varying(50),"+
"description character varying(50),"+
"location character varying(50),"+
"company character varying(50),"+
"jtitle character varying(50),"+
"photo character varying(200),"+
"id serial NOT NULL"+
")");
query.on("end", function (result) {
client.end();
res.write('Table Schema Created');
res.end();
});
},
dropTable : function(req, res){
var pg = require('pg');
var conString = process.env.DATABASE_URL || "postgres://postgres:Welcome123#localhost:5432/postgres";
var client = new pg.Client(conString);
client.connect();
var query = client.query( "Drop TABLE cards");
query.on("end", function (result) {
client.end();
res.write('Table Schema Deleted');
res.end();
});
}
};
(This is an edited version of the original. At first the function wasn't working due to a misplaced ' symbol.)
In addRecord change it to req.query.name etc. instead of req.name.

LDAP Authentication with NodeJS, Express, and Passport-ldapauth

I"m having trouble authenticating to an Active Directory Server with the tools/applications mentioned in the title.
I'm using a test AD environment found here
Here are the relevant code snippets, if anyone has any suggestions I would really appreciate it.
Currently, the error i'm getting is "invalid username/password". I'm not sure if this is the bindDn account/pw or the one the user enters in the form. According to the passport-ldapauth project it's:
invalidCredentials flash message for InvalidCredentialsError
NoSuchObjectError, and
/no such user/i LDAP errors (default: 'Invalid username/password')
Thanks in advance.
CLIENT - auth.service.js
...
login: function(user, callback) {
var cb = callback || angular.noop;
var deferred = $q.defer();
$http.post('/auth/ldap', {
email: user.email,
password: user.password
}).
success(function(data) {
$cookieStore.put('token', data.token);
currentUser = User.get();
deferred.resolve(data);
return cb();
}).
error(function(err) {
this.logout();
deferred.reject(err);
return cb(err);
}.bind(this));
return deferred.promise;
},
...
SERVER index.js
'use strict';
var express = require('express');
var passport = require('passport');
var auth = require('../auth.service');
var router = express.Router();
router.post('/', function(req, res, next) {
passport.authenticate('ldapauth', function (err, user, info) {
var error = err || info;
if (error) return res.json(401, error);
if (!user) return res.json(404, {message: 'Something went wrong, please try again.'});
var token = auth.signToken(user._id, user.role);
res.json({token: token});
})(req, res, next)
});
module.exports = router;
SERVER passport.js
var passport = require('passport');
var LdapStrategy = require('passport-ldapauth').Strategy;
exports.setup = function (User, config) {
passport.use(new LdapStrategy({
usernameField: 'email',
passwordField: 'password',
server: {
url: 'ldap://ldap.forumsys.com:389',
bindDn: "cn=read-only-admin,dc=example,dc=com",
bindCredentials: "password",
searchBase: 'ou=mathematicians,dc=example,dc=com',
searchFilter: 'uid={{username}}'
}
},
function (user, done) {
return done(null, user);
}
));
};
The problem is with the ou=mathematicians in the search base. There is the following mention in the comments on that web page:
The issue you are seeing is due to the fact that “uid=riemann” is a member of “ou=mathemeticians”, but does not reside under that ou. His membership in that ou is established by a uniqueMember attribute on “ou=mathemeticians”.
This should work (tried it even with ldapauth-fork which passport-ldapauth uses):
var opts = {
server: {
"url": "ldap://ldap.forumsys.com:389",
"adminDn": "cn=read-only-admin,dc=example,dc=com",
"adminPassword": "password",
"searchBase": "dc=example,dc=com",
"searchFilter": "(uid={{username}})",
}
};
For whose still lose your way, here is my code snippet in Typescript.
Server Side
import * as express from 'express'
import * as bodyParser from 'body-parser'
import * as cors from 'cors'
import * as passport from 'passport'
import * as ldapstrategy from 'passport-ldapauth'
// connect to LDAP server
const OPTS: ldapstrategy.Options = {
server: {
url: "ldap://ldap.forumsys.com",
bindDN: "cn=read-only-admin,dc=example,dc=com",
bindCredentials: 'password',
searchBase: "dc=example,dc=com",
searchFilter: "(uid={{username}})"
}
}
passport.use(new ldapstrategy(OPTS))
// instantiate the server
const app = express()
// parse the request data automatically
app.use(bodyParser.json())
// allow cross origin resource sharing
app.use(cors())
// inject LDAP connection to express server
app.use(passport.initialize())
// listen to port defined
const port = process.env.PORT || 8085
app.listen(port, (): void => {
console.log(`Listening on port ${port}`)
})
app.post('/login', (req: express.Request, res: express.Response, next: express.NextFunction): void | Response => {
passport.authenticate('ldapauth', (err, user, info): void => {
var error = err || info
if (error)
res.send({
status: 500,
data: error
})
if (!user)
res.send({
status: 404,
data: "User Not Found"
})
else
res.send({
status: 200,
data: user
})
})(req, res, next)
})
Client Side
Your code looks correct, but the error you're getting leads me to believe you really don't have the correct username/password supplied! Are you sure you're testing with the right credentials?
As a sidenote -- if you're looking for a simpler way to do this for a big project, and don't mind spending some money, Stormpath's API service does this sort of thing for you: it basically syncs your AD / LDAP users into it's API service so you can work with them via a REST API (it's much simpler).
There are two libraries you can use to work with it:
express-stormpath
passport-stormpath
Both are pretty simple / nice to use.
this code me
phpLDAPadmin express.js and passport-ldapauth
var express = require('express'),
passport = require('passport'),
LdapStrategy = require('passport-ldapauth');
const OPTS = {
server: {
url: 'ldap://localhost:389',
bindDN: 'cn=admin,dc=ramhlocal,dc=com',
bindCredentials: 'password',
searchBase: 'dc=ramhlocal,dc=com',
searchFilter: '(uid={{username}})'
}
};
var app = express();
passport.use(new LdapStrategy(OPTS));
app.use(express.json());
app.use(express.urlencoded({extended: false}));
app.use(passport.initialize());
app.post('/login', function (req, res, next){
passport.authenticate('ldapauth', {session: false}, function(err, user, info) {
var error = err || info
console.log(user);
if (error)
res.send({
status: 500,
data: error
})
if (! user) {
res.send({
status: 404,
data: "User Not Found"
})
}
res.send({
status: 200,
data: user
})
})(req, res,next)
})
app.listen(8080);
enter image description here

NodeJs Passport isAuthenticated() returning false even after login

I'm new to Angular.js and trying to build local authentication for a website. I have gone through various sources and Authentication in Single Page Applications was very helpful. When I tried build the same in my localhost my code went in to a loop.
app.post('/login',.....) is returning user in the response but after that while loading the admin page it is checking whether the user is logged in by calling app.get('/loggedin',... ) and req.isAuthenticated() is returning false even after login and it goes to a loop. I can't understand why this is happening please help me.
Server Side code
var express = require('express');
var http = require('http');
var path = require('path');
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
//==================================================================
// Define the strategy to be used by PassportJS
passport.use(new LocalStrategy(
function(username, password, done) {
if (username === "admin" && password === "admin") // stupid example
return done(null, {name: "admin"});
return done(null, false, { message: 'Incorrect username.' });
}
));
// Serialized and deserialized methods when got from session
passport.serializeUser(function(user, done) {
done(null, user);
});
passport.deserializeUser(function(user, done) {
done(null, user);
});
// Define a middleware function to be used for every secured routes
var auth = function(req, res, next){
if (!req.isAuthenticated())
res.send(401);
else
next();
};
//==================================================================
// Start express application
var app = express();
// all environments
app.set('port', process.env.PORT || 3000);
app.use(express.favicon());
app.use(express.cookieParser());
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.session({ secret: 'securedsession' }));
app.use(passport.initialize()); // Add passport initialization
app.use(passport.session()); // Add passport initialization
app.use(app.router);
app.all('*', function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
// development only
if ('development' == app.get('env')) {
app.use(express.errorHandler());
}
//==================================================================
// routes
app.get('/', function(req, res){
res.render('index', { title: 'Express' });
});
app.get('/users', auth, function(req, res){
res.send([{name: "user1"}, {name: "user2"}]);
});
//==================================================================
//==================================================================
// route to test if the user is logged in or not
app.get('/loggedin', function(req, res) {
res.send(req.isAuthenticated() ? req.user : '0');
});
// route to log in
app.post('/login', passport.authenticate('local'), function(req, res) {
res.send(req.user);
});
// route to log out
app.post('/logout', function(req, res){
req.logOut();
res.send(200);
});
//==================================================================
http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
Client Side Js file
'use strict';
/**********************************************************************
* Angular Application
**********************************************************************/
var app = angular.module('app', ['ngResource','ngRoute'])
.config(function($routeProvider, $locationProvider, $httpProvider) {
//================================================
// Check if the user is connected
//================================================
var checkLoggedin = function($q, $timeout, $http, $location, $rootScope){
// Initialize a new promise
var deferred = $q.defer();
// Make an AJAX call to check if the user is logged in
$http.get('http://localhost:3000/loggedin').success(function(user){
// Authenticated
if (user !== '0')
$timeout(deferred.resolve, 0);
// Not Authenticated
else {
$rootScope.message = 'You need to log in.';
$timeout(function(){deferred.reject();}, 0);
$location.url('/login');
}
});
return deferred.promise;
};
//================================================
//================================================
// Add an interceptor for AJAX errors
//================================================
$httpProvider.responseInterceptors.push(function($q, $location) {
return function(promise) {
return promise.then(
// Success: just return the response
function(response){
return response;
},
// Error: check the error status to get only the 401
function(response) {
if (response.status === 401)
$location.url('/login');
return $q.reject(response);
}
);
}
});
//================================================
//================================================
// Define all the routes
//================================================
$routeProvider
.when('/', {
templateUrl: 'views/main.html'
})
.when('/admin', {
templateUrl: 'views/admin.html',
controller: 'AdminCtrl',
resolve: {
loggedin: checkLoggedin
}
})
.when('/login', {
templateUrl: 'views/login.html',
controller: 'LoginCtrl'
})
.otherwise({
redirectTo: '/login'
});
//================================================
}) // end of config()
.run(function($rootScope, $http){
$rootScope.message = '';
// Logout function is available in any pages
$rootScope.logout = function(){
$rootScope.message = 'Logged out.';
$http.post('http://localhost:3000/logout');
};
});
/**********************************************************************
* Login controller
**********************************************************************/
app.controller('LoginCtrl', function($scope, $rootScope, $http, $location) {
// This object will be filled by the form
$scope.user = {};
// Register the login() function
$scope.login = function(){
$http.post('http://localhost:3000/login', {
username: $scope.user.username,
password: $scope.user.password,
})
.success(function(user){
// No error: authentication OK
$rootScope.message = 'Authentication successful!';
$location.url('/admin');
})
.error(function(){
// Error: authentication failed
$rootScope.message = 'Authentication failed.';
$location.url('/login');
});
};
});
/**********************************************************************
* Admin controller
**********************************************************************/
app.controller('AdminCtrl', function($scope, $http) {
// List of users got from the server
$scope.users = [];
// Fill the array to display it in the page
$http.get('http://localhost:3000/users').success(function(users){
for (var i in users)
$scope.users.push(users[i]);
});
});
You need to allow cookies to be set in cross domain
In express
res.header('Access-Control-Allow-Credentials', true);
And in ajax setup
xhrFields: {
withCredentials: true
}
You can find relevant answers here and here
I think rdegges has part of the idea since cookies and session variables are part of what makes the state management work. I think that bodyParser is also required but I omitted it here.
I'm using Passport on my website (authenticating to a MongoDB users table) and here are excerpts from my code.
/server.js:
var cookieParser = require('cookie-parser');
...
var passport = require('passport');
var expressSession = require('express-session');
var initPassport = require('./passport/init');
initPassport(passport);
...
self.app.use(cookieParser());
self.app.use(expressSession({secret: 'MYSECRETISVERYSECRET', saveUninitialized: true, resave: true}));
self.app.use(passport.initialize());
self.app.use(passport.session());
...
var routes = require('./routes/index')(passport);
self.app.use('/', routes);
/passport/init.js:
var login = require('./login');
var signup = require('./register');
var User = require('../models/user');
module.exports = function(passport) {
// Passport needs to be able to serialize and deserialize users to support persistent login sessions
passport.serializeUser(function(user, done) {
console.log('serializing user: ');
console.log(user);
done(null, user._id);
});
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user) {
console.log('deserializing user:', user);
done(err, user);
});
});
// Setting up Passport Strategies for Login and SignUp/Registration
login(passport);
signup(passport);
}
/routes/index.js:
var passport = require('passport');
var User = require('../models/user');
...
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())
return next();
// if the user is not authenticated then redirect him to the login page
res.redirect('/login');
}
For what it's worth I'm not seeing your isValidated() function anywhere defined.
Can be so many things.
1.) Order as in PassportJS Facebook login isAuthenticated returns false even though authentication succeeds (order seems correct though in your case).
2.) No req.login() as in Passport and Passport Local req.isAuthenticated always returns false
In this case I opt for the latter but for a different reason than in that question.
You have provided your own LocalStrategy. To make the user log in, you will have to call req.login() yourself. Just as if you would define your own custom callback, as described in the passport documentation: http://passportjs.org/guide/authenticate/.
I had the same issue by forgetting to add
request.login()
on
app.post('/login',
function(request, response, next) {
console.log(request.session)
passport.authenticate('login',
function(err, user, info) {
if(!user){ response.send(info.message);}
else{
request.login(user, function(error) {
if (error) return next(error);
console.log("Request Login supossedly successful.");
return response.send('Login successful');
});
//response.send('Login successful');
}
})(request, response, next);
}
);
also make sure you have the following order for initialization
var session = require('express-session');
// required for passport session
app.use(session({
secret: 'secrettexthere',
saveUninitialized: true,
resave: true,
// using store session on MongoDB using express-session + connect
store: new MongoStore({
url: config.urlMongo,
collection: 'sessions'
})
}));
// Init passport authentication
app.use(passport.initialize());
// persistent login sessions
app.use(passport.session());
Is your browser keeping your session cookie around? It sounds to me as if your browser isn't holding onto your session cookie after login, which is why subsequent requests to /loggedin are failing.
In my case I tried solution suggested by JMeas to manually call session saving, but it didn't work
https://github.com/jaredhanson/passport/issues/482
req.session.save(function() { successRedirect(); })
After some experiments, I just moved app.use(session({ ... })) at the top of all middleware calls and now req.isAuthenticated() works as expected. I presume, session setup should go as the first middleware or at least before setting cookies.
Broken call :
var app = express();
app.use(query.json());
app.use(query.urlencoded({ extended: false }));
app.use(cookies());
app.use(express.static(path.join(__dirname, 'public')));
app.use(passport.initialize());
app.use(passport.session());
app.use(session({
secret: 'card',
resave: true,
saveUninitialized: true
}));
app.use('/', routes); // this is where I call passport.authenticate()
Fixed call :
app.use(session({
secret: 'card',
resave: true,
saveUninitialized: true
}));
app.use(query.json());
app.use(query.urlencoded({ extended: false }));
app.use(cookies());
app.use(express.static(path.join(__dirname, 'public')));
app.use(passport.initialize());
app.use(passport.session());
app.use('/', routes);

Resources