8

When I am authenticating usual way (using login form), it works all right. I am getting this error only when /check_form is accessed via GET method directly, in which case an exception being thrown:

You must configure the check path to be handled by the firewall using form_login in your security firewall configuration.

Here is the relevant security.yml part:

firewalls:
    acme_area:
        pattern:    ^/(acme|admin)/
        provider: fos_userbundle
        form_login:
            provider: fos_userbundle
            csrf_provider: form.csrf_provider
            login_path: acme_login
            check_path: /acme/login_check
        logout:
            path: /acme/logout
            target: acme_login
        anonymous: true

I am using 2.3, thus no methods option is applicable (though I have no idea if it would help).

It is not really an issue as no proper usage could be spoiled by this error, but it pollutes the error log when some diligent bot is visiting the site and it's just untidy. So, I'd like to know which configuration option I can change to get rid of this error.

To boil this down, it seems that I want some 4xx error to be thrown instead of 500. Ideally it should be 405 Method Not Allowed, but 404 cold do too.

EDIT:

As as I learned from the Alex's answer below, this happens because POST requests are handled by the firewall and GET requests by the Controller. Thus, it seems that default checkAction() have to be extended to be able to handle two cases:

  1. When request is POST but no firewal entry is present (already nandled)
  2. When firewall entry is present but request is GET (my case)
Your Common Sense
  • 156,878
  • 40
  • 214
  • 345
  • You have probably already seen and digested the information here? http://stackoverflow.com/questions/17406446/how-does-the-login-check-path-route-work-without-default-controller-action – Professor Abronsius Nov 18 '15 at 10:02

1 Answers1

8

There is no configuration option for that. If the request reach the controller, it unconditionally throws the exception: credible source.

POST request to the route are handled by firewall: official docs; GET ones go to the controller as usual.

There are few options to get rid of the error in the log, if you don't care about such events. The simplest one in my opinion is to override SecurityController::checkAction to return 500 error without throwing an exception. The official docs how to achieve it: Overriding Default FOSUserBundle Controllers.

EDIT:

In the controller you can return whatever code you like:

public function checkAction()
{
    return new Response('', 418); // or better use Response constants 
}

Another way is to disable GET method to /acme/login_check in the routing config, and let router do its job and return normal 405 Method Not Allowed as usual.

EDIT2:

You can analyse request in the action, and still throw an exception:

public function checkAction(Request $request)
{
    if ($request->getMethod() == Request::METHOD_POST) {
        throw new \RuntimeException('You must configure the check path to be handled by the firewall using form_login in your security firewall configuration.');
    } else {
        return new Response('', Response::HTTP_METHOD_NOT_ALLOWED);
    }
}

but I would recommend to debug your routes instead. This logic should belong to the router, not controller. In the long run, your routing config will mislead devs who will maintain this code, and they will have several hard debugging hours trying to figure out why it returns 405, when app/console debug:router clearly states that GET method is allowed.

Alex Blex
  • 34,704
  • 7
  • 48
  • 75
  • But why doesn't it throw with POST method? And why should I care for such events? May be my understanding of the flow is just wrong though. Can't it be a routing issue and thus solved by fixing routes? The "credible source" is not actually mine. It was added automatically, while I were looking for the answer at all. – Your Common Sense Nov 20 '15 at 11:41
  • Hey, no offence about 'official docs'. I just couldn't find better title for the links. I Added `POST` stuff to the answer. You probably shouldn't care about bots, but not all bots are equally dumb. I prefer to keep logs just in case. There are no issues with routes. It is exactly how it is implemented, but you can explicitly override `GET /acme/login_check` if you like to point it to somewhere else. – Alex Blex Nov 20 '15 at 12:15
  • Aha, that's really helpful to know for a such a noob as I am. So, to me it turns out to be the routig issue, as no firewall gets involved. Assuming there is no sane GET scenario for the /login_check, can't you propose the solution thet will make either 403 or 404 when /login_check is requested via GET (as 500 is surely wrong here)? Or even 405 if possible – Your Common Sense Nov 20 '15 at 12:26
  • I have updated answer how to return custom response code. – Alex Blex Nov 20 '15 at 13:21
  • Thank you! One last question. If overriding the checkAction, how can I tell if it was run as it's originally intended (POST request but no firewall entry) or it was run because of my case (GET request)? – Your Common Sense Nov 20 '15 at 13:28
  • `POST` requests are being intercepted by firewall. The handler returns response https://github.com/symfony/symfony/blob/3909460c04e6b13858f2fa3b4e41ec68fdebf0a2/src/Symfony/Component/Security/Http/Firewall/AbstractAuthenticationListener.php#L163 so no controller is involved at all. Overriding controller doesn't change that. The best way to **ensure** it does not regress is to run your functional tests, of course: http://symfony.com/doc/current/book/testing.html#your-first-functional-test – Alex Blex Nov 20 '15 at 14:15
  • Sorry for being unclear. But as far as I learned, the controller *is* called when request is POST but no firewall action is defined - the very use case that is handled by the default action. So, I want to preserve this behavior, as it's very helpful indeed. But I want to handle also another case - when the controller is called with GET method. So it seems I need a condition to distinguish these two cases. Hope I am clear this time and my premises are not wrong. And thank you for your time! – Your Common Sense Nov 20 '15 at 14:58
  • No worries, I updated the answer, but I beg you to not follow this slippery slope and fix the routing config. It is not a quick fix to suppress error log any more, but a piece of functionality which masks a configuration bug. – Alex Blex Nov 20 '15 at 15:44
  • Interestingly that I came to this conclusion myself. I just found the route config for userbundle, and there is already a `POST` line. So now I have no idea why doesn't it work... – Your Common Sense Nov 20 '15 at 16:14
  • `app/console debug:router | grep login_check` may shed some light. If it is still post-only there, then xdebug + functional tests, I'm afraid. Default setup allows only POST, and return 405 for GET requests, so it must be somewhere else in another bundle or your code. – Alex Blex Nov 20 '15 at 16:31