Description
Symfony version(s) affected: Reproduced with 2.7.47 (LTS) and 3.4.10 (LTS). Probably other versions where PR #24805 was merged are affected as well.
Description
Apparently, access control behavior for the logout path was changed in bugfix releases of Symfony, I suppose this is caused by #24805.
In Symfony 2.7.46, the logout path was not considered by the access_control
rules defined in security.yml
. Starting from 2.7.47 it is, so an "Access Denied" exception is thrown if the logout path is not allowed.
Also see hslavich/OneloginSamlBundle#53
How to reproduce
This example reproduces this issue with a minimal Symfony 2.7 application created with the Symfony installer.
git clone https://github.com/xelan/symfony-logout-break.git
cd symfony-logout-break
composer install
php app/console server:start 0.0.0.0:8000
- Go to http://localhost:8000/app_dev.php => you see the default index page
- Go to http://localhost:8000/app_dev.php/test => you are prompted for login
- Login with username
user
, passwordpass
=> you see an example page with a logout link - Click the logout link => you get an "Access Denied" error message
If you change composer.json to "symfony/symfony": "2.7.46"
, run composer update
and test again, the last step (logout) is successful.
Possible Solution
IMHO, two approaches would be possible:
- Revert the access control behavior for the logout path (Retaining BC)
- Consider it a fixed security flaw (as logout path was not considered by the
access_control
configuration before), but clearly document the change in the upgrade guides for all supported versions.
Additional context
app/config/security.yml
:
security:
encoders:
Symfony\Component\Security\Core\User\User: plaintext
providers:
in_memory:
memory:
users:
user: { password: pass, roles: [ 'ROLE_USER' ] }
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
login:
pattern: ^/login$
security: false
secured_area:
pattern: ^/
form_login:
check_path: example_login_check
login_path: example_login
require_previous_session: false
logout:
path: example_logout
target: /
anonymous: ~
access_control:
- { path: ^/$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/test$, roles: ROLE_USER }
- { path: ^/, roles: ROLE_DUMMY_NO_ACCESS }