Skip to content

Firewall does not recognize {_locale} #1493

Closed
keymaster opened this Issue Jul 1, 2011 · 13 comments

5 participants

@keymaster

I know this was fixed in Beta5, but something seems to have changed and it does not seem to be working any longer in RC3.

In Beta5 the following worked for the url /en/login, /en/login_check, and /en/logout:

firewalls:
main:
pattern: .*
form_login:
provider: fos_userbundle
login_path: /{_locale}/login
use_forward: false
check_path: /{_locale}/login_check
failure_path: null
logout:
path: /{_locale}/logout
target: /
anonymous: true

However, in RC3, when the login form submits to the url:

http://localhost/Symfony/web/app_dev.php/en/login_check

...the response is:

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

It appears the firewall doesn't recognize that "/{_locale}/login_check" should match "/en/login_check".

But, when I change the check_path to: "/en/login_check", and the login_path to "/en/login", I can login fine.

The same situation occurs with logout.

On the Symfony2 list, Stof said some changes were made, and now we should be using route names in the firewall instead of paths. The thread is here: https://groups.google.com/forum/#!topic/symfony2/_gAf_mdxmJc

So, I replaced the paths with routes, but that also doesn't seem to work:

app/config/security.yml

security:
providers:
fos_userbundle:
id: fos_user.user_manager

firewalls:
    main:
        pattern:      .*
        form_login:
            provider:       fos_userbundle
            login_path:     fos_user_security_login
            use_forward:    false
            check_path:     fos_user_security_check
            failure_path:   null
        logout:
            path:   fos_user_security_logout
            target: /
        anonymous:    true

access_control:
    # The WDT has to be allowed to anonymous users to avoid requiring the login with the AJAX request
    - { path: ^/_wdt/, role: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/_profiler/, role: IS_AUTHENTICATED_ANONYMOUSLY }
    # AsseticBundle paths used when using the controller for assets
    - { path: ^/js/, role: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/css/, role: IS_AUTHENTICATED_ANONYMOUSLY }
    # URL of FOSUserBundle which need to be available to anonymous users
    - { path: ^/(en|fr|he|ru)/login, role: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/(en|fr|he|ru)/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/(en|fr|he|ru)/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
   # Secured part of the site
    # This config requires being logged for the whole site and having the admin role for the admin part.
    # Change these rules to adapt them to your needs
    - { path: ^/.*/admin/, role: ROLE_ADMIN }
    - { path: ^/.*, role: ROLE_USER }

role_hierarchy:
    ROLE_ADMIN:       ROLE_USER
    ROLE_SUPER_ADMIN:  ROLE_ADMIN

app/config/routing.yml

fos_user_security:
resource: "@FOSUserBundle/Resources/config/routing/security.xml"
prefix: /{_locale}

fos_user_profile:
resource: "@FOSUserBundle/Resources/config/routing/profile.xml"
prefix: /{_locale}/profile

fos_user_register:
resource: "@FOSUserBundle/Resources/config/routing/registration.xml"
prefix: /{_locale}/register

fos_user_resetting:
resource: "@FOSUserBundle/Resources/config/routing/resetting.xml"
prefix: /{_locale}/resetting

fos_user_change_password:
resource: "@FOSUserBundle/Resources/config/routing/change_password.xml"
prefix: /{_locale}/change-password

With the above setup, when I go to the url /en/login, I get the message:

"The "fos_user_security_logout" route has some missing mandatory parameters ("_locale")."

Stof recommended I open this ticket.

@Seldaek
Symfony member
Seldaek commented Jul 1, 2011

I think they are now handled with routes or absolute paths/URLs, so you must do: login_path: route_name and then in your routing config define the route_name route with /{_locale}/foo.

@stof
Symfony member
stof commented Jul 1, 2011

@Seldaek This is waht it did, as described at the end. But the router complains about a missing parameter which is weird as the locale should be injected automatically.

@Seldaek
Symfony member
Seldaek commented Jul 1, 2011

Ok, must be a real bug then :)

@fabpot
Symfony member
fabpot commented Jul 5, 2011

That's because security tries to generate a URL before the router listener is triggered. So, at this point, the _locale variable is still empty.

