schmittjoh / jmssecurityextrabundle Goto Github PK
View Code? Open in Web Editor NEWEnhances the Symfony2 Security Component with several new features
Home Page: http://jmsyst.com/bundles/JMSSecurityExtraBundle
Enhances the Symfony2 Security Component with several new features
Home Page: http://jmsyst.com/bundles/JMSSecurityExtraBundle
According to the best practice, the services defined by the bundle should be named jms_security_extra.*
but you use security.*
in many places.
This could eventually create some clashes if a service with the same name is added later in SecurityBundle or if another bundle also uses a name that should be reserved for SecurityBundle. And it makes debugging harder as people seeing an issue about the service will report it against SecurityBundle instead of JMSSecurityExtraBundle (see symfony/symfony#2524 for instance)
Hi,
after updating my installation I got the following error when the autoload files are generated:
[JMS\DiExtraBundle\Exception\RuntimeException]
The @Inject annotation can only be used on non-public properties when the class is a non-service controller. For services, @Inject is only supported on public properties. The offending annotation is on JMS\SecurityExtraBundle\Tests\Functional\TestBundle\Controller\PostController::$request in /opt/local/apache2/htdocs/fmdb/vendor/jms/security-extra-bundle/JMS/SecurityExtraBundle/Tests/Functional/TestBundle/Controller/PostController.php.
After changing the visibility of the class properties the files could be generated.
I can send a PR if needed.
Not sure if the bundle has been coded to check for correct expression syntax, but I had this expression new Expression('object, "OPERATOR") or hasRole("ROLE_SUPPORT")')
which is clearly missing the hasExpression(
part and the bundle did not give an error which means bugs will be hard to find.
I have the need sometimes in the app to only allow users to do something if their profile validates some given rules (based on the validation groups of the framework).
So for example a user can only join an event if we know his first and last name as well as his phone number.
Do you see this as potentially part of this bundle or should I put these kind of things elsewhere? I have a proof of concept only so far, but it's very similar in approach to what you do in the security extra bundle.
Hi! Is there any special config settings for PreAuthorize annotation? I've got this error:
AnnotationException: [Semantical Error] The annotation "@Entity" in method Doctrine\ODM\MongoDB\Mapping\Driver\AnnotationDriver::isTransient() was never imported. Did you maybe forget to add a "use" statement for this annotation?
in my config:
jms_security_extra: secure_all_services: true
I have an error message on my web host.
Can you change set_time_limit(0); with @set_time_limit(0);
JMSSecurityExtraBundle / DependencyInjection / Compiler / SecureMethodInvocationsPass.php
line: 182
Hi,
I use the annotations with expressions, which, btw, are awesome (and thanks for that), but in that particular case i need to Pre-authorize access to a method with a class-scope ACL check.
I have a specific Acl Voter based on user's subscription (and constraints associated to it), and i need to do something like :
/**
* @PreAuthorize("hasPermission('My\Model\Album', 'CREATE')")
*/
public function newAction()
{}
That doesn't seem to be possible.
In my AclVoter i don't get the class name string in the $object param but a MethodInvocation proxy object.
But maybe i'm wrong, and i'm not using the correct expression ;-)
Thanks.
Bye.
I've created an issue on FOSOAuthServerBundle.
Since this Symfony PR on security providers and this commit, there' s a BC break on SecurityProviders configuration.
@stof suggested that many developers trying to maintain BC will eventually try something like that.
Should SecurityExtension implement addSecurityListenerFactory
and forward it to Sf SecurityExtension?
What do you think?
Is it possible to use the switch user functionality while having all three built-in voters disabled? I did so when switching to expressions and had to enable the role voter (jms_security_extra.voters.disable_role: true
) to make switching user work again.
I got apache 2 error:
mod_fcgid: stderr: PHP Fatal error: Uncaught exception 'InvalidArgumentException' with message 'Unable to load class "JMS\SecurityExtraBundle\Controller\ControllerListener"' in ......................./app/bootstrap.php.cache:996
It's seems that there is no directory JMS\SecurityExtraBundle\Controller
and MethodSecurityInterceptor is not injected.
Would it be more extensible, if generator will utilize Zend\CodeGenerator\Php\Class::fromReflection() ?..
The bundle has been added on Travis but without a .travis.yml
config file. So Travis uses its default behavior which is to run it with Rake
(Travis was initially build for Ruby projects). So all builds are failing: http://travis-ci.org/#!/schmittjoh/JMSSecurityExtraBundle/builds/369559
Maybe it will be useful to add some information when AccessDeniedInformation is thrown like roles or token ?
I think of a use case where a user can obtain a specific role by filling a form, and when this role is required for a page we can redirect him to the form by using the access denied handler. At the moment we cannot know if exception come from this role or another (like ROLE_ADMIN).
Imagine expression like this. doctrineParamConverter('FooBundle:Model', #id).getUser().getId() == user.getId()
and a DoctrineParamConverterFunction with load function which maps to doctrineParamConverter.
class DoctrineParamConverterFunction
{
/**
* @var \Symfony\Component\DependencyInjection\Container
*/
private $container;
public function __construct(Container $container)
{
$this->container = $container;
}
public function load($modelName, $id, $manager = '')
{
if ('' == $modelName) {
throw new \InvalidArgumentException('model name should not be blank.');
}
$manager = ('' == $manager) ? 'doctrine.orm.entity_manager' : 'doctrine.orm.' . $manager . '_entity_manager';
/** @var $manager EntityManager */
$manager = $this->container->get($manager);
//do we need to resolve the class?
if (false !== strpos($modelName, ':')) {
$modelName = $manager->getClassMetadata($modelName)->getName();
}
try {
$object = $manager->find($modelName, $id);
} catch (\Exception $e) {
return null;
}
return $object;
}
}
Now as you can see the function might return null when something goes wrong or the object with specified id doesn't exists.
Throwing the HttpNotFound exception is not a solution as this is the job of a controller..
IMHO just checking if the object where we are accessing the function or a property would proabably not be enough, we also need to decide on what whole expression should evaluate to.
hi,
after i followed your installation steps for symfony 2.0.x (http://jmsyst.com/bundles/JMSSecurityExtraBundle/master/installation i have 2.0.12) i am getting following error, right at the end of the command
php bin/vendors install
PHP Fatal error: Call to undefined method JMS\SecurityExtraBundle\DependencyInjection\JMSSecurityExtraExtension::getConfiguration() in C:\Program Files (x86)\Zen
d\Apache2\htdocs\mysite\vendor\bundles\JMS\SecurityExtraBundle\DependencyInjection\JMSSecurityExtraExtension.php on line 45
and a long row of other stack errors, but i thought this might be the source?
Is it possible to secure an entire class. I tried looking for a discussion in this topic but I couln't find anything. Is there any reason why this has not implemented? I can work on a PR but I would like to know first if there is anything I should know?
/**
@secure(roles="ROLE_USER")
*/
class MyClass
{
}
Mapping/Driver/AnnotationReader.php : 39
$this->setAnnotationNamespaceAlias('JMS\\SecurityExtraBundle\\Annotation\\', 'extra');
Could you change it to for example securityExtra
Thank you
It's like a convention - use 2.0
branch (parseable by packagist.org) for sf2.0.0 and master
for 2.1+. In this case, sf2.0.0 users will be able to install JMSSecurityExtraBundle
with just 2.0.0-dev
dep.
Whenever i use authenticate for an action in my controller with
- @Secure(roles="ROLE_USER")
my users who mark "remember me" when logging in, get a login request....so they have to authenticate again
how do i protect my action, so everyone (except of notlogged in=authenticate_anyonmously) can use it?
I could need a not
operator to be able to migrate (in Twig)
is_granted('ROLE_ALLOWED_TO_SWITCH') and not is_granted('ROLE_PREVIOUS_ADMIN')
to an expression.
Hi!
After installing symfony-standard I can see secured for admin area when logged in as a "user". Can you please check why this issue appears: https://github.com/symfony/symfony-standard/issues/285
It seems to me like it's related to JMSSecurityExtraBundle.
Thanks!
Would it be posible to use the JMSSecurityExtraBundle with YML instead of Annotations somehow?
I don't really like annotations but I do feel that putting the security on the methods is a lot better then putting it on URLs like the core symfony2 security does it.
So I was wondering if it would be an (fairly) easy swap which I could do myself?
I'm running a multi-website installation of Symfony2, using multiple kernels.
Each site has its own small tweaks to security access control, like locking down a few extra pages. Its always a combination of the site config and the main platform config.
This works fine except that this bundle defines ACL config as cannotBeOverwritten()
.
I commented this out and got the expected results, so I was looking for a decent way of replacing this class or config without hacking the bundle or other weird solutions.
Is there a way to make this configurable? Or a recommendation of getting around it?
Hi,
When i try to generate my page in the AdmingerenatorIpsum Project , the jms generate me a app/cache/dev/jms_security/expressions/b1ad6ad9b2d66ca3c153c54c69af64e3305fd527.php
file with
<?php
// Expression: hasPermission(Movie, "VIEW")
return function(array $context) {
if (!isset($context['token'])) {
throw new RuntimeException('The context contains no item with key "token".');
}
if (!$context['token'] instanceof Symfony\Component\Security\Core\Authentication\Token\TokenInterface) {
throw new RuntimeException(sprintf('The item "token" is expected to be of type "Symfony\Component\Security\Core\Authentication\Token\TokenInterface", but got "%s".', get_class($context['token'])));
}
return $context['container']->get('security.acl.permission_evaluator')->hasPermission($context['token'], $context['Movie'], 'VIEW');
};
And of course i have the error An exception has been thrown during the rendering of a template ("You have requested a non-existent service "security.acl.permission_evaluator".")
where is my mistake ??
I'm trying to git submodule add JMSSecurityExtraBundle, and it throws:
Cloning into vendor/bundles/JMS/SecurityExtraBundle...
fatal: https://github.com/schmittjoh/SecurityExtraBundle.git/info/refs not found: did you run git update-server-info on the server?
I'll keep watching this project and clone it when repaired, thank you for a great work !
MV.
Thanks to that we will be able to add 1.1 version to our deps file
Hi!
I've got this call in my controller since I am unable to use annotations at this stage due to the use of FOSRestBundle overriding my templating.
<?php
if (!$this->get('security.context')->isGranted(new Expression('hasRole("ROLE_SUPERUSER")'))) {
throw new AccessDeniedException('Token does not have the required roles.');
}
Note: this is meant to be a full expression:
hasPermission(company, "MASTER") or hasRole("ROLE_SUPERUSER")
However, I am simplifying if for this issue.
Now, debugging this, the security context converts the expression to an array:
<?php
return $this->accessDecisionManager->decide($this->token, (array) $attributes, $object);
And the ExpressionVoter
receives an array for $attributes
, and so does not vote:
<?php
public function vote(TokenInterface $token, $object, array $attributes)
{
$result = VoterInterface::ACCESS_ABSTAIN;
foreach ($attributes as $attribute) {
// this continue is invoked
if (!$attribute instanceof Expression) {
continue;
}
$result = VoterInterface::ACCESS_DENIED;
if (!isset($this->evaluators[$attribute->expression])) {
$this->evaluators[$attribute->expression] =
$this->createEvaluator($attribute);
}
if (call_user_func($this->evaluators[$attribute->expression],
$this->expressionHandler->createContext($token, $object))) {
return VoterInterface::ACCESS_GRANTED;
}
}
return $result;
}
The $attributes
variable looks like this:
array(1) (
[expression] => (string) hasRole("ROLE_SUPERUSER")
)
It would be nice to have the 1.0 version available, so we can link symfony-standard 2.0 to it.
The only thing I'm not sure about is whether metadata master-dev is compatible with the 1.0.0 which is currently used by symfony?
The custom controller resolver creating a proxy around the controller breaks bundles expecting to read some annotations on the controller (as they are not on the controller class anymore but should be searched on the parent class). Could you add an interface implemented by the proxy controller so that we can test if the controller we have is one of your proxy thanks to a simple instanceof
check ?
Either I'm doing something wrong or SecureRandom::nextBytes(16)
is not returning any proper values. Sometimes it's weird chinese numbers, sometimes it's something invisible.
I'm on a Mac running OSX Lion, PHP 5.3.8 with Suhosin-Patch.
if in deps:
git=http://github.com/schmittjoh/JMSSecurityExtraBundle.git
target=/bundles/JMS/SecurityExtraBundle
version=origin/1.0.x
then displays error:
[Symfony\Component\Config\Definition\Exception\InvalidConfigurationException]
Unrecognized options "expressions" under "jms_security_extra"
but if i set version to mater:
[JMSSecurityExtraBundle]
git=http://github.com/schmittjoh/JMSSecurityExtraBundle.git
target=/bundles/JMS/SecurityExtraBundle
version=origin/master
the displays error:
[Symfony\Component\Config\Definition\Exception\InvalidConfigurationException]
Unrecognized options "secure_controllers" under "jms_security_extra"
The bundle should be renamed to JMSSecurityExtraBundle
to avoid conflict if someone else want to create another SecurityExtraBundle
on Github.
After vendors update (today) i got message about required JMSAopBundle bundle. After adding this bundle and clearing cache i got error
ErrorException: Warning: call_user_func_array() expects parameter 1 to be a valid callback, class 'Metadata\MetadataFactory' does not have a method 'setIncludeInterfaces' in /var/www/benchmark/vendor/symfony/src/Symfony/Component/DependencyInjection/ContainerBuilder.php line 763
Can you please change required version of "jms/metadata" to ">=1.1.0,<1.3-dev"
I have all my forms and controllers defined as services. And now I'm trying to modify my forms according to the current user's security context. But this doesn't seem to work because security context is null at the time the form gets build.
I've narrowed it down it and this only happens when container is getting build and JMSSecurityExtraBundle is enabled.
The bundle version is not important the behavior is the same.
This is a bit modified symfony/symfony#3574
Hi,
The documentation says that the @PreAuthorize annotation can be used on a controller class, to secure all actions. But when I try to use it this way, I get this exception:
"[Semantical Error] Annotation @PreAuthorize is not allowed to be declared on class [...]\MyController. You may only use this annotation on these code elements: METHOD."
I use the 1.1.* version via composer.
Thanks,
Gregoire.
Hi,
When I try to use an expression with hasPermission
I get the exception:
You have requested a non-existent service "security.acl.permission_evaluator"
I don't have acl enabled because I use custom voters. Is that what it's all about?
Hello sir, is it possible to change them to protected for extensibility. I need a @SecureAnd annotation which supports "role_b, role_c & role_a". I wanted to fork it but don't think my code is good enough to be pulled (and will end up bogged down with upstream maintenance) so I chose to extend it instead.
Right now I have to copy the entire ControllerListener.php into my ControllerListener.php but won't be able to receive any new commits from you should there be any changes in ControllerListener.php
Not sure where to report better, decided here.
When using @secure annotation together with @ParamConverter http://symfony.com/doc/current/bundles/SensioFrameworkExtraBundle/annotations/converters.html - ParamConverter is working before secure check, and even if token has no access doctrine will execute query for requested object. This doesn't happens with standard symfony security. Some other events may also be dispatched before security checks
Notice: Undefined index: parameter_mapping_name in vendor/bundles/JMS/SecurityExtraBundle/Security/Authorization/Expression/Compiler/ParameterExpressionCompiler.php line 58
This is my method declaration:
<?php
/**
* {@inheritdoc}
*
* @PreAuthorize("hasPermission(#project.getCompany(), 'OPERATOR') or hasRole('ROLE_SUPERUSER')")
*/
public function updateProject(ProjectInterface $project)
{
}
Hi,
After upgrade from 1.0.x to 1.2.* (actually upgrade symfony from 2.0 to 2.1.2) the inheritance of annotation not works any more.
And all of my inherited methods become unsecured.
This is my case:
//BaseController.php
class BaseController extends Controller{
/**
* @Secure(roles="ROLE_MASTER")
*
*/
public function newAction()
{
//some actions
}
}
//ArticleController.php
class ArticleController extends BaseController{
//not even override of parent method
}
Before upgrade the ArticleController::newAction() method was secured. Now it is not and I have to duplicate a lot of code.
Is this fiture or bug? Maybe I do something wrong.
Sorry for my english.
The method signature of interest is:
<?php
public function hasPermission(TokenInterface $token, $object, $permission) { }
And we are interested in $object
. In most of my expressions, it works fine because the entity was loaded beforehand. E.g. in #project.getCompany()
, the company is loaded previously and so is of type Jbi\CoreBundle\Entity\Company
(i.e. not a proxy).
However, in my latest expression, I have #site.getProject()
and when hasPermission
is called, the $object
is of type Proxies\JbiCoreBundleEntityProjectProxy
and therefore when trying to find the ACL for the OID, it fails telling me that no ACL exists.
So - I could see how your response may be something like "hasPermission
has a precondition that $object
is of the correct type, not a proxy".
What do you think? Is there a way around or is there a way within this method that would check for a proxy?
A follow on from #22, but I've made a new issue since I noticed that you created a test for issue22.
The stack trace partial:
[RuntimeException]
There is no parameter with name "project" for method "Jbi\CoreBundle\Manager\ProjectsManager::createProject".
Exception trace:
() at /app/cache/dev/jms_security/expressions/8dfa724b356323205a4fc1f3616817cf5e7baa64.php:21
Here is a copy of the generated expression code:
<?php
// Expression: hasPermission(#project.getCompany(), 'OPERATOR') or hasRole('ROLE_SUPERUSER')
return function(array $context) {
if (!isset($context['token'])) {
throw new RuntimeException('The context contains no item with key "token".');
}
if (!$context['token'] instanceof Symfony\Component\Security\Core\Authentication\Token\TokenInterface) {
throw new RuntimeException(sprintf('The item "token" is expected to be of type "Symfony\Component\Security\Core\Authentication\Token\TokenInterface", but got "%s".', get_class($context['token'])));
}
if (!isset($context['object'])) {
throw new RuntimeException('The context contains no item with key "object".');
}
if (!$context['object'] instanceof CG\Proxy\MethodInvocation) {
throw new RuntimeException(sprintf('The item "object" is expected to be of type "CG\Proxy\MethodInvocation", but got "%s".', get_class($context['object'])));
}
if (!isset($a['project'])) {
throw new RuntimeException(sprintf('There is no parameter with name "project" for method "%s".', $context['object']));
}
if (!$context['token'] instanceof Symfony\Component\Security\Core\Authentication\Token\TokenInterface) {
throw new RuntimeException(sprintf('The item "token" is expected to be of type "Symfony\Component\Security\Core\Authentication\Token\TokenInterface", but got "%s".', get_class($context['token'])));
}
$a = $context['token']->getRoles();
if (isset($context['role_hierarchy'])) {
$a = $context['role_hierarchy']->getReachableRoles($a);
}
$b = array();
foreach ($a as $role) {
$b[$role->getRole()] = true;
}
$a = $b;
return ($context['container']->get('security.acl.permission_evaluator')->hasPermission($context['token'], $context['object']->arguments[$a['project']]->getCompany(), 'OPERATOR')) || (isset($a['ROLE_SUPERUSER']));
};
As you can see, there is no variable $a
at the right place, and even the $a
that is declared contains roles, not the parameter.
I can't seem to find JMS\SecurityExtraBundle\Security\EventListener\SecureRandomSchemaListener
. Should I open a PR or have you forgotten to commit it?
I am using JMS Security bundle to secure methods and controllers. When non previleged user access the secure page then i get this error
Token does not have the required roles.
Is there any way , i can make that custom page and more defined error message
If I take away the @secure annotation the form will POST and execute just fine. As you can see there is a default value:
/**
------------------------------ERROR-------------------------------------------
Controller "Closure" requires that you provide a value for the "$col_width" argument (because there is no default value or because there is a non optional argument after this one).
After following the installation instructions, I'm trying to set the expressions option in app/config/config.yml, and when I clear the cache I get this error:
[Symfony\Component\Config\Definition\Exception\InvalidConfigurationException]
Unrecognized options "expressions" under "jms_security_extra"
Other options are not working either, such as method_access_control (the one that I need).
it would be good to see what tagged version works with which version of other of your bundles
i was in 1.0 on this one and wanted to see if i could go up to 1.1.x without having to change things
With
security:
role_hierarchy:
ROLE_SUPER_ADMIN: ROLE_ADMIN
defined, the expression hasRole("ROLE_ADMIN")
fails although the user has role ROLE_SUPER_ADMIN
.
In the generated expression code
<?php
// Expression: hasRole("ROLE_ADMIN")
return function(array $context) {
if (!isset($context['token'])) {
throw new RuntimeException('The context contains no item with key "token".');
}
if (!$context['token'] instanceof Symfony\Component\Security\Core\Authentication\Token\TokenInterface) {
throw new RuntimeException(sprintf('The item "token" is expected to be of type "Symfony\Component\Security\Core\Authentication\Token\TokenInterface", but got "%s".', get_class($context['token'])));
}
$a = $context['token']->getRoles();
if (isset($context['role_hierarchy'])) {
$a = $context['role_hierarchy']->getReachableRoles($a);
}
$b = array();
foreach ($a as $role) {
$b[$role->getRole()] = true;
}
$a = $b;
return isset($a['ROLE_ADMIN']);
};
isset($context['role_hierarchy'])
evaluates to false which makes the defined role hierarchy being ignored.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.