Search code examples
meteormeteor-accounts

How do I login pre-authenticated users?


How do I login users using pre-authenticated authentication request?

Authentication is handled by https://www.netiq.com/ and requests are passed to Meteor with http headers that contain username, roles etc. How can I populate user objects in Meteor and do authorization?

Coming from Java and Spring Security, I used https://github.com/spring-projects/spring-security/blob/master/web/src/main/java/org/springframework/security/web/authentication/preauth/PreAuthenticatedAuthenticationProvider.java


Solution

  • On the server, register a login handler using something like this (untested):

    Accounts.registerLoginHandler("netiqPreauth", function(options) {
      var self = this;
      if (! options || ! options.netiqPreauth || 
          ! self.connection || ! self.connection.httpHeaders) {
        return undefined;
      }
    
      // parseHeaders() parses the headers into a userDetails object.
      var userDetails = parseHeaders(self.connection.httpHeaders);
    
      // Code below assumes userDetails.username is unique
      var existingUser = Meteor.user.findOne({ "services.netiq.username": userDetails.username });
      if (existingUser) {
        if (EJSON.stringify(existingUser.services.netiq) !== EJSON.stringify(userDetails)) {
          Meteor.users.update(existingUser._id, { 
            $set: { "services.netiq": userDetails }, // Update details
            $unset: { "services.resume.loginTokens": "" } // Force logout
          });
        }
        return { userId: existingUser._id };
      }  
      var newUserId = Accounts.insertUserDoc(options, {
        profile: { /* whatever */ }, // Optional
        services: {
          netiq: userDetails
        }  
      });
      return {
        userId: newUserId
      };
    });
    

    That will only update the details associated with a user when the user logs in. If you have some way to notify the server when a user's details change, you can have the server update the details and delete the existing tokens associated with the user (like in the code above). Deleting the tokens will logout the user anywhere they might be logged in. Deleting a user will also log the user out.

    If you don't have a way to be notified about changes to a user's details, you could also call Accounts.config({ loginExpirationInDays: some_suitably_short_time_period } ) (on the client and server) to log out users frequently.

    To log a user in, you need to call Accounts.callLoginMethod() on the client. If you want to automatically log the user back in when he is logged out, you could do something like this (untested):

    Meteor.startup(function(){
        Tracker.autorun(function () {
          if (! Meteor.userId()) {
            Accounts.callLoginMethod({
              methodArguments: [{
                netiqPreauth: true
              }],
              userCallback: function (error) {
                if (error) {
                  // handle error
                } else {
                  // handle success
                }
              }
            });
          }
        });
      });
    }