Using dynamic roles in security.yml - symfony

I have a Ldap repository storing roles for users. They are already mapped to Symfony roles.
I would like to use them in the security.yml but I cannot hard code role values because they evolve with the application.
Is it possible to have something like this?
access_control:
- { path: ^/project/$project, roles: ROLE_$project_MEMBER }
Thanks.

Have you taken a look at implementing ACL? See also this piece of documentation.

i'm also stuck in the same problem you have to give roles which is stored in your in DB like
access_control:
- { path: ^/Services/, role: ROLE_USER }

there is no way and it's not good to do it the way I wanted, I've ended using the voters system using affirmative strategy

Related

Symfony 6 trouble with access_control - is_authenticated_fully etc

# set hierarchy for roles?
role_hierarchy:
# give admin also the roles inside the array.
ROLE_ADMIN: [ROLE_USER]
# 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: ^/admin, roles: ROLE_ADMIN }
# Unless the path is login, user must be authenticated anonymously.
# This means only page accessible anonymously is login page.
- { path: ^(/(login|register)), roles: IS_AUTHENTICATED_ANONYMOUSLY }
# can visit any other path if authenticated fully
- { path: ^/, roles: IS_AUTHENTICATED_FULLY }
This simple code doesn't seem to work. I cannot visit login or register anonymously. I know the IS_AUTHENTICATED_FULLY part is working as when I comment it out (and I am signed out, aka authenticated anonymously) I can visit other paths other than login and register.
Even when I simply do:
- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
It doesn't work and I cannot visit /login. What am I doing wrong?
I have been using this video as a guide: https://youtu.be/XjbIDOIoXTo?t=4211
Symfony 5.3 has deprecated the old authentication mechanism along with the Guard Component see https://symfony.com/blog/new-in-symfony-5-3-guard-component-deprecation. The new system doesn't "authenticate" user by default with IS_AUTHENTICATED_ANONYMOUSLY.
Anonymous users no longer exist
You now must use the PUBLIC_ACCESS as #Bossman specified in a comment. https://symfony.com/doc/current/security.html#allowing-unsecured-access-i-e-anonymous-users
The video in your link clearly states that the video has been recorded using Symfony 5.2
NOTICE - THIS SERIES WAS RECORDED USING SYMFONY 5.2. THERE HAVE BEEN SOME MINOR CHANGES AND SOME CLASSES HAVE SINCE BEEN REMOVED. YOU WILL STILL BE ABLE TO FOLLOW THIS TUTORIAL BUT YOU WILL NEED TO COMBINE IT THE DOCUMENTATION IN SOME PARTS.

Restrict Login for All pages for not logged in User: Symfony3

I am using fos bundle for Symfony and it's working fine but now I want to restrict all pages for not logged user except (login and register). How can I achieve that?
security.yml need to look like this:
access_control:
- { path: ^/(register|login)?$, roles: IS_AUTHENTICATED_ANONYMOUSLY}
- { path: ^/?$, roles: ROLE_USER}
Check Documentation for more Security Symfony !
Greetings Violence
I assume, that you use FosUserBundle and as stated in the comments, it's all explained in the Docs.
Have a look at "Step 4: Configure your application's security.yml"

Define roles in a bundle config

I have some questions about roles that I'm trying to understand a long time:
1. We have some bundles that we use in couple of projects. We would like to define roles in a bundle config, so that we do not copy roles into the role_hierarchy in security.yml. Is there any clean way to do it?
My first idea was to import them into role_hierarchy like this:
role_hierarchy:
ROLE_ADMIN: ROLE_USER, ROLE_TRANSLATOR
ROLE_SUPER_ADMIN: ROLE_ADMIN
ROLE_NOT_APPROVED_USER: ROLE_USER
ROLE_TRANSLATOR: ROLE_USER
"%base_bundle.role.hierarchy%"
This of course doesn't work. Is there any possibility to do it this way(merge arrays in yaml)?
My other idea was to store roles in DB, but in my opinion it's overkill, because we have no dynamic roles. Everything is static.
Is there any workaround to achieve what I try to do? Or is it a good idea to define it in a bundle?
2. I use roles as permissions (ROLE_POST_EDIT, ROLE_POST_DELETE, ...) and voters to deny or approve access to the resource. So at the end there are a tons of roles. Is it a good idea to mix roles with permissions? If not what is the best practise?
EDIT: I feel the difference between ROLE_POST_EDIT and ROLE_USER or ROLE_ADMIN. User has ROLE_USER because he is user. But user has "permission ROLE_EDIT_POST" to be able to edit a post. In my opinion there is a difference between. Anyway should I care about this difference or is there any other practise how to do?
We have some bundles that we use in couple of projects. We would like to define roles in a bundle config, so that we do not copy roles into the role_hierarchy in security.yml. Is there any clean way to do it?
You can use Prepended Extensions to "prepend" configuration of another extension:
class AcmeHelloExtension extends Extension implements PrependExtensionInterface
{
// ...
public function prepend(ContainerBuilder $container)
{
$container->prependExtensionConfig('security', [
'role_hierarchy' => [
'ROLE_ADMIN' => ...
...
],
]);
}
}
I use roles as permissions (ROLE_POST_EDIT, ROLE_POST_DELETE, ...) and voters to deny or approve access to the resource. So at the end there are a tons of roles. Is it a good idea to mix roles with permissions? If not what is the best practise?
A small misconfusion here: The roles you define with role_hierarchy are not related to the things you pass to isGranted(). You're passing attributes to isGranted(). Unfortunately, for the RoleHierarchyVoter, symfony decided to make the attributes similair to the role name (that is, if the role name starts with ROLE_).
Voters vote on permissions, or attributes as they are called. So it's perfectly valid and good practice to have many permissions in isGranted().
However, I recommend not to start them with ROLE_*. These attributes are checked by the RoleVoter/RoleHierarchyVoter. Name them e.g. POST_EDIT, POST_DELETE:
if ($this->isGranted('POST_EDIT', $post)) {
// ...
}

