mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
Tie auth middleware to needsPermission api
This commit is contained in:
parent
3ef6f29d6e
commit
c31ffb98b0
@ -23,6 +23,7 @@
|
||||
"dependencies": {
|
||||
"express": "3.17.2",
|
||||
"when": "3.4.6",
|
||||
"bcryptjs": "2.1.0",
|
||||
"nopt": "3.0.1",
|
||||
"mqtt": "0.3.x",
|
||||
"ws": "0.4.32",
|
||||
|
@ -20,8 +20,9 @@ var oauth2orize = require("oauth2orize");
|
||||
var strategies = require("./strategies");
|
||||
var Tokens = require("./tokens");
|
||||
var Users = require("./users");
|
||||
var permissions = require("./permissions");
|
||||
|
||||
var settings = require("../../settings");
|
||||
var settings = null;
|
||||
var log = require("../../log");
|
||||
|
||||
|
||||
@ -33,23 +34,30 @@ var server = oauth2orize.createServer();
|
||||
|
||||
server.exchange(oauth2orize.exchange.password(strategies.passwordTokenExchange));
|
||||
|
||||
function init() {
|
||||
function init(_settings) {
|
||||
settings = _settings;
|
||||
if (settings.adminAuth) {
|
||||
Users.init(settings.adminAuth);
|
||||
Tokens.init(settings)
|
||||
}
|
||||
}
|
||||
|
||||
function authenticate(req,res,next) {
|
||||
function needsPermission(permission) {
|
||||
return function(req,res,next) {
|
||||
if (settings.adminAuth) {
|
||||
if (/^\/auth\/.*/.test(req.originalUrl)) {
|
||||
next();
|
||||
} else {
|
||||
return passport.authenticate(['bearer','anon'], { session: false })(req,res,next);
|
||||
return passport.authenticate(['bearer','anon'],{ session: false })(req,res,function() {
|
||||
if (!req.user) {
|
||||
return next();
|
||||
}
|
||||
if (permissions.hasPermission(req.user,permission)) {
|
||||
return next();
|
||||
}
|
||||
return res.send(401);
|
||||
});
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function ensureClientSecret(req,res,next) {
|
||||
@ -83,7 +91,7 @@ function revoke(req,res) {
|
||||
|
||||
module.exports = {
|
||||
init: init,
|
||||
authenticate: authenticate,
|
||||
needsPermission: needsPermission,
|
||||
ensureClientSecret: ensureClientSecret,
|
||||
authenticateClient: authenticateClient,
|
||||
getToken: getToken,
|
||||
|
@ -19,18 +19,6 @@ var util = require('util');
|
||||
var readRE = /^((.+)\.)?read$/
|
||||
var writeRE = /^((.+)\.)?write$/
|
||||
|
||||
function needsPermission(perm) {
|
||||
return function(req,res,next) {
|
||||
if (!req.user) {
|
||||
return next();
|
||||
}
|
||||
if (hasPermission(req.user,perm)) {
|
||||
return next();
|
||||
}
|
||||
return res.send(401);
|
||||
}
|
||||
}
|
||||
|
||||
function hasPermission(user,permission) {
|
||||
if (!user.permissions) {
|
||||
return false;
|
||||
@ -45,6 +33,4 @@ function hasPermission(user,permission) {
|
||||
|
||||
module.exports = {
|
||||
hasPermission: hasPermission,
|
||||
needsPermission: needsPermission,
|
||||
|
||||
}
|
||||
|
@ -15,30 +15,8 @@
|
||||
**/
|
||||
|
||||
var when = require("when");
|
||||
var crypto = require("crypto");
|
||||
var util = require("util");
|
||||
/*
|
||||
adminAuth: {
|
||||
type: "credentials",
|
||||
users: [{
|
||||
username: "nol",
|
||||
password: "5f4dcc3b5aa765d61d8327deb882cf99" // password
|
||||
permissions: "* read write"
|
||||
}],
|
||||
default: {
|
||||
permissions: "* read write"
|
||||
}
|
||||
},
|
||||
|
||||
adminAuth: {
|
||||
type: "credentials",
|
||||
users: function(username) {return when.resolve(user)},
|
||||
authenticate: function(username,password) { return when.resolve(user);}
|
||||
default: function() { return when.resolve(defaultUser) }
|
||||
}
|
||||
*/
|
||||
|
||||
//{username:"nick",password:crypto.createHash('md5').update("foo",'utf8').digest('hex')}
|
||||
var bcrypt = require('bcryptjs');
|
||||
|
||||
var users = {};
|
||||
var passwords = {};
|
||||
@ -47,10 +25,11 @@ var defaultUser = null;
|
||||
function authenticate(username,password) {
|
||||
var user = users[username];
|
||||
if (user) {
|
||||
var pass = crypto.createHash('md5').update(password,'utf8').digest('hex');
|
||||
if (pass == passwords[username]) {
|
||||
return when.resolve(user);
|
||||
}
|
||||
return when.promise(function(resolve,reject) {
|
||||
bcrypt.compare(password, passwords[username], function(err, res) {
|
||||
resolve(res?user:null);
|
||||
});
|
||||
});
|
||||
}
|
||||
return when.resolve(null);
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ var library = require("./library");
|
||||
var info = require("./info");
|
||||
|
||||
var auth = require("./auth");
|
||||
var needsPermission = require("./auth/permissions").needsPermission;
|
||||
var needsPermission = auth.needsPermission;
|
||||
|
||||
var settings = require("../settings");
|
||||
|
||||
@ -38,7 +38,7 @@ var errorHandler = function(err,req,res,next) {
|
||||
|
||||
function init(adminApp) {
|
||||
|
||||
auth.init();
|
||||
auth.init(settings);
|
||||
|
||||
// Editor
|
||||
if (!settings.disableEditor) {
|
||||
@ -55,7 +55,6 @@ function init(adminApp) {
|
||||
if (settings.adminAuth) {
|
||||
//TODO: all passport references ought to be in ./auth
|
||||
adminApp.use(passport.initialize());
|
||||
adminApp.use(auth.authenticate);
|
||||
adminApp.post("/auth/token",
|
||||
auth.ensureClientSecret,
|
||||
auth.authenticateClient,
|
||||
|
@ -17,10 +17,11 @@
|
||||
var redApp = null;
|
||||
var storage = require("../storage");
|
||||
var log = require("../log");
|
||||
var needsPermission = require("./auth").needsPermission;
|
||||
|
||||
function createLibrary(type) {
|
||||
if (redApp) {
|
||||
redApp.get(new RegExp("/library/"+type+"($|\/(.*))"),function(req,res) {
|
||||
redApp.get(new RegExp("/library/"+type+"($|\/(.*))"),needsPermission("library.read"),function(req,res) {
|
||||
var path = req.params[1]||"";
|
||||
storage.getLibraryEntry(type,path).then(function(result) {
|
||||
if (typeof result === "string") {
|
||||
@ -42,7 +43,7 @@ function createLibrary(type) {
|
||||
});
|
||||
});
|
||||
|
||||
redApp.post(new RegExp("/library/"+type+"\/(.*)"),function(req,res) {
|
||||
redApp.post(new RegExp("/library/"+type+"\/(.*)"),needsPermission("library.write"),function(req,res) {
|
||||
var path = req.params[0];
|
||||
var fullBody = '';
|
||||
req.on('data', function(chunk) {
|
||||
|
@ -23,7 +23,7 @@ var util = require("./util");
|
||||
var fs = require("fs");
|
||||
var settings = require("./settings");
|
||||
var credentials = require("./nodes/credentials");
|
||||
var permissions = require("./api/auth/permissions");
|
||||
var auth = require("./api/auth");
|
||||
|
||||
var path = require('path');
|
||||
|
||||
@ -52,7 +52,7 @@ var RED = {
|
||||
settings:settings,
|
||||
util: util,
|
||||
auth: {
|
||||
needsPermission: permissions.needsPermission
|
||||
needsPermission: auth.needsPermission
|
||||
},
|
||||
version: function () {
|
||||
var p = require(path.join(process.env.NODE_RED_HOME,"package.json"));
|
||||
|
@ -27,59 +27,6 @@ var settings = require("../../../../red/settings");
|
||||
|
||||
|
||||
describe("api auth middleware",function() {
|
||||
describe("authenticate",function() {
|
||||
it("does not trigger on auth paths", sinon.test(function(done) {
|
||||
this.stub(passport,"authenticate",function() {
|
||||
return function() {
|
||||
settings.reset();
|
||||
done(new Error("authentication not applied to auth path"));
|
||||
}
|
||||
});
|
||||
settings.init({adminAuth:{}});
|
||||
var req = {
|
||||
originalUrl: "/auth/token"
|
||||
};
|
||||
auth.authenticate(req,null,function() {
|
||||
settings.reset();
|
||||
done();
|
||||
});
|
||||
|
||||
}));
|
||||
it("does trigger on non-auth paths", sinon.test(function(done) {
|
||||
this.stub(passport,"authenticate",function() {
|
||||
return function() {
|
||||
settings.reset();
|
||||
done();
|
||||
}
|
||||
});
|
||||
settings.init({adminAuth:{}});
|
||||
var req = {
|
||||
originalUrl: "/"
|
||||
};
|
||||
auth.authenticate(req,null,function() {
|
||||
settings.reset();
|
||||
done(new Error("authentication applied to non-auth path"));
|
||||
});
|
||||
|
||||
}));
|
||||
it("does not trigger on non-auth paths with auth disabled", sinon.test(function(done) {
|
||||
this.stub(passport,"authenticate",function() {
|
||||
return function() {
|
||||
settings.reset();
|
||||
done(new Error("authentication applied when disabled"));
|
||||
}
|
||||
});
|
||||
settings.init({});
|
||||
var req = {
|
||||
originalUrl: "/"
|
||||
};
|
||||
auth.authenticate(req,null,function() {
|
||||
settings.reset();
|
||||
done();
|
||||
});
|
||||
|
||||
}));
|
||||
});
|
||||
|
||||
describe("ensureClientSecret", function() {
|
||||
it("leaves client_secret alone if not present",function(done) {
|
||||
|
@ -35,27 +35,4 @@ describe("Auth permissions", function() {
|
||||
permissions.hasPermission({permissions:"read"},"node.write").should.be.false;
|
||||
});
|
||||
});
|
||||
|
||||
describe("needsPermission middleware", function() {
|
||||
it('passes if no user on request',function(done) {
|
||||
var needsPermission = permissions.needsPermission("*");
|
||||
needsPermission({},null,function() {
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('passes if user has required permission',function(done) {
|
||||
var needsPermission = permissions.needsPermission("read");
|
||||
needsPermission({user:{permissions:"read"}},null,function() {
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('rejects if user does not have required permission',function(done) {
|
||||
var needsPermission = permissions.needsPermission("write");
|
||||
needsPermission({user:{permissions:"read"}},{send: function(code) {
|
||||
code.should.equal(401);
|
||||
done();
|
||||
}},null);
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
@ -27,7 +27,8 @@ describe("Users", function() {
|
||||
type:"credentials",
|
||||
users:[{
|
||||
username:"fred",
|
||||
password:"5f4dcc3b5aa765d61d8327deb882cf99", // 'password'
|
||||
password:'$2a$08$LpYMefvGZ3MjAfZGzcoyR.1BcfHh4wy4NpbN.cEny5aHnWOqjKOXK',
|
||||
// 'password' -> require('bcryptjs').hashSync('password', 8);
|
||||
permissions:"*"
|
||||
}]
|
||||
});
|
||||
|
@ -24,6 +24,7 @@ var app = express();
|
||||
var RED = require("../../../red/red.js");
|
||||
var storage = require("../../../red/storage");
|
||||
var library = require("../../../red/api/library");
|
||||
var auth = require("../../../red/api/auth");
|
||||
|
||||
describe("library api", function() {
|
||||
|
||||
@ -166,6 +167,7 @@ describe("library api", function() {
|
||||
app = express();
|
||||
app.use(express.json());
|
||||
library.init(app);
|
||||
auth.init({});
|
||||
RED.library.register("test");
|
||||
});
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user