@fabpot
Symfony member
fabpot commented Jul 5, 2011

I think I've an idea on how to fix this problem. I will play with it today and try to submit a patch.

@fabpot
Symfony member
fabpot commented Jul 5, 2011

First part was rather easy (logout):

4f8a980

@fabpot
Symfony member
fabpot commented Jul 5, 2011

I don't see how to fix the second part without hacking a lot. Here is a patch that works:

diff --git a/src/Symfony/Component/Security/Http/HttpUtils.php b/src/Symfony/Component/Security/Http/HttpUtils.php
index 9ac604e..4d1c77a 100644
--- a/src/Symfony/Component/Security/Http/HttpUtils.php
+++ b/src/Symfony/Component/Security/Http/HttpUtils.php
@@ -48,6 +48,18 @@ class HttpUtils
         if (0 === strpos($path, '/')) {
             $path = $request->getUriForPath($path);
         } elseif (0 !== strpos($path, 'http')) {
+            $context = $this->router->getContext();
+            $session = $request->getSession();
+            try {
+                $parameters = $this->router->match($request->getPathInfo());
+            } catch (\Exception $e) {
+            }
+            if (isset($parameters['_locale'])) {
+                $context->setParameter('_locale', $parameters['_locale']);
+            } elseif ($session) {
+                $context->setParameter('_locale', $session->getLocale());
+            }
+
             $path = $this->generateUrl($path, true);
         }

I won't have time today to work more on it. So, feel free to play with the above code.

@keymaster

@fabpot: Just wanted to report that both your fixes, ie. the logout commit and the above patch, are working for me.

The problems I reported in this ticket no longer occur.

Please commit the patch if you feel comfortable with it.

fyi - I'm using route names instead of paths in the firewall, as follows:

firewalls:
main:
pattern: .*
form_login:
provider: fos_userbundle
login_path: fos_user_security_login
use_forward: false
check_path: fos_user_security_check
failure_path: null
logout:
path: fos_user_security_logout
target: /
anonymous: true

@fabpot
Symfony member
fabpot commented Jul 11, 2011

pushed here: ea7a0eb

@fabpot fabpot closed this Jul 11, 2011
@keymaster

The above commit for login works fine, but it seems a few problems still remain:

In particular, all the following actions result in the error:
"The "fos_user_security_login" route has some missing mandatory parameters ("_locale"). "

  1. after being logged in successfullly at the route /en/login, going to the url "/en/logout" generates the above error (although it does log out the user first).

  2. if you are not logged in, and you go to an url which requires a login, ie. "/en/admin/dashboard", then, instead of being redirected to the login screen, you get the same error.

  3. if you are not logged in, but you go to the logout url "/en/logout" you will get the same error.

Firewall config is same as in above comment.

@schmittjoh schmittjoh reopened this Jul 17, 2011
@fabpot
Symfony member
fabpot commented Jul 18, 2011

I've just tested and it works fine for me (note that I'm not using FOSUserBundle).

@schmittjoh

@keymaster: Could you maybe add a functional test to the SecurityBundle which demonstrates the problem?

@schmittjoh

These issues will be fixed by #1739

@schmittjoh schmittjoh closed this Jul 19, 2011
@fabpot fabpot added a commit to symfony/symfony-standard that referenced this issue Dec 1, 2012
@fabpot fabpot merged branch oscherler/security-routes (PR #454)
This PR was merged into the master branch.

Commits
-------

7eda9be Changed the login/check/logout paths in security.yml to route names.

Discussion
----------

Use route names for login/check/logout paths in security.yml

It might be a good idea to switch the firewall login, logout and check paths to route names in `security.yml`, if only to draw attention to the fact that it’s possible (and probably a good idea?):

    secured_area:
        pattern:    ^/demo/secured/
        form_login:
            check_path: _security_check
            login_path: _demo_login
        logout:
            path:   _demo_logout
            target: _demo

As mentioned in symfony/symfony#1493, it’s apparently the right way to do it if you want a localised login page. At least that’s what I had to do after I prefixed the FOSUserBundle routes with `/{_locale}/`.

---------------------------------------------------------------------------

by brikou at 2012-12-01T07:21:17Z

:+1:
fe79e7a
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.