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
Related
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.
I've having issues with both my routes and getting/saving the data with mongodb. It seems to have validation errors when saving or maybe not posting JSON. Any ideas?
Here's my mongoose schema:
// grab the things we need
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
// create a schema
var sitesEntrySchema = new Schema({
ip: {
type: String,
required: true,
trim: true
},
domain: {
type: String,
required: true,
trim: true
},
wp: {
type: String,
required: true,
trim: true
},
host_name: {
type: String,
required: true
},
hosted: {
type: Number,
required: true
}
});
// make this available to our users in our Node applications
var Site = mongoose.model('Site', sitesEntrySchema);
module.exports = Site;
And my angular http request
var app = angular.module('myApp', []);
app.controller('MainCtrl', function($scope, $http) {
$http.get('/api/mongo')
.then(function(response) {
console.log(response.data);
$scope.myData = response.data;
});
});
app.controller('FormCtrl', function($scope, $http) {
$scope.formData = {};
$scope.addSite = function() {
$http.post('/api/create', $scope.formData)
.success(function(data) {
console.log($scope.formData);
$scope.formData = {}; // clear the form so our user is ready to enter another
swal(
'Good job!',
'Site was added!',
'success'
);
})
.error(function(data) {
console.log('Error: ' + data);
});
};
});
My express routes:
var express = require('express');
var router = express.Router();
var Site = require('../models/site');
//Return From Mongo
router.get('/api/mongo', function(req, res) {
Site.find({}, function(err, sites) {
if (err)
res.send(err)
res.send(sites);
});
//res.json({"yo": "yo this shit works"});
});
//Add A Site
router.post('/api/create', function(req, res, next) {
//create object with form input
var siteData = {
ip: req.body.ip,
domain: req.body.domain,
wp: req.body.wp,
host_name: req.body.host_name,
hosted: req.body.hosted
};
// use schema's 'create' method to insert doc into mongo
Site.create(siteData, function(error) {
if (error) {
//return next(error);
res.send(error);
} else {
return res.json({ message: 'Site added!' });
}
});
});
Without specific outputs that show what is going wrong, here are a few things stick out to me. The first is not always responding with json. You should also try using next() to handle your errors since Express will make sure to send back a correct error response. With these changes, your get route looks like:
//Return From Mongo
router.get('/api/mongo', function(req, res, next) {
Site.find({}, function(err, sites) {
if (err) {
next(err)
} else {
return res.json(sites);
}
});
});
Secondly, It is best practice to return the newly created resource, so your create route should look like
//Add A Site
router.post('/api/create', function(req, res, next) {
//create object with form input
var siteData = {
ip: req.body.ip,
domain: req.body.domain,
wp: req.body.wp,
host_name: req.body.host_name,
hosted: req.body.hosted
};
// use schema's 'create' method to insert doc into mongo
Site.create(siteData, function(error, site) {
if (error) {
next(error);
} else {
return res.json(site);
}
});
});
In addition, depending on your version of Angular, you might be using the deprecated promise syntax for the post request. You should be using .then(), not .success() and .error(). This might also be causing an issue.
Lastly, you should try your best to follow REST guidelines for your routes and responses. It will make it much easier to extend your web app and will keep you more organized. Here is a good Express/Node resource for that https://scotch.io/tutorials/build-a-restful-api-using-node-and-express-4.
ADDED: Here is an example of how you can log your errors depending on production/development environments
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
console.log('err:', err.status, err.message);
res.status(err.status || 500);
res.json({message: err.messages});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
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);
});
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);
I am new to PassportJS and AngularJS and I have a doubt about how to proceed with this authorization.
I have Spring REST API Secured by Oauth2, but I have to send together user credentials like this:
[http://localhost:8080/myapp/oauth/token]
grant_type=password&username=email&password=password&client_id=09e749d8309f4044&client_secret=189309492722aa5a&scope=read
In client my application I use passport and I want to authorize/authenticate my users, how can I create a Stratagy for this ?
I will send here my server config and my security Lib.
Server.js
var fs = require('fs');
var http = require('http');
var https = require('https');
var privateKey = fs.readFileSync(__dirname + '/cert/privatekey.pem').toString();
var certificate = fs.readFileSync(__dirname + '/cert/certificate.pem').toString();
var credentials = {key: privateKey, cert: certificate};
var express = require('express');
var config = require('./config.js');
var passport = require('passport');
var security = require('./lib/security');
var xsrf = require('./lib/xsrf');
var protectJSON = require('./lib/protectJSON');
require('express-namespace');
var app = express();
var secureServer = https.createServer(credentials, app);
var server = http.createServer(app);
// Serve up the favicon
app.use(express.favicon(config.server.distFolder + '/favicon.ico'));
// First looks for a static file: index.html, css, images, etc.
app.use(config.server.staticUrl, express.compress());
app.use(config.server.staticUrl, express['static'](config.server.distFolder));
app.use(config.server.staticUrl, function(req, res, next) {
res.send(404); // If we get here then the request for a static file is invalid
});
app.use(protectJSON);
app.use(express.logger()); // Log requests to the console
app.use(express.bodyParser()); // Extract the data from the body of the request - this is needed by the LocalStrategy authenticate method
app.use(express.cookieParser(config.server.cookieSecret)); // Hash cookies with this secret
app.use(express.cookieSession()); // Store the session in the (secret) cookie
app.use(passport.initialize()); // Initialize PassportJS
app.use(passport.session()); // Use Passport's session authentication strategy - this stores the logged in user in the session and will now run on any request
app.use(xsrf); // Add XSRF checks to the request
security.initialize(config.oauth.authorize_url, config.oauth.access_token, config.oauth.apiKey, config.oauth.secretKey, config.oauth.scopereq); // Add a Oauth strategy for handling the authentication
app.use(function(req, res, next) {
if ( req.user ) {
console.log('Current User:', req.user.firstName, req.user.lastName);
} else {
console.log('Unauthenticated');
}
next();
});
app.post('/login', security.login);
app.post('/logout', security.logout);
// Retrieve the current user
app.get('/current-user', security.sendCurrentUser);
// Retrieve the current user only if they are authenticated
app.get('/authenticated-user', function(req, res) {
security.authenticationRequired(req, res, function() { security.sendCurrentUser(req, res); });
});
// Retrieve the current user only if they are admin
app.get('/admin-user', function(req, res) {
security.adminRequired(req, res, function() { security.sendCurrentUser(req, res); });
});
// This route deals enables HTML5Mode by forwarding missing files to the index.html
app.all('/*', function(req, res) {
// Just send the index.html for other files to support HTML5Mode
res.sendfile('index.html', { root: config.server.distFolder });
});
// A standard error handler - it picks up any left over errors and returns a nicely formatted server 500 error
app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
// Start up the server on the port specified in the config
server.listen(config.server.listenPort, 'localhost', 511, function() {
// // Once the server is listening we automatically open up a browser
var open = require('open');
open('http://localhost:' + config.server.listenPort + '/');
});
console.log('Deengo Business App Server - listening on port: ' + config.server.listenPort);
secureServer.listen(config.server.securePort);
console.log('Deengo Business App Server - listening on secure port: ' + config.server.securePort);
lib/security.js
var express = require('express');
var passport = require('passport');
var app = express();
var BearerStrategy = require('passport-http-bearer').Strategy
var filterUser = function(user) {
if ( user ) {
return {
user : {
id: user._id.$oid,
email: user.email,
firstName: user.firstName,
lastName: user.lastName,
admin: user.admin
}
};
} else {
return { user: null };
}
};
var security = {
initialize: function(_authorize_url, _access_token, _apiKey, _secretKey, _scopereq) {
passport.use('deengo-auth', new OAuth2Strategy({
authorizationURL: _authorize_url,
tokenURL: _access_token,
clientID: _apiKey,
clientSecret: _secretKey,
callbackURL: 'http://localhost:3000/oauth/autorize/callback',
scope: _scopereq,
passReqToCallback: true,
skipUserProfile: true
},
function(req, accessToken, refreshToken, profile, done) {
client['headers']['authorization'] = 'bearer ' + req.session.passport.accessToken;
User.findOrCreate({ clientId: clientId }, function(err, user) {
done(err, user);
});
}
));
},
authenticationRequired: function(req, res, next) {
console.log('authRequired');
if (req.isAuthenticated()) {
next();
} else {
res.json(401, filterUser(req.user));
}
},
adminRequired: function(req, res, next) {
console.log('adminRequired');
if (req.user && req.user.admin ) {
next();
} else {
res.json(401, filterUser(req.user));
}
},
sendCurrentUser: function(req, res, next) {
res.json(200, filterUser(req.user));
res.end();
},
login: function(req, res, next) {
console.log(req.body.email);
console.log(req.body.password);
function authenticationFailed(err, user, info){
//if (err) { return next(err); }
/*if (!user) { return res.json(filterUser(user)); }
req.logIn(user, function(err) {
if ( err ) { return next(err); }
return res.json(filterUser(user));
});*/
}
//passport.authenticate("deengo-auth", authenticationFailed)(req, res, next);
return null;
},
logout: function(req, res, next) {
req.logout();
res.send(204);
}
};
module.exports = security;
lib/DeengoStrategy.js
var util = require('util');
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var BearerStrategy = require('passport-http-bearer').Strategy;
var rest = require('request');
function DeengoRestStrategy(authorize_url, access_token, apiKey, secretKey, scopereq) {
this.authorize_url = authorize_url;
this.access_token = access_token;
this.apiKey = apiKey;
this.secretKey = secretKey;
this.scopereq = secretKey;
this.baseUrl = 'http://localhost:8080/deengo/api/';
// Call the super constructor - passing in our user verification function
// We use the email field for the username
LocalStrategy.call(this, { usernameField: 'email' }, this.verifyUser.bind(this));
// Serialize the user into a string (id) for storing in the session
passport.serializeUser(function(user, done) {
done(null, user.id);
});
// Deserialize the user from a string (id) into a user (via a cll to REST)
passport.deserializeUser(this.get.bind(this));
// We want this strategy to have a nice name for use by passport, e.g. app.post('/login', passport.authenticate('deengo'));
this.name = DeengoRestStrategy.name;
}
// DeengoRestStrategy inherits from LocalStrategy
util.inherits(DeengoRestStrategy, LocalStrategy);
DeengoRestStrategy.name = "deengo";
// Query the users collection
DeengoRestStrategy.prototype.query = function(query, done) {
query.accessToken = this.accessToken; // Add the apiKey to the passed in query
var request = rest.get(this.baseUrl, { qs: query, json: {} }, function(err, response, body) {
done(err, body);
});
};
// Get a user by id
DeengoRestStrategy.prototype.get = function(id, done) {
var query = { apiKey: this.apiKey };
var request = rest.get(this.baseUrl + id, { qs: query, json: {} }, function(err, response, body) {
done(err, body);
});
};
// Find a user by their email
DeengoRestStrategy.prototype.findByEmail = function(email, done) {
this.query({ q: JSON.stringify({email: email}) }, function(err, result) {
if ( result && result.length === 1 ) {
return done(err, result[0]);
}
done(err, null);
});
};
// Check whether the user passed in is a valid one
DeengoRestStrategy.prototype.verifyUser = function(email, password, done) {
this.findByEmail(email, function(err, user) {
if (!err && user) {
if (user.password !== password) {
user = null;
}
}
done(err, user);
});
};
module.exports = DeengoRestStrategy;
I do not know if I have to use passport-Bearer or not and how to use-it.
Thanks in advance for any help.
Regards,
Eduardo.
I do not know if I have to use passport-Bearer or not and how to use-it.
No. There are other options, such as:
oauth.io
httpProvider + express middleware
Here is an example of how to use passport:
// Express using passport-local
// This code is adaptation of examples/express3 from https://github.com/jaredhanson/passport-local
// configure Express
app.configure(function() {
// ...
app.use(express.session({
// The domain should start with a dot, as this allows the subdomain.
domain: '.app.local',
secret: 'keyboard cat'
}));
// Enable cors.
app.use(function(req, res, next) {
res.header('Access-Control-Allow-Credentials', true);
res.header('Access-Control-Allow-Origin', req.headers.origin);
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.header('Access-Control-Allow-Headers', 'X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept');
next();
});
// ...
});
app.get('/account', ensureAuthenticated, function(req, res){
// Return the current user's info
res.json(req.user);
});
References
Express + AngularJS Subdomain login