Failed login returns 200 status code

W1zzard

Well-known member
Affected version
2.3.6
This makes it hard to catch bruteforces in the logs, should return 401

edit:
SELECT COUNT(*) FROM xf_login_attempt WHERE FROM_UNIXTIME(attempt_date) > CURRENT_DATE()
-> 184468

and it's only 5 pm

fix:
edit LoginController.php, after $user = $loginService->validate($input['password'], $error);

change
return $this->view('XF:Login\Form', 'login', $viewParams);

to

$view = $this->view('XF:Login\Form', 'login', $viewParams);
$view->setResponseCode(401);
return $view;
 
Last edited:
Your suggested fix violates RFC 9110 section 15.5.2

Tl;Dr
You can't set status code 401 without requesting the client to perform HTTP level authentication via WWW-Authenticate.
From a technical point of view IMHO 200 is correct, even for failed logins.

If you want to have (more) logging for failed login attempats there are various options to achieve that:
https://xenforo.com/community/resources/monolog-logging-service.6080/ + add code for logging
Set a response header and include this in your webserver logs (+ hide from clients)
 
We tend to look at the login attempts that don't have any corresponding "content IP" address, so something like:
SQL:
select inet6_ntoa(xf_login_attempt.ip_address) as ip, count(*) as attempts from xf_login_attempt where not exists (select xf_ip.ip from xf_ip where xf_ip.ip = xf_login_attempt.ip_address) and xf_login_attempt.attempt_date >= unix_timestamp(now() - interval 2 day) group by xf_login_attempt.ip_address;
and depending on the thresholding we have we block those IPs for a while. Obviously adjusting the interval to one that suits you.
 
That would be semantically wrong as well:
The client is not forbidden to perform a login operation (unless it is blocked via IP or smth. else, in this case a 403 would be appropriate).
403 or even a 404 is semantically correct.

The 403 (Forbidden) status code indicates that the server understood the request but refuses to fulfill it. A server that wishes to make public why the request has been forbidden can describe that reason in the response content (if any).

If authentication credentials were provided in the request, the server considers them insufficient to grant access. The client SHOULD NOT automatically repeat the request with the same credentials. The client MAY repeat the request with new or different credentials. However, a request might be forbidden for reasons unrelated to the credentials.

An origin server that wishes to "hide" the current existence of a forbidden target resource MAY instead respond with a status code of 404 (Not Found).
They provided a login credentials, but the server is refusing access on supplying them.
 
Back
Top Bottom