{"action":"created","issue":{"url":"https://api.github.com/repos/symfony/symfony/issues/16378","labels_url":"https://api.github.com/repos/symfony/symfony/issues/16378/labels{/name}","comments_url":"https://api.github.com/repos/symfony/symfony/issues/16378/comments","events_url":"https://api.github.com/repos/symfony/symfony/issues/16378/events","html_url":"https://github.com/symfony/symfony/issues/16378","id":114010601,"number":16378,"title":"[Security] Improvement/Evolution: several firewalls with the same pattern","user":{"login":"david-fanin","id":9631150,"avatar_url":"https://avatars.githubusercontent.com/u/9631150?v=3","gravatar_id":"","url":"https://api.github.com/users/david-fanin","html_url":"https://github.com/david-fanin","followers_url":"https://api.github.com/users/david-fanin/followers","following_url":"https://api.github.com/users/david-fanin/following{/other_user}","gists_url":"https://api.github.com/users/david-fanin/gists{/gist_id}","starred_url":"https://api.github.com/users/david-fanin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/david-fanin/subscriptions","organizations_url":"https://api.github.com/users/david-fanin/orgs","repos_url":"https://api.github.com/users/david-fanin/repos","events_url":"https://api.github.com/users/david-fanin/events{/privacy}","received_events_url":"https://api.github.com/users/david-fanin/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":1,"created_at":"2015-10-29T09:25:34Z","updated_at":"2015-10-29T10:22:24Z","closed_at":null,"body":"Hello!\r\n\r\n# Context:\r\nI am currently working on a site where some features are only available to authenticated members. So I have the following firewall configuration:\r\n\r\n/app/config/security.yml:\r\n\r\n    security:\r\n        encoders:\r\n            members:\r\n                class:              VE\\ProjectBundle\\Model\\Member\r\n                algorithm:          sha1\r\n                iterations:         1\r\n                encode_as_base64:   false\r\n        providers:\r\n            members:\r\n                propel:\r\n                    class:      VE\\ProjectBundle\\Model\\Member\r\n                    property:   email\r\n        firewalls:\r\n            member_area:\r\n                pattern:    ^/\r\n                provider:   members\r\n                anonymous:  ~\r\n                form_login:\r\n                    login_path:             /member\r\n                    check_path:             /member/validate-login\r\n                    username_parameter:     email\r\n                    password_parameter:     password\r\n                    default_target_path:    /member\r\n                logout:\r\n                    path:   /member/logout\r\n                    target: /member\r\n                    invalidate_session: false\r\n\r\nI also have an administration area accessible to the URL \"/administration\" and which the following configuration:\r\n\r\n/app/config/security.yml:\r\n\r\n    security:\r\n        encoders:\r\n            administrators:\r\n                class:              VE\\AdministrationBundle\\Model\\Administrator\r\n                algorithm:          sha1\r\n                iterations:         1\r\n                encode_as_base64:   false\r\n        providers:\r\n            administrators:\r\n                propel:\r\n                    class:      VE\\AdministrationBundle\\Model\\Administrator\r\n                    property:   email\r\n        firewalls:\r\n            administration_area:\r\n                pattern:    ^/administration\r\n                provider:   administrators\r\n                anonymous:  ~\r\n                form_login:\r\n                    login_path:             /administration/administrator/login\r\n                    check_path:             /administration/administrator/validate-login\r\n                    username_parameter:     email\r\n                    password_parameter:     password\r\n                    default_target_path:    /administration\r\n                    csrf_parameter:         _token\r\n                logout:\r\n                    path:   /administration/administrator/logout\r\n                    target: /administration\r\n                    invalidate_session: false\r\n        access_control:\r\n            administration_administrator_login:\r\n                path: ^/administration/administrator/login\r\n                roles: IS_AUTHENTICATED_ANONYMOUSLY\r\n            administration:\r\n                path: ^/administration\r\n                roles: ROLE_ADMIN\r\n\r\n# Problem:\r\nI want to show in the global template of the site (behind the firewall \"member_area\") a link to return to the administration when the visitor is authenticated to the firewall \"administration_area\". In fact, I try to do something more complex, but I simplified the problem to be more clear.\r\n\r\n/src/VE/ProjectBundle/Resources/views/globalTemplate.html.twig:\r\n\r\n    {% if app.user and is_granted('ROLE_ADMIN') %}\r\n        <a href=\"#\">Return to administration</a>\r\n    {% endif %}\r\n\r\nExcept that the pattern of the firewall is \"/administration\", the firewall \"administration_area\" is not active for the URL \"/home\" for example. In addition, if \"app.user\" is defined, it will contain an object \"Member\" and not an object \"Administrator\".\r\n\r\nChange the pattern of the firewall \"administration_area\" to \"^/\" does not solve anything because the firewall \"member_area\" is executed before.\r\n\r\nChanging the order of firewalls in the configuration ask the opposite problem. If \"app.user\" is defined, it will contain an object \"Administrator\" and not an object \"Member\".\r\n\r\nShare the same context between the two firewalls appears not to be either a solution because we have not a single object \"User\". I want absolutely to have two separate entities (Member and Administrator).\r\n\r\n# Solution:\r\nI suggest here a solution or rather an idea based on the existing. There maybe/probably better to do.\r\nThe idea is to have multiple firewalls for the same pattern.\r\n\r\n/app/config/security.yml:\r\n\r\n    security:\r\n        firewalls:\r\n            member_area:\r\n                pattern:    ^/\r\n            administration_area:\r\n                pattern:    ^/\r\n\r\n\r\nOn the side of a controller, you could do this:\r\n\r\n/src/VE/ProjectBundle/Controller/ShowPageController.php:\r\n\r\n    if ($this->getUser('member_area') && $this->isGranted('editProfile', null, 'member_area')) {\r\n        // Can edit his profile\r\n    }\r\n\r\n    if ($this->getUser('administration_area') && $this->isGranted('ROLE_ADMIN', null, 'administration_area')) {\r\n        // Is admin authenticated\r\n    }\r\n\r\n\r\nThe side of a Twig template, we could do this:\r\n\r\n/src/VE/ProjectBundle/Resources/views/globalTemplate.html.twig:\r\n\r\n    {% if app.firewalls.member_area.user and is_granted('editProfile', null, null, 'member_area') %}\r\n        <a href=\"#\">Edit my profile</a>\r\n    {% endif %}\r\n\r\n    {% if app.firewalls.administrator_area.user and is_granted('ROLE_ADMIN', null, null, 'administration_area') %}\r\n        <a href=\"#\">Return to administration</a>\r\n    {% endif %}\r\n\r\n\r\n# Meanwhile?\r\nDo you have one or more other \"temporary\" solutions that solve my problem?\r\n\r\nThank you!"},"comment":{"url":"https://api.github.com/repos/symfony/symfony/issues/comments/152137406","html_url":"https://github.com/symfony/symfony/issues/16378#issuecomment-152137406","issue_url":"https://api.github.com/repos/symfony/symfony/issues/16378","id":152137406,"user":{"login":"iltar","id":1754678,"avatar_url":"https://avatars.githubusercontent.com/u/1754678?v=3","gravatar_id":"","url":"https://api.github.com/users/iltar","html_url":"https://github.com/iltar","followers_url":"https://api.github.com/users/iltar/followers","following_url":"https://api.github.com/users/iltar/following{/other_user}","gists_url":"https://api.github.com/users/iltar/gists{/gist_id}","starred_url":"https://api.github.com/users/iltar/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/iltar/subscriptions","organizations_url":"https://api.github.com/users/iltar/orgs","repos_url":"https://api.github.com/users/iltar/repos","events_url":"https://api.github.com/users/iltar/events{/privacy}","received_events_url":"https://api.github.com/users/iltar/received_events","type":"User","site_admin":false},"created_at":"2015-10-29T10:22:24Z","updated_at":"2015-10-29T10:22:24Z","body":"You can create a shared context: http://symfony.com/doc/current/reference/configuration/security.html#firewall-context\r\n\r\nI would recommend to just share the same firewall though, because that's what it is. When your user is an administrator, just assign the `ROLE_ADMIN` to him."}}