Bypassing the MODX Manager Login I

Use your own code, or an external service to authenticate users

You might someday want to bypass the MODX Manager Login process and authenticate users yourself in code. Maybe you want to implement an LDAP authentication, or authenticate them by sending their credentials to another server for validation.

I needed to do this myself in my GoRevo extra. I wanted to be able to let the former Evolution users use their Evo credentials to log in to the Revolution site. Since Revolution does not use all the possible hash algorithms available in Evolution, I had to duplicate the Evolution login code and authenticate the users myself, bypassing the MODX Manager login process.

It's actually fairly simple, and it doesn't require any hacking of of the MODX core code, thanks to MODX's accessible architecture. In this article, we'll look at how it's done.

Using the Right System Event

There are several System Events involved in the Manager login process, but the only one that works for our task is OnManagerAuthentication. When a user submits the login form, MODX fires the OnManagerAuthentication event. Our plugin, attached to that event, will determine if the user gets to log in, and set its output to true or false. If the value is true, MODX logs the user in without checking the credentials at all.

Note that if the output is false, MODX checks the credentials in the usual way, and if they're valid, it logs the user in regardless of what happened in our plugin. It might be possible to prevent this behavior using other login events, but It's seldom necessary since local authentication will always fail if the user is not in the database, and if they are in the local database, you probably want them logged in.

The technique described in this article should also work in the front end if you change the event to OnWebAuthentication, but I've never tested to see if it works. Assuming that it works, there's no reason you can't connect the plugin to both OnManagerAuthentication and OnWebAuthentication and have it work in both the front and back end of your site.


Unfortunately, there is one big catch to this process. Before the the authentication event is fired, MODX tries to get the user from the database and performs several tests. If this fails, the authentication event is never fired and the user is not logged in. In order for this technique to work, the user has to be in the database, be unblocked, and has to have the permissions necessary to log in. There is a way around this, but it's not pretty. We'll discuss it in the following article.

The Plugin Code

If the user is in the database, not blocked, and has the correct permissions, everything you need to do is in one place. You create a plugin (the plugin name can be anything you want), check OnManagerAuthentication on the "System Events" tab of the plugin, enter code like this into the plugin, and save it:

$authenticated = false;

/* Your authentication code here sets $authenticated to true if the 
   user should be allowed to log in */

$modx->event->_output = (bool) $authenticated;

In the code above, we've set the $authenticated variable to false at the top. This is a good security practice, since it will stay false unless we explicitly authenticate the user by setting it to true.

The method of returning a value is kind of odd since you might expect to put the value in the return statement, but that won't work. Having to do it though the $modx->event->_output variable is slightly more secure, since the $modx object must be instantiated in order for the value to make it back to the login code.

Important: Note the underscore in front of output. It's easy to miss, and the code will fail without it.

Available Variables

The following variables are available in your plugin for you to use in authenticating the user:

$password -- The entered password in plain text
$rememberme -- The value of the rememberme checkbox
$lifetime -- The lifetime of the users session cookie (defaults to 0 - unlimited)
$loginContext -- The context the user should be logged in to (defaults to current context)
$addContexts -- Array of other contexts the user should be logged in to or an empty array
$user -- The user object

Notice that the username is missing. If the user is in the database, it should be available like this:

$username = $user->get('username');

The $user, $loginContext, and $addContexts variables are reference variables, so if you change them, the change will persist for the rest of the login. You don't need to log the user in. MODX will will do that for you for all listed contexts if your output tells it that the user has been authenticated.

Coming Up

In the next article, we'll look at what to do if the users are not in the database.

Comments (0)

Please login to comment.