-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[2.8] [Ldap] Added support for LDAP (New Component + integration in the Security Component). #14602
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
<?php | ||
|
||
/* | ||
* This file is part of the Symfony package. | ||
* | ||
* (c) Fabien Potencier <[email protected]> | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
namespace Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory; | ||
|
||
use Symfony\Component\Config\Definition\Builder\NodeDefinition; | ||
use Symfony\Component\DependencyInjection\DefinitionDecorator; | ||
use Symfony\Component\DependencyInjection\ContainerBuilder; | ||
use Symfony\Component\DependencyInjection\Reference; | ||
|
||
/** | ||
* FormLoginLdapFactory creates services for form login ldap authentication. | ||
* | ||
* @author Grégoire Pineau <[email protected]> | ||
* @author Charles Sarrazin <[email protected]> | ||
*/ | ||
class FormLoginLdapFactory extends FormLoginFactory | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You're making it impossible like this to attach a custom authenticator. Can you extend the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These factories are only to be used with LDAP, and actually override the authentication provider to be the LDAP bind authentication provider. As it already handles authentication, I don't really see why you would want to attach a custom authenticator. Can you provide a use case? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For example if a user account is disabled, a certain token is not supplied etc. LDAP should be nothing more than a specific user provider in my opinion. Instead of fetching it from the database, you fetch it from ldap. For me it's currently impossible to do the following:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This issue should start to be addressed in #14673 (with the new guard authentication system), and maybe #14713. This feature will be adapted for the new guard system, and improved once these PRs. Depending on when (and whether) these two PRs will be merged, a new PR should be made to update the legacy authentication providers. Until then, I will fix the tests, unless there actually is another issue. Ping @iltar @weaverryan There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If the guard PR gets merged and we can build this on top of that, that's awesome! Realistically, since security is so complex, I imagine that we (the community) will make a push on all these security-related PR's at the same time and decide how it will all end up. For now, I agree with making this PR as solid as possible without #14673 and #14713... though I hope that'll change ;). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok. I keep the PR as is. I'll fix the tests, and that should do it. Of course, I'm open for any suggestion. Ping @iltar @stof @weaverryan There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think core features in the Security component should still be built with core features. Guard is more for end-users. |
||
{ | ||
protected function createAuthProvider(ContainerBuilder $container, $id, $config, $userProviderId) | ||
{ | ||
$provider = 'security.authentication.provider.ldap_bind.'.$id; | ||
$container | ||
->setDefinition($provider, new DefinitionDecorator('security.authentication.provider.ldap_bind')) | ||
->replaceArgument(0, new Reference($userProviderId)) | ||
->replaceArgument(2, $id) | ||
->replaceArgument(3, new Reference($config['service'])) | ||
->replaceArgument(4, $config['dn_string']) | ||
; | ||
|
||
return $provider; | ||
} | ||
|
||
public function addConfiguration(NodeDefinition $node) | ||
{ | ||
parent::addConfiguration($node); | ||
|
||
$node | ||
->children() | ||
->scalarNode('service')->end() | ||
->scalarNode('dn_string')->defaultValue('{username}')->end() | ||
->end() | ||
; | ||
} | ||
|
||
public function getKey() | ||
{ | ||
return 'form-login-ldap'; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
<?php | ||
|
||
/* | ||
* This file is part of the Symfony package. | ||
* | ||
* (c) Fabien Potencier <[email protected]> | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
namespace Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory; | ||
|
||
use Symfony\Component\Config\Definition\Builder\NodeDefinition; | ||
use Symfony\Component\DependencyInjection\DefinitionDecorator; | ||
use Symfony\Component\DependencyInjection\ContainerBuilder; | ||
use Symfony\Component\DependencyInjection\Reference; | ||
|
||
/** | ||
* HttpBasicFactory creates services for HTTP basic authentication. | ||
* | ||
* @author Fabien Potencier <[email protected]> | ||
* @author Grégoire Pineau <[email protected]> | ||
* @author Charles Sarrazin <[email protected]> | ||
*/ | ||
class HttpBasicLdapFactory extends HttpBasicFactory | ||
{ | ||
public function create(ContainerBuilder $container, $id, $config, $userProvider, $defaultEntryPoint) | ||
{ | ||
$provider = 'security.authentication.provider.ldap_bind.'.$id; | ||
$container | ||
->setDefinition($provider, new DefinitionDecorator('security.authentication.provider.ldap_bind')) | ||
->replaceArgument(0, new Reference($userProvider)) | ||
->replaceArgument(2, $id) | ||
->replaceArgument(3, new Reference($config['service'])) | ||
->replaceArgument(4, $config['dn_string']) | ||
; | ||
|
||
// entry point | ||
$entryPointId = $this->createEntryPoint($container, $id, $config, $defaultEntryPoint); | ||
|
||
// listener | ||
$listenerId = 'security.authentication.listener.basic.'.$id; | ||
$listener = $container->setDefinition($listenerId, new DefinitionDecorator('security.authentication.listener.basic')); | ||
$listener->replaceArgument(2, $id); | ||
$listener->replaceArgument(3, new Reference($entryPointId)); | ||
|
||
return array($provider, $listenerId, $entryPointId); | ||
} | ||
|
||
public function addConfiguration(NodeDefinition $node) | ||
{ | ||
parent::addConfiguration($node); | ||
|
||
$node | ||
->children() | ||
->scalarNode('service')->end() | ||
->scalarNode('dn_string')->defaultValue('{username}')->end() | ||
->end() | ||
; | ||
} | ||
|
||
public function getKey() | ||
{ | ||
return 'http-basic-ldap'; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
<?php | ||
|
||
/* | ||
* This file is part of the Symfony package. | ||
* | ||
* (c) Fabien Potencier <[email protected]> | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
namespace Symfony\Bundle\SecurityBundle\DependencyInjection\Security\UserProvider; | ||
|
||
use Symfony\Component\Config\Definition\Builder\NodeDefinition; | ||
use Symfony\Component\DependencyInjection\DefinitionDecorator; | ||
use Symfony\Component\DependencyInjection\ContainerBuilder; | ||
use Symfony\Component\DependencyInjection\Reference; | ||
|
||
/** | ||
* LdapFactory creates services for Ldap user provider. | ||
* | ||
* @author Grégoire Pineau <[email protected]> | ||
* @author Charles Sarrazin <[email protected]> | ||
*/ | ||
class LdapFactory implements UserProviderFactoryInterface | ||
{ | ||
public function create(ContainerBuilder $container, $id, $config) | ||
{ | ||
$container | ||
->setDefinition($id, new DefinitionDecorator('security.user.provider.ldap')) | ||
->replaceArgument(0, new Reference($config['service'])) | ||
->replaceArgument(1, $config['base_dn']) | ||
->replaceArgument(2, $config['search_dn']) | ||
->replaceArgument(3, $config['search_password']) | ||
->replaceArgument(4, $config['default_roles']) | ||
->replaceArgument(5, $config['uid_key']) | ||
->replaceArgument(6, $config['filter']) | ||
; | ||
} | ||
|
||
public function getKey() | ||
{ | ||
return 'ldap'; | ||
} | ||
|
||
public function addConfiguration(NodeDefinition $node) | ||
{ | ||
$node | ||
->children() | ||
->scalarNode('service')->isRequired()->cannotBeEmpty()->end() | ||
->scalarNode('base_dn')->isRequired()->cannotBeEmpty()->end() | ||
->scalarNode('search_dn')->end() | ||
->scalarNode('search_password')->end() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually, you can be authenticated anonymously using See http://php.net/manual/en/function.ldap-bind.php:
Regarding the |
||
->arrayNode('default_roles') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is required, as you are accessing this key in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Indeed! |
||
->beforeNormalization()->ifString()->then(function($v) { return preg_split('/\s*,\s*/', $v); })->end() | ||
->requiresAtLeastOneElement() | ||
->prototype('scalar')->end() | ||
->end() | ||
->scalarNode('uid_key')->defaultValue('sAMAccountName')->end() | ||
->scalarNode('filter')->defaultValue('({uid_key}={username})')->end() | ||
->end() | ||
; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
vendor/ | ||
composer.lock | ||
phpunit.xml |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
<?php | ||
|
||
/* | ||
* This file is part of the Symfony package. | ||
* | ||
* (c) Fabien Potencier <[email protected]> | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
namespace Symfony\Component\Ldap\Exception; | ||
|
||
/** | ||
* ConnectionException is throw if binding to ldap can not be established. | ||
* | ||
* @author Grégoire Pineau <[email protected]> | ||
*/ | ||
class ConnectionException extends \RuntimeException | ||
{ | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
<?php | ||
|
||
/* | ||
* This file is part of the Symfony package. | ||
* | ||
* (c) Fabien Potencier <[email protected]> | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
namespace Symfony\Component\Ldap\Exception; | ||
|
||
/** | ||
* LdapException is throw if php ldap module is not loaded. | ||
* | ||
* @author Grégoire Pineau <[email protected]> | ||
*/ | ||
class LdapException extends \RuntimeException | ||
{ | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
Copyright (c) 2004-2015 Fabien Potencier | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is furnished | ||
to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
THE SOFTWARE. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The LDAP extension is available without any installation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. It seems that the LDAP extension is available by default in Travis' PHP build.
See travis-ci/travis-ci#1096
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
indeed, 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, and this is certain, as I added the skip tests only after checking that they passed on travis first, and because of appveyor launching tests with and without PHP extensions.