Symfony2 User permission managment

I come to you because I have a little concern about the management of users and their Permissions with Symfony2.
Let me explain:
I set up the FOSUserBundle:
What I'd like to do now is a rights management. I have an entity 'Post'.
I have users with roles specified below.
ROLE_GUEST - VIEW,RATE
ROLE_USER - VIEW,CREATE,RATE,EDIT_OWN
ROLE_EDITOR - VIEW,CREATE,RATE,EDIT,DELETE
I want to set permission to each roles for performing certain actions.
Thank you :)
If i understand your necessity correctly you want to have a security layer based on those roles. You can do this in may ways:
The symfony default way -
you can configure the security layer of symfony like in the example below
# app/config/security.yml
security:
# ...
access_control:
- { path: ^/post/view, roles: VIEW }
- { path: ^/post/rate, roles: RATE }
# etc
This will take care of route access control. More info on http://symfony.com/doc/current/cookbook/security/access_control.html
For more complex roles like EDIT_OWN, you can take the direct approach
if (!$post->isAuthor($this->getUser())) {
$this->denyAccessUnlessGranted('EDIT', $post);
// or without the shortcut:
//
// use Symfony\Component\Security\Core\Exception\AccessDeniedException;
// ...
//
// if (!$this->get('security.authorization_checker')->isGranted('edit', $post)) {
// throw $this->createAccessDeniedException();
// }
} else {
$this->denyAccessUnlessGranted('EDIT_OWN', $post);
}
For all this and more you can check the symfony site http://symfony.com/doc/current/best_practices/security.html
For even more advanced roles or ACL requirement also take a look here https://symfony.com/doc/current/components/security/authorization.html and at the authorization voters https://symfony.com/doc/current/components/security/authorization.html#voters
In the 4 links I provided in this post you should find all you need to implement RBAC as well as ACL. You can also find information about some annotations you may want to use. Also there are some extensions to the symfony security layer that may come in handy depending on the symfony version you are working on like JMS\SecurityExtraBundle.
Hope this help,
Alexandru Cosoi

How to use Neo4j with FOSUserBundle?

