We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 3151
    • 7 Posts
    Hi all,

    First of all, I just wanted to say that I’m new to MODx and it’s been a great experience so far looking at the architecture/model of Revolution - it really is an exciting development environment.

    But now I’m stumbling into this issue - when I’m trying to create a simple plugin for authenticating to external system.

    Basically what I’m trying to do is to use ’OnBeforeWebLogin’ event which is called indirectly by Login (http://svn.modxcms.com/docs/display/ADDON/Login+Snippet) snippets/package - to call my own snippets that does the external authentication.

    The plugin code is shown below.

    <?php
    
    /* Handle event */
    switch ($modx->event->name) {
        case 'OnBeforeWebLogin':
    		$username = '';
    		$givenPassword = '';
            if (isset($scriptProperties['username'])) {
    			/* if exist, assign value */
    			$username = $scriptProperties['username'];
            } else if (isset($scriptProperties['password'])) {
    			/* if exist, assign value */
    			$givenPassword = $scriptProperties['password'];
            } 
    
    		// call snippet to do external authentication
    		$output = $modx->runSnippet('ExternalLogin',$scriptProperties);
    		
    		// output would be in boolean to test the authentication
    		// true - would proceed logging into modx
    		// false - would stop the login into the system
    		// issue - $modx->event->output((bool) true) -> converting the boolean into integer, which makes it never validates as true
    		$modx->event->output($output)
    		
            break;
    
        case 'OnBeforeWebLogout':
    		// ... has not been implemented
            break;
    
       default: break;
    }
    return true;
    ?>
    


    What I intend to do is to have the result from my snippet returning boolean value which would proceed with standard modx login (implemented by Login snippet - package) when the value is true..

    but I’m suspecting that there is some issues with $modx->event->output function. I always get the same results no matter what the boolean value I use, whether true/false.

    /core/model/modx/processors/security/Login.php
    $rt = false;  /* $rt will be an array if the event fires */
    if ($loginContext == 'mgr') {
        $rt = $modx->invokeEvent("OnBeforeManagerLogin", $onBeforeLoginParams);
    } else {
        $rt = $modx->invokeEvent("OnBeforeWebLogin", $onBeforeLoginParams);
    }
    
    /* If the event fired, loop through the event array and fail if there's an error message  */
    if (is_array($rt)) {
        foreach ($rt as $key => $value) {   /* php4 compatible */
            if ($value !== true) {
    			// - my comment - it stops in here everytime
                return $modx->error->failure($value);
            }
        }
        unset($key,$value);
    }
    
    // - my comment - i need the code to continue on trough here if boolean value true returned
    


    I ran few simple tests - inspecting /core/model/modx/processors/security/Login.php - and it seems the variable $value in $rt returns array if I pass an array to it, returns string if we passed string to it - but it does not return boolean, infact it seems like it is converting the boolean value into integer. So this conditional statement ($value !== true) would always evalute to true - which then stopping the process in that conditional statement each time. Is this meant to happen?

    or this is a fault/bug? - I’m unsure how to solve this problem. If the fault is in my approach to create the plugin, could someone in here please point me into the right direction.

    Here’s my server info:
    - MODx Revolution 2.0.0-rc-2 rev6923
    - PHP Version 5.2.5
    - Zend engine (phpinfo)
    Zend Engine v2.2.0,
    with the ionCube PHP Loader v3.1.32, and
    with Zend Extension Manager v1.2.2,
    with Zend Optimizer v3.3.3,

    Thanks very much
      • 26903
      • 1,336 Posts
      I wrote an OpenId authentication add on for revo and did roughly the same as you, i.e. to check whether to proceed with the MODx login or not, here’s my plugin code :-
      $result = $_SESSION["openidauth"];
      $modx->event->_output = false;
      if ( $result == 'authenticationOK' ) {
         $modx->event->_output = true;
      }
      
      return;
      


      Notice I use ’_output’ and not ’output’ and set it to true. I can’t honestly remember why this is, if I get chance later I’ll have a closer look.
        Use MODx, or the cat gets it!
        • 28215
        • 4,149 Posts
        I think the issue you’re having is that any return value from $modx->runSnippet is always going to be a string. So sending that value to $modx->event->output() without typecasting it to a boolean will always cause that condition to pass.
          shaun mccormick | bigcommerce mgr of software engineering, former modx co-architect | github | splittingred.com
          • 3151
          • 7 Posts
          Thank you for all the reply guys..

          I did try type casting the call to $modx->event->output

                  $v = (bool) "true";
                  $modx->event->output($v);
          


          but still same result.. - does not work & convert the value to string one(1)

          But now it works - when I assigned the boolean value straight away to the global _output, just like what shamblett is recommending.

          Thanks for all the help..
            • 73
            • 37 Posts
            Thank guys this helped so much adding a disclaimer checkbox on a login form.
            Until we have better documentation, maybe this clarification may help some..

            This does not work in a plugin:
            <?php
            
            if ($modx->event->name == 'OnBeforeWebLogin') { 
            		
            	if ($_POST['agree'] != "yes") {
            		return $modx->error->failure("Please read our disclaimer before logging in!");
            	}
            	
            	return;
            	
            }
            
            ?>
            


            but this does:

            <?php
            
            if ($modx->event->name == 'OnBeforeWebLogin') { 
                    
                if ($_POST['agree'] != "yes") {
                    return $modx->error->failure("Please read our disclaimer before logging in!");
                    $modx->event->_output = false;
                }else{
                    $modx->event->_output = true;
                }
                
                return;
                
            }
            
            ?>
            
              • 36764 ☆ A M B ☆
              • 45 Posts
              Evengard aka Eiventeleiron Reply #6, 14 years, 1 month ago
              WHY I didn't see that topic before... I spent 5 hours while trying to find out the issue...

              Well, thank you really, 2byte and shamblett.

              2Devs - this should be documented somewhere... Or the behaviour of the event->output() should be changed...
                • 22303 MODX Staff
                • 10,725 Posts
                Important note here:

                Remember that multiple plugins can be assigned to a single event in MODX. This means you should expect multiple return values in most cases. This is why using the $modx->event->output() method is not working as you expect. It is setting the return value into an array of values returned from all plugins being executed on that event. You are circumventing this behavior when you return a boolean (or any other non-array value) by assigning it directly to $modx->event->_output.
                  • 36764 ☆ A M B ☆
                  • 45 Posts
                  Evengard aka Eiventeleiron Reply #8, 14 years, 1 month ago
                  The problem is that it is not (as far as I can see). The _output seems then to be copied to an array (inside modx.invokeEvent()), which is THEN checked in the login.php processor.

                  Well, in any case if not using the _output there is no way to use the OnBeforeWebLogin plugin - it will always evaluate to "false", because it seems that during the parsing we have something like this:
                  ob_start();
                  $this->event->_output = $this->plugin->process(...);
                  $this->event->_output = $this->event->_output.ob_get_contents(); // here we got the problem, because we get our output converted to a string here!
                  

                  but in the login.php processor we have:
                  foreach($rt as $key => $value)
                  {
                  // ...
                  if($value!==true) // we can never make this unhappen - because the type of the $value is ALWAYS a string! It can only be a bool if we set by setting directly the _output, but when using output() it is still a string!
                  // ...
                  }


                  And yes, I have checked. Changing the _output still allows using multiple plugins on the same event (they goes all to the array).
                    • 36764 ☆ A M B ☆
                    • 45 Posts
                    Evengard aka Eiventeleiron Reply #9, 14 years ago
                    https://github.com/modxcms/revolution/pull/392 - pull request aimed to fix that. Now the first call of event->output() preserves it's type