I have a Symfony 3 CRM with FOS User Bundle installed for the login. The issue is, most users of this CRM will be engineers belonging to a company who are only allowed to see certain parts, so I have created their own dashboard specifically. Admin users can see everything and simply redirect to the main dashboard. However, it seems that only users with ROLE_ADMIN are allowed to access the CRM and everyone else is denied regardless of where they go.
Here is my security file:
security:
encoders:
FOS\UserBundle\Model\UserInterface: bcrypt
role_hierarchy:
ROLE_STAFF: ROLE_USER
ROLE_ADMIN: ROLE_STAFF
ROLE_SUPER_ADMIN: ROLE_ADMIN
providers:
fos_userbundle:
id: fos_user.user_provider.username
firewalls:
main:
pattern: ^/
form_login:
provider: fos_userbundle
csrf_token_generator: security.csrf.token_manager
# if you are using Symfony < 2.8, use the following config instead:
# csrf_provider: form.csrf_provider
use_referer: false
success_handler: login_success_handler
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: ^/, role: ROLE_ADMIN }
- { path: ^/staff-dashboard, role: ROLE_STAFF }
As you can see I have created a custom role called ROLE_STAFF which is assigned to engineers (or staff members) and they are allowed to view the staff-dashboard link. I have a test user with the ROLE_STAFF role but I still am unable to view staff-dashboard.
I also have the following if statement in my controller, so it redirects all those users who are NOT admin to the staff-dashboard:
if($userRole === "ROLE_ADMIN") {
return $this->render('AppBundle:pages:dashboard.html.twig', array(
'latest' => $latest,
'cashflow_chart' => $ob,
'job_chart' => $ob2
));
} else {
return $this->redirectToRoute('app_staff_dashboard');
}
But again, this does not work.
Any help with this is appreciated - I haven't yet found a solid solution.
Access control rules are processed in order specified in config. First matched rule (matched path) is checked and processing stops.
For your case 2 rules match path /staff-dashboard: 1 - { path: ^/, role: ROLE_ADMIN } and 2 - { path: ^/staff-dashboard, role: ROLE_STAFF }. The 1-st one is checked. Staff users don't pass this rule.
Change the order of these 2 rules.
Related
I'm setting up Symfony 4 to create new website, but when I want to login with user, who have multiple role ROLE_USER and ROLE_ADMIN, I'm redirected to login page. With just one role ROLE_USER I can login, How to solve this problem ?
Configuration is PHP 7.2, Symfony 4.2, Web Server Built-in Symfony "server:start".
I've tried to change security configuration but nothing change.
security.yaml
security:
encoders:
App\Entity\User: plaintext
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: ROLE_ADMIN
# https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
providers:
fos_userbundle:
id: fos_user.user_provider.username_email
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
secured_area:
# this firewall applies to all URLs
pattern: ^/
# but the firewall does not require login on every page
# denying access is done in access_control or in your controllers
anonymous: ~
# This allows the user to login by submitting a username and password
# Reference: http://symfony.com/doc/current/cookbook/security/form_login_setup.html
form_login:
# fos user bundle handles the form login
#provider: fos_userbundle
# The route name that the login form submits to
check_path: fos_user_security_check
# The name of the route where the login form lives
# When the user tries to access a protected page, they are redirected here
login_path: fos_user_security_login
# Secure the login form against CSRF
# Reference: http://symfony.com/doc/current/cookbook/security/csrf_in_login_form.html
csrf_token_generator: security.csrf.token_manager
logout:
# The route name the user can go to in order to logout
path: fos_user_security_logout
# The name of the route to redirect to after logging out
target: homepage
# Easy way to control access for large sections of your site
# Note: Only the *first* access control that matches will be used
access_control:
- { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/categories, role: ROLE_ADMIN }
- { path: ^/tags, role: ROLE_ADMIN }
- { path: ^/typewords, role: ROLE_ADMIN }
- { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin, role: ROLE_ADMIN }
- { path: ^/, role: ROLE_USER }
routes.yaml
controllers:
resource: '../src/Controller/'
type: annotation
fos_user:
resource: "#FOSUserBundle/Resources/config/routing/all.xml"
easy_admin_bundle:
resource: '#EasyAdminBundle/Controller/EasyAdminController.php'
prefix: /admin
type: annotation
I expect to login with another ROLE than ROLE_USER.
By hierarchy, a user with ROLE_ADMIN automatically has the ROLE_USER. So just remove ROLE_USER from that user. Not sure how the roles are loaded from the user provider, check also how ROLE_ADMIN is written in the database or what you use to map the User entity. (Include the mapping file for the user entity for further insight)
I am having issues securing a route 'dashboard' to a custom user role. I am using FOSUserBundle and I am aware that due to due users are given ROLE_USER by default - even though this role does appear in the user table.
On a user sign in (this happens via Steam) I add a new custom
$user->setRoles(['ROLE_LOGGED_STEAM_USER']);
My issue flows as such - User hits site - User logs in - redirect to Dashboard route - with the access denied error.
I have also disabled the security line and dumping out the ROLES to which I can pull from the token user object to confirm the ROLE exists and matches the rule
Here is my security ACL
security:
encoders:
FOS\UserBundle\Model\UserInterface: sha512
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: ROLE_ADMIN
providers:
steamauth:
id: steam.user_provider
fos_userbundle:
id: fos_user.user_provider.username
firewalls:
main:
provider: steamauth
pattern: ^/
form_login:
provider: fos_userbundle
logout: true
anonymous: true
form_login:
login_path: login
check_path: login_check
steam:
default_route: controller.dashboard.home
access_control:
- { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/dashboard, role: ROLE_LOGGED_STEAM_USER }
Initially, I wasn't aware that all roles had to Begin with ROLE_*
Here is a screenshot of the user entry with the role attached here
I hope its somthing simple im just overlooked so any help would be great!
Thanks it advance for any help/suggestions!
Not sure but I think you have a typo, please try changing role to roleS wtih "s"
- { path: ^/dashboard, roles: ROLE_LOGGED_STEAM_USER }
I think you must register your custom role on the "role_hierarchy" so the code will be:
role_hierarchy:
ROLE_ADMIN: [ROLE_USER, ROLE_LOGGED_STEAM_USER]
ROLE_SUPER_ADMIN: ROLE_ADMIN
Hope it help.
I am using Symfony 3.2 and fos user bundle 2.0
I use the classic setup : "Getting Started With FOSUserBundle"
security:
always_authenticate_before_granting: true
encoders:
FOS\UserBundle\Model\UserInterface: bcrypt
role_hierarchy:
ROLE_ADMIN: ROLE_CLIENT
providers:
fos_userbundle:
id: fos_user.user_provider.username
firewalls:
main:
pattern: ^/
form_login:
provider: fos_userbundle
csrf_token_generator: security.csrf.token_manager # Use form.csrf_provider instead for Symfony <2.4
logout: true
anonymous: ~
access_control:
- { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin, role: ROLE_ADMIN }
- { path: ^/client, role: ROLE_CLIENT }
It work but something is strange :
When I logout and navigate to public page it appears as I am always logged
I need to manually reload the page in my browser to make the logout effective.
( I use the {% if is_granted('ROLE_ADMIN') %} in my template )
Is it a problem with my security configuration or a problem with cache memory?
Some help will bee appreciated
thank
Vincent
Try adding the ROLE_USER to your role hierarchy like this:
role_hierarchy:
ROLE_CLIENT: ROLE_USER
ROLE_ADMIN: ROLE_CLIENT
As stated in the docs: "Make sure every user has at least one role, or your user will look like they're not authenticated. A common convention is to give every user ROLE_USER." http://symfony.com/doc/current/security.html#roles
today I have noticed I can always access the register and reset form regardless if I am authenticated or not.
Here is 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_provider.username
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
pattern: ^/
form_login:
provider: fos_userbundle
csrf_provider: form.csrf_provider
logout:
delete_cookies:
activeGame: {}
anonymous: true
access_control:
- { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin/, role: ROLE_ADMIN }
Regarding http://symfony.com/doc/current/cookbook/security/remember_me.html#forcing-the-user-to-re-authenticate-before-accessing-certain-resources it seems "normal" to be able to access this pages.
But how can I "easily" disable it for authenticated user or did I miss anything?
Thanks in advance!
You may be able to accomplish what you are looking for by using the newly introduced allow_if expression for access controls.
- { path: ^/register, allow_if: "not is_authenticated()" }
Another way may be:
- { path: ^/register, allow_if: "user == 'anon'" }
I havent fully tested this but it should only allow users who are not authenticated fully or authenticated remembered to access that path
Here is a little bit about the security
Here are some of the variable and functions available in expressions
Then here is some info on the Expressions you can use in allow_if
IF however, you do not want to throw a 403 Access Denied Exception when logged in users try and access those pages. Instead you would like to redirect them elsewhere then you can add a check to their respective controller actions. Something like:
public function registerAction()
{
if (true === $this->get('security.context')->isGranted('IS_AUTHENTICATED_REMEMBERED')) {
return $this->redirect($this->generateUrl('some_route_to_send_them_to'));
}
// ...
}
Background
According to the Symfony documentation the login form needs to be specified on the security.yml file, also hes login_check path. Until now my app is working fine, users tries to access a secure page (mysite.com/edit/123) next if they are not logged they will be redirected to /login and after they login they will be redericted again to the original intended path (/edit/123).
Similar question: Two separate login pages in Symfony 2
Problem
The problem now is, i need a different login form, lets say /minimal_login, i need to include that on the security.yml but the only way i know is creating a different firewall, and as i saw on the documentation this creates a separate identification scheme, so i suppose users logged by differents firewall can not share the same secured pages, and thats not what i want.
What is need
If the user tries to access any secure page but /popup they will be redirected to /login, BUT if they tries to access /popup (and they are not logged) they will be redirected to /minimal_login. And no matter how the user logs into my app, they will always share the same access, i mean, if they log in using /login or /minimal_login they can access the same pages.
My secuity.yml
jms_security_extra:
secure_all_services: false
expressions: true
security:
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: [ ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH ]
providers:
main:
entity: {class: Done\PunctisBundle\Entity\User, property: username}
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
remember_me:
key: %secret%
lifetime: 3600
path: /
domain: ~
pattern: ^/
anonymous: ~
form_login:
login_path: /login
check_path: /login_check
logout:
path: /logout
target: /
access_control:
- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/signup, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/verification, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/popup/, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/ajax/track, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/ajax/socialbox, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/, roles: ROLE_USER }
encoders:
Done\PunctisBundle\Entity\User:
algorithm: md5
iterations: 1
encode_as_base64: false
I faced a similar problem and I solved using the firewall context configuration.
firewalls:
somename:
# ...
context: my_context
othername:
# ...
context: my_context
http://symfony.com/doc/current/reference/configuration/security.html#firewall-context