Skip to content

Commit

Permalink
Moves auth to one pleace, cleans up auth straragies (openhab#60)
Browse files Browse the repository at this point in the history
Signed-off-by: Dan Cunningham <[email protected]>
  • Loading branch information
digitaldan authored Mar 13, 2017
1 parent 1764721 commit d276743
Show file tree
Hide file tree
Showing 3 changed files with 198 additions and 232 deletions.
124 changes: 35 additions & 89 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ var flash = require('connect-flash'),
cronJob = require('cron').CronJob,
appleSender = require('./aps-helper'),
oauth2 = require('./oauth2'),
auth = require('./auth.js'),
Limiter = require('ratelimiter');


Expand Down Expand Up @@ -226,28 +227,6 @@ every5MinStatJob.start();
// Create http server
var server = http.createServer(app);


// Local authentication strategy for passportjs
passport.use(new LocalStrategy({
usernameField: 'username'
},
function (username, password, done) {
User.authenticate(username, password, function (err, user, params) {
// console.log(params);
return done(err, user, params);
});
}));

passport.serializeUser(function (user, done) {
done(null, user._id);
});

passport.deserializeUser(function (id, done) {
User.findById(id, function (err, user) {
done(err, user);
});
});

// Configure the openHAB-cloud for development or productive mode
app.configure('development', function () {
app.use(express.errorHandler());
Expand Down Expand Up @@ -366,13 +345,21 @@ var io = require('socket.io').listen(server, {
// var ioredis = require('socket.io-redis');
// io.adapter(ioredis({ host: 'localhost', port: 6379 }));

// Ensure user is authenticated
// Ensure user is authenticated for web requests
function ensureAuthenticated(req, res, next) {
if (req.isAuthenticated()) {
return next();
}
req.session.returnTo = req.originalUrl || req.url;
res.redirect('/login')
res.redirect('/login');
}

// Ensure user is authenticated for REST or proxied requets
function ensureRestAuthenticated(req, res, next) {
if (req.isAuthenticated()) {
return next();
}
return passport.authenticate(['basic','bearer'], {session: false})(req, res, next);
}

// Ensure user have 'master' role for certain routes
Expand Down Expand Up @@ -528,47 +515,6 @@ function setSessionTimezone(req, res) {
// REST routes
app.get('/api/events', ensureAuthenticated, events_routes.eventsvaluesget);

// Functions to process proxy requests to openHABs

// If the request contains a bearer token then do oauth2, otherwise try basic auth
var restAuth = function (req, res, next) {
if (req.headers['authorization'] && req.headers['authorization'].indexOf('Bearer') == 0) {
passport.authenticate('bearer', {
session: false
}, function (error, user, info) {
if (error) {
return res.status(401).json({
errors: [{
message: error
}]
});
}
if (!user) {
return res.status(401).json({
errors: [{
message: "Authentication failed"
}]
});
}
req.logIn(user, function (error) {
if (error) {
return res.status(401).json({
errors: [{
message: error
}]
});
}
return next();
});
})(req, res, next);
} else {
var ba = express.basicAuth(function (username, password, callback) {
User.authenticate(username, password, callback);
});
ba(req, res, next);
}
};

function setOpenhab(req, res, next) {
req.user.openhab(function (error, openhab) {
if (!error && openhab) {
Expand Down Expand Up @@ -832,34 +778,34 @@ function addAndroidRegistration(req, res) {
}

// Process all requests from mobile apps to openHAB
app.all('/rest*', restAuth, preassembleBody, setOpenhab, proxyRouteOpenhab);
app.all('/images/*', restAuth, preassembleBody, setOpenhab, proxyRouteOpenhab);
app.all('/static/*', restAuth, preassembleBody, setOpenhab, proxyRouteOpenhab);
app.all('/rrdchart.png*', restAuth, preassembleBody, setOpenhab, proxyRouteOpenhab);
app.all('/chart*', restAuth, preassembleBody, setOpenhab, proxyRouteOpenhab);
app.all('/openhab.app*', restAuth, preassembleBody, setOpenhab, proxyRouteOpenhab);
app.all('/WebApp*', restAuth, preassembleBody, setOpenhab, proxyRouteOpenhab);
app.all('/CMD*', restAuth, preassembleBody, setOpenhab, proxyRouteOpenhab);
app.all('/cometVisu*', restAuth, preassembleBody, setOpenhab, proxyRouteOpenhab);
app.all('/proxy*', restAuth, preassembleBody, setOpenhab, proxyRouteOpenhab);
app.all('/greent*', restAuth, preassembleBody, setOpenhab, proxyRouteOpenhab);
app.all('/jquery.*', restAuth, preassembleBody, setOpenhab, proxyRouteOpenhab);
app.all('/classicui/*', restAuth, preassembleBody, setOpenhab, proxyRouteOpenhab);
app.all('/ui/*', restAuth, preassembleBody, setOpenhab, proxyRouteOpenhab);
app.all('/basicui/*', restAuth, preassembleBody, setOpenhab, proxyRouteOpenhab);
app.all('/doc/*', restAuth, preassembleBody, setOpenhab, proxyRouteOpenhab);
app.all('/start/*', restAuth, preassembleBody, setOpenhab, proxyRouteOpenhab);
app.all('/icon*', restAuth, preassembleBody, setOpenhab, proxyRouteOpenhab);
app.all('/habmin/*', restAuth, preassembleBody, setOpenhab, proxyRouteOpenhab);
app.all('/remote*', restAuth, preassembleBody, setOpenhab, proxyRouteOpenhab);
app.all('/habpanel/*', restAuth, preassembleBody, setOpenhab, proxyRouteOpenhab);
app.all('/rest*', ensureRestAuthenticated, preassembleBody, setOpenhab, proxyRouteOpenhab);
app.all('/images/*', ensureRestAuthenticated, preassembleBody, setOpenhab, proxyRouteOpenhab);
app.all('/static/*', ensureRestAuthenticated, preassembleBody, setOpenhab, proxyRouteOpenhab);
app.all('/rrdchart.png*', ensureRestAuthenticated, preassembleBody, setOpenhab, proxyRouteOpenhab);
app.all('/chart*', ensureRestAuthenticated, preassembleBody, setOpenhab, proxyRouteOpenhab);
app.all('/openhab.app*', ensureRestAuthenticated, preassembleBody, setOpenhab, proxyRouteOpenhab);
app.all('/WebApp*', ensureRestAuthenticated, preassembleBody, setOpenhab, proxyRouteOpenhab);
app.all('/CMD*', ensureRestAuthenticated, preassembleBody, setOpenhab, proxyRouteOpenhab);
app.all('/cometVisu*', ensureRestAuthenticated, preassembleBody, setOpenhab, proxyRouteOpenhab);
app.all('/proxy*', ensureRestAuthenticated, preassembleBody, setOpenhab, proxyRouteOpenhab);
app.all('/greent*', ensureRestAuthenticated, preassembleBody, setOpenhab, proxyRouteOpenhab);
app.all('/jquery.*', ensureRestAuthenticated, preassembleBody, setOpenhab, proxyRouteOpenhab);
app.all('/classicui/*', ensureRestAuthenticated, preassembleBody, setOpenhab, proxyRouteOpenhab);
app.all('/ui/*', ensureRestAuthenticated, preassembleBody, setOpenhab, proxyRouteOpenhab);
app.all('/basicui/*', ensureRestAuthenticated, preassembleBody, setOpenhab, proxyRouteOpenhab);
app.all('/doc/*', ensureRestAuthenticated, preassembleBody, setOpenhab, proxyRouteOpenhab);
app.all('/start/*', ensureRestAuthenticated, preassembleBody, setOpenhab, proxyRouteOpenhab);
app.all('/icon*', ensureRestAuthenticated, preassembleBody, setOpenhab, proxyRouteOpenhab);
app.all('/habmin/*', ensureRestAuthenticated, preassembleBody, setOpenhab, proxyRouteOpenhab);
app.all('/remote*', ensureRestAuthenticated, preassembleBody, setOpenhab, proxyRouteOpenhab);
app.all('/habpanel/*', ensureRestAuthenticated, preassembleBody, setOpenhab, proxyRouteOpenhab);

// myOH API for mobile apps
app.all('/api/v1/notifications*', restAuth, preassembleBody, setOpenhab, api_routes.notificationsget);
app.all('/api/v1/notifications*', ensureRestAuthenticated, preassembleBody, setOpenhab, api_routes.notificationsget);

// Android app registration
app.all('/addAndroidRegistration*', restAuth, preassembleBody, setOpenhab, addAndroidRegistration);
app.all('/addAppleRegistration*', restAuth, preassembleBody, setOpenhab, addAppleRegistration);
app.all('/addAndroidRegistration*', ensureRestAuthenticated, preassembleBody, setOpenhab, addAndroidRegistration);
app.all('/addAppleRegistration*', ensureRestAuthenticated, preassembleBody, setOpenhab, addAppleRegistration);

function sendSimpleNotificationToUser(user, message) {
sendNotificationToUser(user, message, '', '');
Expand Down
116 changes: 90 additions & 26 deletions auth.js
Original file line number Diff line number Diff line change
@@ -1,44 +1,108 @@
var passport = require('passport')
, LocalStrategy = require('passport-local').Strategy
, BasicStrategy = require('passport-http').BasicStrategy
, ClientPasswordStrategy = require('passport-oauth2-client-password').Strategy
, BearerStrategy = require('passport-http-bearer').Strategy
, User = require('./models/user');
var passport = require('passport'),
LocalStrategy = require('passport-local').Strategy,
BasicStrategy = require('passport-http').BasicStrategy,
ClientPasswordStrategy = require('passport-oauth2-client-password').Strategy,
BearerStrategy = require('passport-http-bearer').Strategy,
OAuth2Client = require('./models/oauth2client'),
OAuth2Token = require('./models/oauth2token'),
User = require('./models/user');


// Local authentication strategy for passportjs
// Local authentication strategy for passportjs, used for web logins
passport.use(new LocalStrategy({
usernameField: 'username'},
function(username, password, done){
User.authenticate(username, password, function(err, user, params) {
usernameField: 'username'
},
function (username, password, done) {
User.authenticate(username, password, function (err, user, params) {
return done(err, user, params);
});
}));

passport.serializeUser(function(user, done) {
done(null, user._id);
});

passport.deserializeUser(function(id, done) {
User.findById(id, function (err, user) {
done(err, user);
});
});

passport.use(new BasicStrategy(
function(username, password, done) {
// standard basic authentication strategy, used for REST based logins
passport.use(new BasicStrategy(
function (username, password, done) {
User.authenticate(username, password, function (err, user, params) {
return done(err, user, params);
});
}
));

// authentication strategy used by oauth clients, usess a custom name 'oAuthBasic'
passport.use('oAuthBasic' , new BasicStrategy(
function (username, password, done) {
OAuth2Client.findOne({
clientId: username
}, function (error, client) {
if (error) {
return done(error);
}
if (!client) {
return done(null, false);
}
if (client.clientSecret != password) {
return done(null, false);
}
return done(null, client);
});
}
));

// A client-password strategy for authorizing requests for tokens
passport.use(new ClientPasswordStrategy(
function(clientId, clientSecret, done) {

function (clientId, clientSecret, done) {
OAuth2Client.findOne({
clientId: clientId
}, function (error, client) {
if (error) {
return done(error);
}
if (!client) {
return done(null, false);
}
if (client.clientSecret != clientSecret) {
return done(null, false);
}
return done(null, client);
});
}
));

// A bearer strategy to authorize API requests by oauth2code
passport.use(new BearerStrategy(
function(accessToken, done) {

function (accessToken, done) {
OAuth2Token.findOne({
token: accessToken
}, function (error, oauth2token) {
if (error) {
return done(error);
}
if (!oauth2token) {
return done(null, false);
}
User.findOne({
_id: oauth2token.user
}, function (error, openhabUser) {
if (error) {
return done(error);
}
if (!openhabUser) {
return done(null, false);
}
var info = {
scope: oauth2token.scope
};
done(null, openhabUser, info);
});
});
}
));

passport.serializeUser(function (user, done) {
done(null, user._id);
});

passport.deserializeUser(function (id, done) {
User.findById(id, function (err, user) {
done(err, user);
});
});
Loading

0 comments on commit d276743

Please sign in to comment.