1

I'm trying to write a simple authentication backend for Meteor that authenticates against an LDAP server. I need the function registered as login handler (the input to Accounts.registerLoginHandler) to return the id the of the user just logged in.

The problem I think lies in the Fiber I've created, getUserId, and that it's not returning id like I want it to. I know it has to be in a Fiber or else meteor gets angry and throws errors. Even though the log right before the yield shows me the id isn't undefined, getUserId.run() always returns undefined.

Any help would be greatly appreciated, thanks!

Accounts.registerLoginHandler(function(loginRequest) { 

    console.log("In login handler");

    return auth.authenticate(loginRequest.username, loginRequest.password, function(err, ldap_user) {

        if (err){
            // ldap authentications was failed
            console.log("Login failed");
            return undefined;
        }
        else {
            // authentication was successful
            console.log("Login success");

            // extracting team name from ldap record
            var equals = ldap_user.memberOf.indexOf("=");
            var comma = ldap_user.memberOf.indexOf(",");
            var team_name = ldap_user.memberOf.slice(equals+1,comma);

            // add user if they don't already exist

            var getUserId = Fiber( function() { // Meteor code must be ran within a fiber
                var id = null;
                var user = Meteor.users.findOne({username: loginRequest.username});
                if(!user) {

                    // insert user and kick back id
                    id = Meteor.users.insert({username: loginRequest.username,
                                              profile : {team : team_name}
                                             });
                    console.log('no user found, creating' + id);

                } else { 

                    id = user._id; 
                    console.log('user found, returning id' + id);

                }

                console.log('id: '+id);
                Fiber.yield(id);  // return id
            });

            // send logged in users if by executing the fiber
            return {id: getUserId.run()};
        }
    });
});
mwillsey
  • 41
  • 4

1 Answers1

0

I think the problem is related to instead needing to use Meteor.bindEnvironment to control the scope of the (environment) variables and fibers in use.

A good three-step tutorial on the subject is found here:

  1. https://www.eventedmind.com/feed/nodejs-introducing-fibers
  2. https://www.eventedmind.com/feed/meteor-dynamic-scoping-with-environment-variables
  3. https://www.eventedmind.com/feed/meteor-what-is-meteor-bindenvironment

My take on your code would be something like this (which in a similar problem worked for me):

Accounts.registerLoginHandler(function(loginRequest) { 

    console.log("In login handler");

    var boundAuthenticateFunction = Meteor.bindEnvironment(function(err, ldap_user) {
        if (err){
            // ldap authentications was failed
            console.log("Login failed");
            return undefined;
        }
        else {
            // authentication was successful
            console.log("Login success");

            // extracting team name from ldap record
            var equals = ldap_user.memberOf.indexOf("=");
            var comma = ldap_user.memberOf.indexOf(",");
            var team_name = ldap_user.memberOf.slice(equals+1,comma);

            // add user if they don't already exist

            var id = null;
            var user = Meteor.users.findOne({username: loginRequest.username});
            if(!user) {

                // insert user and kick back id
                id = Meteor.users.insert({username: loginRequest.username,
                                          profile : {team : team_name}
                                         });
                console.log('no user found, creating' + id);

            } else { 

                id = user._id; 
                console.log('user found, returning id' + id);

            }

            console.log('id: '+id);

            return {id: id};
        }
    }, function(e){throw e;});

  return auth.authenticate(loginRequest.username, loginRequest.password, boundAuthenticateFunction);
});

Mind, the code sample above is untested...

Spiralis
  • 3,232
  • 2
  • 39
  • 53