I'm using two firewalls with same pattern for two types of users:
Admin with access to both frontend and backend who can see some extra controls in frontend app then normal user.
User who can access only frontend.
This is my simplified security.yml configuration:
firewalls:
admin:
pattern: .*
form_login:
login_path: /admin/login
check_path: /admin/login
logout:
path: /admin/logout
...
front:
pattern: .*
form_login:
login_path: /user/login
check_path: /user/login-check
logout: true
anonymous: true
...
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
access_control:
- { path: ^/admin/, role: ROLE_ADMIN }
- { path: ^/admin/login, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/user/login, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/user/profile, role: ROLE_FRONTEND_USER }
- { path: ^/user/upload-photo, role: ROLE_FRONTEND_USER }
...
The problem is that when any non loggedin user tries to access for example /user/profile they're redirected to /admin/login. I Guess this is because there's no connection between firewall and access_control so Symfony can't know if the user tried to access section for ROLE_FRONTEND_USER or ROLE_ADMIN and then redirected accordingly.
My question is, is there any elegant way to solve this? Maybe use an event listener and manually check on denied permissions whether the requested URL required ROLE_FRONTEND_USER or ROLE_ADMIN roles?
You can manually set the url where the user will be redirected :
front:
pattern: .*
# ...
access_denied_url: /user/login
Anonymous users will be redirected to the expected login route without need of a specific pattern per firewall.
Hope this solves your problem.
Related
On my website, I have 3 sections : Admin, Members and Public. The Admin section is only reachable through "gestion.%domain%", and must have an Admin User. This section works great.
For the Members section, it is reachable through "membre.%domain%", and must have a Member User. This also works great.
The problem comes to the Public section. Every part of this section is accessible either anonymously or logged in with a Member User. When logged in, the top menu will change a bit to show more option (kinda like any shopping website).
So I've configured my security settings as follow :
security:
providers:
membre_provider:
id: App\Security\Provider\MembreProvider
manager_provider:
id: App\Security\Provider\ManagerProvider
encoders:
App\Entity\Utilisateur: sha512
role_hierarchy:
ROLE_MEMBRE: [ROLE_NON_MEMBRE]
ROLE_SUPER_ADMIN: [ROLE_ADMIN]
ROLE_ADMIN: [ROLE_EDITEUR]
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
admin:
host: 'gestion.%domain%'
pattern: .*
anonymous: ~
form_login:
login_path: admin_login
check_path: admin_login
access_denied_url: admin_access_denied
provider: manager_provider
logout:
path: admin_logout
target: admin_login
main:
pattern: .*
anonymous: true
form_login:
login_path: membre_login
check_path: membre_login
access_denied_url: membre_login
provider: membre_provider
user_checker: App\Security\MembreUserChecker
logout:
path: membre_logout
target: index
remember_me:
secret: '%kernel.secret%'
name: 'remember_me_main'
lifetime: 604800 # 1 week in seconds
path: /
always_remember_me: true
access_control:
- { path: ^/connexion, roles: IS_AUTHENTICATED_ANONYMOUSLY, host: 'membre.%domain%' }
- { path: ^/demande_reinitialisation, roles: IS_AUTHENTICATED_ANONYMOUSLY, host: 'membre.%domain%' }
- { path: ^/reinitialisation, roles: IS_AUTHENTICATED_ANONYMOUSLY, host: 'membre.%domain%' }
- { path: ^/, roles: ROLE_NON_MEMBRE, host: 'membre.%domain%'}
- { path: ^/connexion, roles: IS_AUTHENTICATED_ANONYMOUSLY, host: 'gestion.%domain%' }
- { path: ^/, roles: ROLE_EDITEUR, host: 'gestion.%domain%'}
- { path: ^/, roles: IS_AUTHENTICATED_ANONYMOUSLY}
As you can see, I have the admin context and the main context. The main context is shared between the "Members" section and the "Public" section. And it does work as intended when testing it (in the "Security" tab of the profiler, both shows as "main" context)
The problem is when I try to get the logged in user infos in the public section, I always get the anonymous token (it even shows the anonymous token in the profiler), but when I'm in the "Members" section, I can get the logged in user correctly.
I'm completely lost there...
Ok, so I have managed to solve my issue. The problem came from the session handling. Since I have multiple sub-domains, the session wasn't shared between them, so my public section wasn't aware that the user was logged in in the member section.
The only thing I had to configure was the session parameters in framework.yml :
session:
handler_id: ~
cookie_domain: '.%domain%'
name: 'MYAPPSESSID'
EDIT : This SO answer helped me in finding and solving the problem : https://stackoverflow.com/a/29850083/1907465
I have a problem concerning identification, authentication and redirection on Symfony2 (v2.8.9).
I installed HWIOAuthBundle in order to use the Google Sign-in and based on a User Bundle handmade. The website is completely closed to anonymous users and you need to login to use it.
My problem is that in order to access a precise URL given by someone, and land on it after you logged in via the login page, I set in the app/config/config.yml the use_referer to true.
Since then, when someone goes directly to the /login page, once he's authenticated, he's taken back to the /login page instead of being re-directed on the private homepage of the website (/hub defined by the route rnd_hub_homepage). He's taken there properly identified and authenticated but I wish he shouldn't land there but on the /hub page.
If I set the line always_use_default_target_path to true in app/config/security.yml, then the use_referer is no longer taken into account for others URLs...
Here is my extract for the file app/config/security.yml:
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
login:
pattern: ^/login$
anonymous: true
main:
pattern: ^/
anonymous: true
#logout: true
logout:
path: /logout
target: /login
oauth:
resource_owners:
google: "/login/check-google"
login_path: /login
always_use_default_target_path: false
failure_path: /login
oauth_user_provider:
service: ib_user.oauth_user_provider
access_control:
- { path: ^/hub, roles: IS_AUTHENTICATED_FULLY }
- { path: ^/user, roles: ROLE_USER }
- { path: ^/XXX, roles: ROLE_XXX }
- { path: ^/YYY, roles: ROLE_YYY }
- { path: ^/ZZZ, roles: ROLE_ZZZ }
- { path: ^/AAA, roles: ROLE_AAA }
- { path: ^/BBB, roles: ROLE_BBB }
- { path: ^/DDD, roles: ROLE_DDD }
- { path: ^/EEE, roles: ROLE_EEE }
- { path: ^/admin, roles: ROLE_ADMIN }
And here is the extract of my app/config/config.yml file:
hwi_oauth:
firewall_names: [main]
target_path_parameter: rnd_hub_homepage
use_referer: true
resource_owners:
google:
type: google
#etc....
Thank you in advance for your various inputs on this question...
(sorry for my english, I'm french born)
I think you have defined 2 times logout configuration. Try to remove:
logout: true
In an application I am developing, I'm having a weird issue with the access control for the security component.
I use the FOSUserBundle (of course) for users and I copied the example access control rules from the bundle documentation to my security.yml The login screen (/login) works perfectly but the issue is, all other access control rules have absolutely no effect whatsoever. When a user goes to /register for example, he is redirected to /login, the same goes for /resetting.
This is my security.yml file:
jms_security_extra:
secure_all_services: false
expressions: true
security:
encoders:
FOS\UserBundle\Model\UserInterface: sha512
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: ROLE_ADMIN
providers:
fos_userbundle:
id: fos_user.user_provider.username_email
firewalls:
dev:
pattern: ^/(\_(profiler|wdt)|css|images|js)/
security: false
api:
pattern: ^/api
anonymous: false
form_login: false
provider: fos_userbundle
http_basic:
realm: "REST Service Realm"
main:
pattern: ^/
form_login:
provider: fos_userbundle
csrf_provider: form.csrf_provider
logout: true
anonymous: ~
switch_user: { role: ROLE_SUPER_ADMIN, parameter: _impersonate }
access_control:
- { path: ^/login, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/superadmin/, role: ROLE_SUPER_ADMIN }
I have tried to turn of security for paths containing /resetting and /register, but that clearly won't work since the security token still needs to be available for the FOSUserBundle controllers.
Any help would be much appreciated!
It might be to do with the order of the access_control, try putting superadmin above the others. You also don't seem to have a secured_area section (like this example from Symfony2 access control redirects to login)
security:
firewalls:
secured_area:
pattern: ^/
anonymous: ~
form_login:
login_path: login
check_path: login_check
The problem was that another bundle was messing with each request checking if the user was logged in or not. If the user wasn't logged in, a redirect response was generated to the login page.
No idea why this was done, I think it comes from an era where the original authors had less experience with Symfony.
But so it proves again, always check the logs. Very thoroughly.
I think I don't fully understand the concept of firewall and access control of symfony but here's my understanding.
I have FOSUserBundle installed and configured properly.
I created some roles:
role_hierarchy:
ROLE_COACH: [ROLE_USER]
ROLE_EDITOR: [ROLE_USER]
ROLE_PREMIUM_COACH : [ROLE_USER, ROLE_COACH]
ROLE_ADMIN: [ROLE_USER, ROLE_SONATA_ADMIN, ROLE_COACH, ROLE_EDITOR, ROLE_PREMIUM_COACH]
ROLE_SUPER_ADMIN: [ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
I want to prevent people from accessing the url /dashboard if they are not logged in, therefore if they don't have the role ROLE_USER.
Here's my firewall:
firewalls:
# -> custom firewall for the admin area of the URL
admin:
pattern: /admin(.*)
form_login:
provider: fos_userbundle
login_path: /admin/login
use_forward: false
check_path: /admin/login_check
failure_path: null
logout:
path: /admin/logout
anonymous: true
# -> end custom configuration
# defaut login area for standard users
main:
pattern: .*
form_login:
provider: fos_userbundle
csrf_provider: form.csrf_provider
login_path: /login
use_forward: false
check_path: /login_check
failure_path: null
logout: true
anonymous: true
Here's what I added under access_control:
- { path: ^/dashboard, role: [ROLE_USER]}
- { path: ^/dashboard/blog, role: [ROLE_EDITOR]}
I can access the page /dashboard even if I'm not connected and I don't want that possible. What am I getting wrong ?
From that pastebin
- { path: ^/.*, role: IS_AUTHENTICATED_ANONYMOUSLY }
this line is what cause your issue. This tells to symfony2 security system that every user can access everything (this is the "very first rule" if you ignore the FOS ones) and so, when this is satified, no other controll will be done (as - { path: ^/OSC/dashboard, role: ROLE_USER} came after)
Possibile solutions:
1) Place that line at the bottom of your acl.
PRO: your application will work
CONS: if you don't properly set all ACL, you'll run into "security" issues or some unauthorized users could access pages that, into your logic, they have not to access.
2) Remove that line at all
PRO: your application will not suffer from security issues and unauthorized access
CONS: you have to set all route explicitly and properly, but this is pretty "natural" if you want to build a strong application
The reason you're getting through is because there isn't a firewall for /dashboard, but (assuming you're trying to setup SonataAdminBundle) that's not what you're supposed to have in access_control
Here's how mine looks for Sonata:
access_control:
- { path: ^/admin/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin/logout$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin/login-check$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin, role: ROLE_ADMIN }
- { path: ^/.*, role: [IS_AUTHENTICATED_ANONYMOUSLY] }
Your firewall definition is fine otherwise.
If you're trying to configure you're own custom dashboard, then you need to define another firewall entry, very similar to the admin firewall.
EDIT:
Try changing pattern to: ^/.*
If you want to block just /OSC then: /OSC(.*)
I'm working on a project with Symfony2 where you must be logged to be able to see the website. I am using FOSUserBundle to create the member area. Here is the idea : if an anonymous comes to the website, I systematically redirect to the login page.
Here is my security.yml :
providers:
fos_userbundle:
id: fos_user.user_manager
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
realm: "Acces reserve"
login:
pattern: ^/(login$|register|resetting)
anonymous: true
main:
pattern: ^/
form_login:
provider: fos_userbundle
remember_me: true
remember_me:
key: %secret%
anonymous: true
logout: true
access_control:
- { path: ^/backoffice, roles: ROLE_ADMIN }
- { path: ^/, roles: ROLE_USER }
I think there is no reason for it not to work ; here is the problem now. I observed that I'm not logged the same in /login and in others areas. For example, if I log myself then I'm the user named "admin" with role "ROLE_USER" on the website BUT if I go then to /login, I'm logged as "anon" with no role at all.
Same problem but more boring: when a new user register, he's log on the /login page but not on the other pages... So he's always redirect to /login and the logout doesn't change anything. :/
Do you have an idea ?
Thanks !
P.S. : Is it possible to manually clean all sessions in Symfony2 ? 'cause I would like to be able to try other things but in Chrome I just can't do anything for now... I tryed clear the browser cache and cookies, clear Symfony cache, etc... Nothing changes, I'm still logged as "admin" on the /login page -_-
The thing is you specified the fos_userbundle provider only for main firewall, not for login and dev firewalls. So fos_userbundle isn't used for /login page at all.
The documentation says you should use this config:
firewalls:
main:
pattern: ^/
form_login:
provider: fos_userbundle
remember_me: true
remember_me:
key: %secret%
logout: true
anonymous: true
access_control:
- { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/backoffice, roles: ROLE_ADMIN }
- { path: ^/, roles: ROLE_USER }