I'm implementing a Symfony 2 solution according to a set specification. The specification states that the login form at GET /login must resumbit to POST /login.
How can I change the URL for the /login_check? Can I create a route that calls the security controller directly, like the following? I don't see any controller in the Security bundle.
oft_auth_login:
pattern: /login
defaults: { _controller: MagicSecurityBundle:Default:login_check }
methods: [POST]
According to the documentation for security.yml,
check_path (type: string, default: /login_check) This is the route or
path that your login form must submit to. The firewall will intercept
any requests (POST requests only, by default) to this URL and process
the submitted login credentials.
So I have to create a valid route, but I can't figure out where it's supposed to point to (firewall action? security action?) or what it's supposed to do.
I changed it to POST /login, but it said it couldn't find it…
Now I have a security.yml file that looks like this:
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
login:
pattern: ^/login$
security: false
secured_area:
pattern: ^/
anonymous: ~
form_login:
login_path: oft_auth_login
check_path: oft_auth_login_check
username_parameter: user
password_parameter: passwd
And a routing.yml that looks like this:
oft_auth_login:
pattern: /login
defaults: { _controller: OftAuthBundle:Default:login }
methods: [GET]
oft_auth_login_check:
pattern: /login
methods: [POST]
I can load the form fine (GET /login), and the form method is POST and the action is /login, but when I submit it, I get the following error (404, route not found):
Unable to find the controller for path "/login". Maybe you forgot
to add the matching route in your routing configuration? 404 Not
Found – NotFoundHttpException
What code, firewall methods, etc. would I have to call to authenticate a user in a custom check_login method, or any other way to accomplish what I'm trying to do, which is to access and post the login form to the same URL (/login)?
Best Answer
In your security.yml, you should see something like:
In your routing.yml, you should see something like:
Change
check_path: /login_check
in security.yml tocheck_path: /new_login_check
Change
pattern: /login_check
in routing.yml topattern: /new_login_check
That will change the URL for the login check route.
Your login form probably looks like:
The
{{ path('login_check') }}
twig snippet outputs the URL to the route identified bylogin_check
. This is not the same as a URL. Example routing configuration (using YAML):Using the path('route_identifier') function will route to the URL /relative/URL/path, which calls the method testAction in the ExampleController class in the ExampleBundle.
You should always use Symfony's routing where possible in your templates, so you avoid conflicts and can easily change routes.
Somewhat orthogonal to changing the login check route, but rereading your question, it says that you want to use the /login path for different actions depending on GET/POST. This requires an extra step, as Symfony will choose the first matching route available to use.
After following the above, your routing.yml might contain something like:
As such, it'll only ever match the login route, never the login_check route. You'll need to specify a method as well:
See the Symfony documentation on Routing for more information.
Another issue you will run into is that the login_check route must match the firewall the user is logging into, but the login route must be accessible to non-authenticated users!
From Symfony's documentation:
This is a bit tricky when using the same URL for both actions, but it is possible. The biggest hurdle is that you can't match firewalls by an http method. The first thing you need to do, then, is make sure that both login routes only match your main firewall, by removing any firewalls that specifically match the login routes.
In the example above, that means removing this section from the security.yml:
That'll meet the first requirement of login_check matching the firewall you're using, but unauthenticated users won't be able to reach the login route any more! That causes a redirect loop. Fortunately, there's a way around that. In your security.yml file, below the section firewalls, you should see a section called access_control. (If not, make one.) You'll need to add the following line to the top of this section. (Again, Symfony matching is conservative, quitting once it finds the first match.)
That will explicitly allow anonymous users to access the /login path, but only via GET.