TotallyInformation / node-red-contrib-uibuilder

Easily create data-driven web UI's for Node-RED using any (or no) front-end framework.
https://totallyinformation.github.io/node-red-contrib-uibuilder/#/
Apache License 2.0
454 stars 86 forks source link

authenticate with passport #50

Closed simon86de closed 5 years ago

simon86de commented 5 years ago

im just trying to implement some basic authentication to my uibuilder dashboard. did somebody already get this work? my actual uibuilder section from settings.js looks like:

uibuilder: {
        debug: true,        
        middleware: function(req,res,next) {
            var passport= require('passport')
            var LocalStrategy= require('passport-local').Strategy
            passport.use(new LocalStrategy(
                function(username, password, done) {
                if (username === 'admin' && password === 'secret') {
                    return done(null, {name: 'admin'});
                }
                    return done(null, false);
                }
            ))
            passport.serializeUser(function(user, cb) {
                cb(null, user);
            });
            passport.deserializeUser(function(user, cb) {
                cb(null, user);
            });
            passport.initialize()
            passport.authenticate('local', function(err, user, info) {
                if (err) { return next(err); }
                if (!user) { return res.redirect('/login'); }
                req.logIn(user, function(err) {
                  if (err) { return next(err); }
                  return next();
                });
              })(req, res, next);
        } 
    }

using this, i get "access denied" without the correct credentials. using the correct credentials, i get:

Error: passport.initialize() middleware not in use
    at IncomingMessage.req.login.req.logIn (/usr/src/node-red/node_modules/passport/lib/http/request.js:46:34)
    at /data/settings.js:296:21
    at Strategy.strategy.success (/usr/src/node-red/node_modules/passport/lib/middleware/authenticate.js:214:18)
    at verified (/data/node_modules/passport-local/lib/strategy.js:83:10)
    at Strategy._verify (/data/settings.js:281:28)
    at Strategy.authenticate (/data/node_modules/passport-local/lib/strategy.js:90:12)
    at attempt (/usr/src/node-red/node_modules/passport/lib/middleware/authenticate.js:361:16)
    at authenticate (/usr/src/node-red/node_modules/passport/lib/middleware/authenticate.js:362:7)
    at middleware (/data/settings.js:300:17)
    at Layer.handle [as handle_request] (/usr/src/node-red/node_modules/express/lib/router/layer.js:95:5)

i think there is something wrong in the logic using var passport= require('passport') (...) within middleware: function(req,res,next) {

can someone help me to find the issue?

thanks

TotallyInformation commented 5 years ago

Hi Simon, I'll admit that I haven't used that, only the simple example from the docs.

I would, however, think that the require statement should not be within the function. It should actually be outside the module.exports section of settings.js.

In fact, I think that only the passport.authenticate function should be included in the middleware function. Can you try that and see if it works?

In v2 of uibuilder, I'll be moving the function out of settings.js to a uibuilder specific location, probably ~/.node-red/uibuilder/.middleware.js I will try to include a more realistic example.

simon86de commented 5 years ago

Hi TotallyInformation,

ive got it done by creating a custom node to get access to the "app" object including all the passport stuff. then i could simply add

uibuilder: { middleware: function(req, res, next){ if(req.isAuthenticated()) { //user is authenticated next(); } else { //user isnt authenticated -> redirect to login page res.redirect('/login'); } } }

to the settings.js section. thanks for your advice

TotallyInformation commented 5 years ago

Glad you got it working.