WPEngine Authentication Issues
August 24th, 2017Over the past few months I’ve received a handful of support inquiries from MarsEdit customers who have trouble logging into their WPEngine-hosted WordPress blog, after initially typing the wrong username or password into MarsEdit’s authentication panel.
Normally when MarsEdit tries to connect to a blog, it reacts to authentication failures by putting up a simple panel prompting for a username and password. In some cases, where the authentication challenge seems to be coming from a higher level than the blog itself, MarsEdit prompts with a different panel, suitable for supplying HTTP protocol-level authentication.
MarsEdit distinguishes between WordPress-level authentication and HTTP-level authentication by the simple fact that WordPress always returns HTTP status 200, even when a user is authenticated. The failure to authenticate is expressed in a valid XMLRPC response, and since the response is valid, it warrants a 200 “Success” HTTP status result.
In the process of debugging this problem, I observed that some of my customers were getting authentication failure responses from their self-hosted WordPress blogs, in which the HTTP Status Code was not 200, but 403 instead. Slowly, but surely, I came to understand that each of these affected customers was running on WPEngine.
Finally, with the help of a customer who shared my eagerness to get to the bottom of the problem, I was able to trace the behavior to a custom WordPress that is installed by WPEngine on behalf of all of their customers. It’s called the “wpengine-common” plugin. My customer was kind enough to send me a copy of the plugin files from within his WordPress installation. Guess what I found inside the plugin?
function wpe_login_failed_403() { // Don't 403 when the login comes // through an Ajax request if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) { return; } status_header( 403 ); } add_action( 'wp_login_failed', 'wpe_login_failed_403' );
This bit of code overrides the standard WordPress login failure, forcing a 403 status code when one occurs. From what I can gather, the intent is to raise the visibility of WordPress login failures so that security packages that monitor for attempts to break into sites can log the attempts and potentially warn users and/or WPEngine about the risk of an intrusion. That’s a great motive, but it has an undesirable consequence for clients of the WordPress API.
Any client of the WordPress API is liable to interpret a 403 status code as an authentication failure outside the scope of WordPress itself. It may assume there is no blog at all to connect to, or it may assume as MarsEdit does, that there is a second level of authentication required to gain access to the server, before gaining access to WordPress.
I don’t know what the ideal solution to this problem is, but it would be nice if WPEngine found another way to flag the potentially suspicious login attempts to their WordPress installations, that didn’t involve breaking the contract for how the WordPress XMLRPC API is supposed to behave. If you look again at the source code excerpt I pasted above, you’ll see there is a special case in place for “Ajax” requests. Presumably this is another use case where the unexpected 403 status response has caused trouble. In fact, if you Google for “wpe_login_failed_403”, you’ll find a number of simple WordPress plugins whose whole purpose is to disable the WPEngine 403 status behavior described here.
I am planning to work around the issue in MarsEdit somehow, but in the mean time if you are a WPEngine customer who also uses MarsEdit, you may run into problems when/if you enter your credentials wrong, or you try to connect again from MarsEdit after changing your password. You’ll see a different login panel speaking of things such as “second level of authentication”. If you run into this, you can get back on track by manually entering your correct username and password:
- Click the blog in the left-hand side of MarsEdit’s main window.
- Hold the option key down while clicking the “Blog” menu item at the top of the screen.
- Select the “Enter Password…” menu item.
- Enter your correct WordPress username and password.
As long as the username and password that are stored by MarsEdit in the keychain are correct, you should be able to connect to your WPEngine-hosted WordPress blog without any issue. Whenever they are incorrect, until I implement a workaround, or until WPEngine changes their plugin behavior, you will need to work around the problem in this manner.