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(.*)
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've been having an issue with Symfony 3.3.9. Sometimes, not always, when a user logs in with the correct username and password, it redirects to the main page like it should, but then back to the login page.
I know the user is logged in because I can grab the user's information with twig from the login page.
It is really strange, because this doesn't happen all the time. It seems random and difficult to reproduce.
I've been looking into this issue for days and can't figure out why this is happening. Looking for some suggestions.
Thanks.
Edit-1 added code
Edit-2
When I get redirected to the login, I've tried typing the main page url to manually go there. This doesn't work, even though I am logged in. If I wait a minute or so however, this does work.
I'm using the FOS user bundle
here's my config.yml
# fos bundle
fos_user:
db_driver: orm
firewall_name: main
user_class: Acme\Entity\User
here's my security.yml
security:
encoders:
FOS\UserBundle\Model\UserInterface: bcrypt
role_hierarchy:
ROLE_EMPLOYEE: [ROLE_USER]
ROLE_MANAGER: [ROLE_EMPLOYEE]
ROLE_ADMIN: [ROLE_MANAGER]
ROLE_SUPER_ADMIN: [ROLE_ADMIN,ROLE_ALLOWED_TO_SWITCH]
providers:
fos_userbundle:
id: fos_user.user_provider.username
firewalls:
main:
pattern: ^/
form_login:
provider: fos_userbundle
csrf_token_generator: security.csrf.token_manager
always_use_default_target_path: true
default_target_path: after_login
# if you are using Symfony < 2.8, use the following config instead:
# csrf_provider: form.csrf_provider
logout: true
anonymous: true
switch_user: true
access_control:
- { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/administration/roe, role: ROLE_ADMIN }
- { path: ^/administration/generateaccessemployees, role: ROLE_ADMIN }
- { path: ^/administration/location, role: ROLE_ADMIN }
- { path: ^/administration/payroll/closepp, role: ROLE_ADMIN }
- { path: ^/administration/t4, role: ROLE_ADMIN }
- { path: ^/administration/eft, role: ROLE_ADMIN }
- { path: ^/administration/stubmessage, role: ROLE_ADMIN }
- { path: ^/administration/payroll_reminder, role: ROLE_ADMIN }
- { path: ^/administration, role: ROLE_MANAGER }
- { path: ^/admin/exit_impersonation, role: ROLE_PREVIOUS_ADMIN }
- { path: ^/admin, role: ROLE_SUPER_ADMIN }
In my login_content.html.twig, I'm able to see:
{{ app.user.username }}
Definitely would need to see some code, more specifically to help get to the root of the problem whatever function is run on login.
EDIT:
In the security.yml you can specify a login_path, in example:
my_firewall:
pattern: ^/(secured_area)/
provider: my_provider
anonymous: ~
form_login:
login_path: my_login_path
default_target_path: /dashboard
And in the routing.yml you can map the route as:
my_login_path:
pattern: /my/relative/url/for/login
defaults: { _controller: MySecurityBundle:Security:login }
then you can use an a normal route, in you specific case:
return $this->forward($this->generateUrl('my_login_path'));
The only reason I suggest this is because default routing after login is causing issues for you.
I switched to my prod environemnt today and started testing. Everything is working great with my admin user. The problem is when I switch to another user, that has a role PROVIDER. This user is only able to add products or import them in admin panel. However, when I go to admin dashboard I get these errors:
Warning: Missing argument 1 for Sonata\AdminBundle\Admin\Admin::__construct(), called in C:\wamp\www\karpedeal_b2c\vendor\ed\blog-bundle\Security\Authorization\Voter\ArticleVoter.php on line 37 and defined in C:\wamp\www\karpedeal_b2c\app\cache\prod\classes.php on line 5473
No idea whats going on since in DEV environment everything works. I can login with provider user, import products etc... in prod, i cant.
For some reason it is trying to access somethin in the blog bundle, however this user does not have any rights to blogs... What is the problem then?
role_hierarchy:
ROLE_PROVIDER: [ROLE_USER, ROLE_SONATA_PROVIDER]
ROLE_ADMIN: [ROLE_USER, ROLE_SONATA_PROVIDER, ROLE_SONATA_ADMIN, ROLE_BLOG_USER, ROLE_BLOG_ADMIN]
ROLE_SUPER_ADMIN: [ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
ROLE_SONATA_PROVIDER:
- ROLE_MP_SHOP_ADMIN_PRODUCT_LIST
- ROLE_MP_SHOP_ADMIN_PRODUCT_VIEW
- ROLE_MP_SHOP_ADMIN_IMPORTER_LIST
- ROLE_MP_SHOP_ADMIN_IMPORT_SCHEMA_CREATE
- ROLE_MP_SHOP_ADMIN_IMPORT_SCHEMA_LIST
SONATA:
- ROLE_SONATA_PAGE_ADMIN_PAGE_EDIT # if you are using acl then this line must be commented
ROLE_SONATA_EMPLOYEE:
- ROLE_MP_SHOP_ADMIN_PRODUCT_LIST
- ROLE_MP_SHOP_ADMIN_PRODUCT_VIEW
firewalls:
# disables authentication for assets and the profiler, adapt it according to your needs
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
admin:
pattern: /admin(.*)
context: user
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
main:
pattern: ^/
context: user
form_login:
provider: fos_userbundle
csrf_provider: form.csrf_provider
login_path: /login
#use_forward: false
check_path: fos_user_security_check
#failure_path: null
always_use_default_target_path: false
default_target_path: profile
logout:
path: fos_user_security_logout
oauth:
resource_owners:
facebook: "/login/check-facebook"
login_path: /login
failure_path: /login
oauth_user_provider:
service: my_user_provider
anonymous: true
default:
anonymous: ~
# activate different ways to authenticate
access_control:
# URL of FOSUserBundle which need to be available to anonymous users
- { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
# Admin login page needs to be access without credential
- { path: ^/admin/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin/logout$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin/login_check$, role: IS_AUTHENTICATED_ANONYMOUSLY }
# Secured part of the site
# This config requires being logged for the whole site and having the admin role for the admin part.
# Change these rules to adapt them to your needs
- { path: ^/admin/, role: [ROLE_PROVIDER, ROLE_ADMIN, ROLE_SONATA_ADMIN, ROLE_SONATA_PROVIDER] }
- { path: ^/.*, role: IS_AUTHENTICATED_ANONYMOUSLY }
acl:
connection: default
UPDATE:
When changing AppKernel $kernel = new AppKernel('prod', true);everything works, so the debugger is causing the problems? How can that be?
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.
So I've mangaged to get the FOSFacebook bundle integrated into my app alongside the FOSUser bundle. Now it's working properly on my dev server minus a few bugs but it works.
UPDATE: So for some reason facebook is setting the cookie to mysite.com.au instead of subdomain.mysite.com which means that it fails to pick up on the cookie and goes to the default failure page which is /facebook/login.
Now for some reason when I deployed it to my live server, which has the same address(I'm changing my hosts file to simulate the domain) when I try to login I get
"No route found for "GET /facebook/login"
If I try to access this page on the dev, I get the same message, but normally it logs me in and then redirects me to the index.
On the live it gets stuck on /facebook/login
Here's my security.yml
security:
encoders:
"FOS\UserBundle\Model\UserInterface": sha512
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
providers:
fos_userbundle:
id: fos_user.user_manager
my_fos_facebook_provider:
id: my.facebook.user
factories:
- "%kernel.root_dir%/../vendor/bundles/FOS/FacebookBundle/Resources/config/security_factories.xml"
firewalls:
public:
pattern: ^/
fos_facebook:
app_url: "(set to the apps.facebook link I have)"
server_url: "http://testbed.mysite.com/app_dev.php/"
check_path: /facebook/check
login_path: /facebook/login
default_target_path: /
provider: my_fos_facebook_provider
form_login:
success_handler: authentication_handler
failure_handler: authentication_handler
provider: fos_userbundle
anonymous: true
logout: true
access_control:
- { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/testing/secure/, role: IS_AUTHENTICATED_FULLY }
- { path: ^/admin/secure/, role: ROLE_ADMIN }
- { path: ^/account, role: IS_AUTHENTICATED_FULLY }
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: ROLE_ADMIN
If you need a look at any other files, let me know
Obviously there is no route for /facebook/login but I believe it's supposed to be that way.
Any ideas people?
Just define login_path as the default path set up in the security.yml :
_security_login:
pattern: /login
requirements:
_scheme: https
_security_check:
pattern: /login_check
requirements:
_scheme: https
_security_logout:
pattern: /logout
requirements:
_scheme: https
You can define your own controller for login_path if you need some specific treatment but you don't have to !
It turns out that somehow on my live site I'd forgotten to setup parameters.ini correctly and as such whenever I attempted to login it'd fail but never actually fully fail.