I am trying to adjust FOSUserBundle to work with my Neo4j database and I cant seem to get it working. After a long time of trying to implement my own user system without any luck (Setting up NEO4j in Symfony2), I started trying to use the FOSUserBundle.
I have used the following articles and repositories:
https://github.com/ikwattro/Neo4jUserBundle
I have taken this and copied all of the files into my UserBundle. I have changed the namespaces.
I have taken the graph manager from here: https://github.com/ikwattro/KwattroNeo4jOGMBundle
For the rest, I have followed the FOSUserBundle documentation.
Now, when I go to the registration form, all fields appear and I can fill in my preferred credentials. This works. After I click on submit I get redirected to the success page, on which an alert overlay is displayed:
An error occurred while loading the web debug toolbar (500: Internal
Server Error). Do you want to open the profiler?
If I then enter the profiler, I can see that I have successfully been authorized and logged in as the user that I just created. The data is also successfully saved in my neo4j database.
The problem now is that if I go to any other page of my Symfony project, I am logged in as Anonymous again. And If I go to the login page, the form is displayed correctly, but it always returns: Invalid credentials.
I am guessing, that there is something wrong with my sessions or my security?
This is my security.yml:
security:
encoders:
FOS\UserBundle\Model\UserInterface: bcrypt
Neo4jUserBundle\Entity\User: bcrypt
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: ROLE_ADMIN
providers:
fos_userbundle:
id: neo4j.user_provider.username
firewalls:
main:
pattern: ^/
form_login:
provider: fos_userbundle
csrf_provider: security.csrf.token_manager
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: ^/admin/, role: ROLE_ADMIN }
I dont know if this information can help or is relevant, but in the profiler under the Request right after registration (when the user is still authenticated correctly) this is the session information:
Session Metadata
Key Value
Created Tue, 21 Jul 15 17:27:34 +0200
Last used Tue, 21 Jul 15 17:27:34 +0200
Lifetime 0
Session Attributes
Key Value
_csrf/authenticate A_H4Ul1XHFYoxQdOirdmbBQRRCJ01Xh8EkGeC6Y7xw0
_csrf/registration OAXAXhfhcN6z0WekMN0fk8zg4ikk5uCCZBlvhy8DyVY
_security.last_username test
_security_main C:74:"Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken":444:{a:3:{i:0;N;i:1;s:4:"main";i:2;s:404:"a:4:{i:0;C:32:"neo4jProxyUserBundle_Entity_User":192:{a:9:{i:0;s:60:"$2y$13$e49oj61cdjk88kk040wg8exlwqVzbdQB5IVNG18Wqcbe.EW8KXi72";i:1;s:31:"e49oj61cdjk88kk040wg8kcc4cg40c4";i:2;s:4:"test";i:3;s:4:"test";i:4;b:0;i:5;b:0;i:6;b:0;i:7;b:1;i:8;i:66;}}i:1;b:1;i:2;a:1:{i:0;O:41:"Symfony\Component\Security\Core\Role\Role":1:{s:47:"Symfony\Component\Security\Core\Role\Rolerole";s:9:"ROLE_USER";}}i:3;a:0:{}}";}}
Flashes
Key Value
success [0 => registration.flash.user_created, 1 => registration.flash.user_created, 2 => registration.flash.user_created, 3 => registration.flash.user_created, 4 => registration.flash.user_created, 5 => registration.flash.user_created, 6 => registration.flash.user_created, 7 => registration.flash.user_created, 8 => registration.flash.user_created]
Any help or hints would be appreciated.
UPDATE [21.07.2015]
I have now created a repository: https://github.com/JoranBeaufort/Neo4jUserBundle (I hope this works, the first time I have used GitHub)
I guess that there is something off with the session handling?
Another thing to point out is, that the dependency injection does not seem to do anything. I must be missing a few vital things.
It would be great to be able to offer a Neo4jUserBundle that works out of the box with FOSUserBundle and can be configured in the config file of the Symfony project. Great and vital would also be the authentication with the database (use username and password to connect to neo4j).
UPDATE [22.07.2015]
I have changed the bundlename and I think I have finally gotten the DependencyInjection to work. I'm not quite sure but I think I had a problem with how I named my classes.
I have also tried what you suggested with findUserById. I have written a controller which takes the route myapp.com/neo4juser/debug/finduserbyid/{id} and then uses the findUserById method to return the user. This is working. I have a user in my Neo4j-Database with an ID = 68 and an email=test#test.test. If I now enter myapp.com/neo4juser/debug/finduserbyid/68 the page is loaded displaying the right email of that user.
TWIG can be found here: https://github.com/JoranBeaufort/Neo4jUserBundle/blob/master/Resources/views/Debug/finduserbyid.html.twig
And the CONTROLLER here: https://github.com/JoranBeaufort/Neo4jUserBundle/blob/master/Controller/DebugController.php
The methods in the UserManager seem to be returning the desired objects.
Does this help in figuring out why the login does not work in any way? Does the serialization have anything to do with the error or the encryption type? Or could it be something to do with the CSRF? Any further hints?
UPDATE [23.07.2015]
When using in_memory as the provider and setting up an in_memory user, the login works. So now I have narrowed down the problem to the provider.
I am getting closer! Now the error in the dev.log file reads:
[2015-07-23 17:11:54] security.INFO: Authentication request failed. {"exception":"[object] (Symfony\\Component\\Security\\Core\\Exception\\BadCredentialsException(code: 0): Bad credentials. at bla/vendor/symfony/symfony/src/Symfony/Component/Security/Core/Authentication/Provider/UserAuthenticationProvider.php:73, Symfony\\Component\\Security\\Core\\Exception\\UsernameNotFoundException(code: 0): Username \"test\" does not exist. at bla/src/Neo4jUserBundle/Security/UserProvider.php:42)"} []
Important is the part `Username "test" does not exist.I am guessing this means that something is not working in the user provider. Can anyone spot what the problem might be? The Provider which I am calling can be found here: https://github.com/JoranBeaufort/Neo4jUserBundle/tree/master/Security
Ok. I opened a PR for some tweaks, but I couldn't get the stuff working.
The tweaks I've done are adding the possibility to define a user and password for via the neo4j_user config, and load the services.yml file in the DI extension.
When I register a user, it is well created in the database. However for fetching a user, after some debug, I can see that the underlying client (neo4jphp combined with neo4j-php-ogm) are using the legacy indexes and it is throwing some errors at this stage.
I can not help further except to tell you to try to not use an ogm in the beginning and try with raw cypher queries.
I'm afraid trying to update both libraries used can be difficult in a first instance.
I would say the problem, as of 27/12/2015, is that UserManager, at line 73, does not return the found user (is a void function). I have not tried it yet and can´t for a few days, and maybe it´s an answer not sought anymore, but I´m pretty sure that´s the problem.
IDEs won´t find it a problems due to the #return tag:
* Finds a user by username
*
* #param string $username
*
* #return UserInterface
*/
public function findUserByUsername($username)
{
$this->findUserBy(array('usernameCanonical' => $this->canonicalizeUsername($username)));
}

Resources