Skip to content

Instantly share code, notes, and snippets.

@dknauss
Last active December 30, 2024 17:10
Show Gist options
  • Select an option

  • Save dknauss/08aa4226989fb3e92e086c4a7c2feb33 to your computer and use it in GitHub Desktop.

Select an option

Save dknauss/08aa4226989fb3e92e086c4a7c2feb33 to your computer and use it in GitHub Desktop.
Return 401 error response for failed WordPress logins.
add_action( 'wp_login_failed', function ():void {
status_header( 401 ); // Generates PHP header("HTTP/1.1 401 Unauthorized");
wp_die( 'Your login attempt failed.' ); // Kill WP/PHP execution with WSOD + error message. (Optional)
});
// A 401 error for failed logins (rather than the default 200 error) may be useful to trigger securty tools watching the HTTP
// access log like fail2ban and mod_security. If fail2ban is set to block IPs with repeated login failures (401s), send it 401s
// for failed logins. Halting PHP execution then is useful if you want to suppress default 'helpful' error messages too.
// A more robust approach would also handle logging requests over XML-RPC and the REST API.
// See: https://github.com/amitrahav/WP-401-On-Failed-Login/blob/master/401-on-auth-fail-init.php
//
// Note that WordPress core comitters (and others) have disagreed that 401 (and 403) are the correct "modern standard" response
// for a failed login and that "all web application frameworks" use 401 (or 403) for failed logins.
//
// See WordPress core Trac ticket #25446 to understand why failed logins return HTTP 200 in WOrdPress, and why this has
// intentionally *not* been changed to 401 (or 403), despite requests to do so.
// https://core.trac.wordpress.org/ticket/25446
//
// It may be preferable to configure fail2ban and similar tools to filter HTTP POST requests to wp-login that result in HTTP
// STATUS CODE 200, which only occurs when a login has failed and the login screen loads with a message to that effect.
// Successfully posted logins get a 301 redirect, so they will not be confused with failed logins.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment