4

Dear community and vitaly-t hopefully,

I am building a website / server with pg-promise. I use postgre role/group login for authentification.

I don't know if I am doing the things correctly but I would like that each user use their own postgres connection to query the database.

So in practice, I create a connection for each user when they connect (if it is not already existing). To do so, I have created a Pool object with an ugly 'fake promise' and a pgUser object:

var pgPool = function(pg){
    var _this=this;
    var fakePromise = function(err){
        var _this=this;
        _this.err=err
        _this.then=function(cb){if(!err){cb();return _this}else{return _this};};
        _this.catch=function(cb){if(err){cb(_this.err)}else{return _this};};
        return _this;
            };

    _this.check= function(user){
        if (_this[user]){
            return _this[user].check();
        }else{
            return new fakePromise({error:'Echec de connection à la base de 
            données'})
        }


    }
    _this.add = function(user,password){
        var c={};
        c.host = 'localhost';
        c.port = 5432;
        c.database = 'pfe';
        c.poolSize = 10;
        c.poolIdleTimeout = 30000;
        c.user=user;
        c.password=password
        if (!_this[user]){
            _this[user] = new pgUser(c,pg);
            return _this[user].check();
        }else{
            _this[user].config.password=password;
            return _this[user].check();
        };
    };
    return _this;
};

var pgUser = function(c,pg){
    var _this=this
    _this.config = c    
    _this.db = new pg(_this.config)
    _this.check = function(){
        return _this.db.connect();
    };
    return _this;
}; 

And here is how I add a user to the 'pool' during the login POST handling

 pool.add(req.body.user,req.body.password).then(function(obj){
            obj.done();
            req.session.user = req.body.user;
            req.session.password = req.body.password;
            res.redirect("/");
            return;
        }).catch(function(err){
            options.error='incorect password/login';
            res.render('login', options);   
            return;
        });

I am sure it could irritate pro developpers and you would be kind if you could explain me the best way :

  • is that a good idea to have one connection to the database per user (it seems legit to have a good security)?
  • how can I use the pg-promise library better to avoid this ugly custom 'pool' object?

Sincerly thank you.

alexnode
  • 91
  • 9
  • This doesn't look right at all. But if I may, why would you want this? Such a solution cannot scale, as connections are the most valuable resource that needs to be shared, in order to be scalable. You are trying to handicap your service on purpose. – vitaly-t Aug 28 '17 at 12:29
  • 1
    Hi vitaly-t. Thank you for your promp reply. Could you rephrase " Such a solution cannot scale, as connections are the most valuable resource that needs to be shared, in order to be scalable" , please. I want to do that in order to increase the security. Each user should have their own connection to pg, isn't it? I cannot find anywhere how to handle multiple users with postgres. Should I have only 1 connection to pg (admin) in my server? I would like to use the row security level function of postgres. – alexnode Aug 28 '17 at 13:19
  • OR each time I want to perform a query, I need to change the global connection variable of your example here ? : https://stackoverflow.com/questions/8484404/what-is-the-proper-way-to-use-the-node-js-postgresql-module – alexnode Aug 28 '17 at 13:38
  • 1
    @vitaly-t , it looks like all examples on the web have a kind of admin password and id for all the queries, whatever is the user connected. I don't understand how I can use the row-security level function of pg-promise doing that. Either I don't understand anything or I am doing something never done before. – alexnode Aug 30 '17 at 11:43
  • 1
    Hi, I have contacted the security responsible of my project, doing research an associate profressor in security (CITI lab)... – alexnode Sep 07 '17 at 15:12
  • 1
    @alexnode, I have exactly the same issue. From what I have read so fare, all exemples seem to use a unique connection. For me it doesn't make sens in term of security. We should be able to create one connection for each user (with their id and pw). Otherwise, it would mean that someone who can access your server, can access the DB... pretty bad. I ended up reseting the &cn of the db object. But not sure if it's good practice. So far it's working... – RomOne Sep 18 '17 at 13:43
  • 1
    @alexnode, please let me know the progress of your work on this matter. I wish to use 4-5 different kind of users (registered, unregistered, admin, employee, etc) for security purpose, too. Tia – SONewbiee Jul 16 '18 at 14:04

1 Answers1

1

I have contacted the security responsible of my project, doing research as associate profressor in security (CITI lab)...here is his comment :

====================

Since it is my fault, I will try to explain ;-). First, to be clear, I work on the security side (notably access control and RDBMS security) but am not very familiar with JS or promises.

Our aim is to implement the principle of least privilege with a defense in depth approach. In this particular case, this means that a query sent by an unprivileged user should not have admin rights on the database side. RDBMS such as PostgreSQL provide very powerful, expressive and well-tested access control mechanisms : RBAC, row-level security, parametrized views, etc. These controls, indeed, are usually totally ignored in web applications which use the paradigm "1 application == 1 user", this user has thus admin role. But heavy clients often use several different users on the database side (either one per final user or one per specific role) and thus benefit from the access control of the database.

Access control from the DB is an addition to access control in the web application. AC in the webapp will be more precise but may probably suffer from some bugs ; AC in the DB will be a bit more laxist but better enforced, limiting damages in case of an application bug.

So in our case, we want to create a DB user for every application user. Then, the connection to the database belongs to this specific user and the database can thus enforce that a simple user cannot execute admin operations. An intermediate possibility would be to drop some privileges before executing a query, but our preferred way is to connect to the database as the currently logged-in user. The login-password is sent by the user when he authenticates and we just pass it to the DBMS. Scalability is not (yet) an issue for our application, we can sacrifice some scalability for this type of security.

Would you have any hints to help us achieve this ?

==================

alexnode
  • 91
  • 9
  • I have ask the question with another post since this does not concern pg-promise in particular : https://stackoverflow.com/questions/46099931/webserver-with-database-one-connection-per-user – alexnode Sep 07 '17 at 15:20