0

I'm trying to use Internationalized routing.

So for one route many URLs.

But one route still being uniquely identified by its name.

This is a great feature but the doc don't says how to deal with the security component.

In fact, I'm using url to make a basic secure of the app.

But since every URL can be different regarding on the locale, the only way I found to make thing still working is to duplicate as many path as route name got.

This my security.yaml right now :

# ./config/packages/security.yaml @ line 27 -- 41
access_control:
        # Allow every user to visit index_no_locale page (Default page when no locale is selected).
        # This will redirect to login page with default locale.
        - { path: ^/$, roles: IS_AUTHENTICATED_ANONYMOUSLY}
        # Allow anonymous to visit login page.
        - { path: ^(/en/login|/fr/connexion|/de/verbindung), roles: IS_AUTHENTICATED_ANONYMOUSLY}
        # Allow anonymous to visit password_reset page.
        - { path: ^(/en/password/reset|/fr/mot-de-passe/reinitialisation|/de/passwort/zurücksetzen), roles: IS_AUTHENTICATED_ANONYMOUSLY}
        # Allow anonymous to visit email_send_password_forgot
        - { path: ^(/en/email/send/password/forgot|/fr/courriel/envoyer/mot-de-passe|/de/email/schreiben/passwort/vergessen), roles: IS_AUTHENTICATED_ANONYMOUSLY}
        # Allow only admin to visit admin url
        - { path: ^/admin, roles: IS_ADMIN}
        # Allow authenticated user ONLY to visit every other urls
        # Specific user right controls are managed inside controller
        - { path: ^/, roles: IS_AUTHENTICATED_FULLY}

As I say this is working, but I've got to duplicate path for every existing route.

I let you see the route for better understand :

> php bin/console debug:router
  Name                             Method   Scheme   Host   Path      
-------------------------------- -------- -------- ------ --------------------
  password_reset.en                ANY      ANY      ANY    /{_locale}/password/reset/{user_id}/{token_value}           
  password_reset.fr                ANY      ANY      ANY    /{_locale}/mot-de-passe/reinitialisation/{user_id}/{token_value}
  password_reset.de                ANY      ANY      ANY    /{_locale}/passwort/zurücksetzen/{user_id}/{token_value}    
  login.en                         ANY      ANY      ANY    /{_locale}/login                                            
  login.fr                         ANY      ANY      ANY    /{_locale}/connexion                                        
  login.de                         ANY      ANY      ANY    /{_locale}/verbindung                                       
  logout                           ANY      ANY      ANY    /{_locale}/logout                                           
  index_no_locale                  ANY      ANY      ANY    /                 
...

I really don't like this for evident reason of redundant modifications to opeer each time a URL have to be added or modified.

The main problem is when user is not logged in and visit a URL where IS_AUTHENTICATED_FULLY role is required.

So now the 'Voter' say that access is denied and redirect response to login_path define into security.yaml

Here is the problem. I can't define a proper path to login_path because I can't guess what was the locale used by the user. So I hardcoded this :

# ./config/packages/security.yaml @ line 1 -- 21
security:
    # https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
    providers:
        ...
    firewalls:
        dev:
            ...
        main:
            anonymous: true

            form_login:
                login_path: /en/login
                check_path: /en/login
                provider:   my_provider
            logout:
                path: /en/logout
            guard:
                ...

Same for logout actually...

yivi
  • 42,438
  • 18
  • 116
  • 138
vincent PHILIPPE
  • 975
  • 11
  • 26

1 Answers1

1

According to this https://symfony.com/doc/current/security.html#logging-out

You can have security.firewalls.main.logout.path referring to a route name. As for login, you can also refer to a route name, but the recommended way to do it is with guard authenticators see https://symfony.com/doc/current/security/form_login.html.

EDIT:

As for the access_control, when I look at the code in Symfony\Component\HttpFoundation\RequestMatcher, it does not look for a route name. So I see two options.

  1. You find a way to create your own RequestMatcher and make Symfony using it, which in my opinion seems overcomplicated for what you need.
  2. Make an entry for every locale in access_control which you are kind of doing right now. For better readability, I would normally put every entry on its own line instead of using regex or like you do, but that's just me.
Julien B.
  • 3,023
  • 2
  • 18
  • 33
  • Oh that's right, I thought I tried that... But still the problem for duplicate path on access_control... I don't know if I should create a new subject on this one... My question is about URL internationalized so it's okay to keep that here... – vincent PHILIPPE Nov 29 '20 at 20:59