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...
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.
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.