Skip to content

Commit 04b82a8

Browse files
committed
added LdapQueryAuthenticationProvider
1 parent 140e847 commit 04b82a8

File tree

3 files changed

+119
-3
lines changed

3 files changed

+119
-3
lines changed

src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/FormLoginLdapFactory.php

+11-3
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,23 @@ class FormLoginLdapFactory extends FormLoginFactory
2626
{
2727
protected function createAuthProvider(ContainerBuilder $container, $id, $config, $userProviderId)
2828
{
29-
$provider = 'security.authentication.provider.ldap_bind.'.$id;
30-
$container
31-
->setDefinition($provider, new ChildDefinition('security.authentication.provider.ldap_bind'))
29+
$method = empty($config['query_string']) ? 'bind' : 'query';
30+
31+
$provider = 'security.authentication.provider.ldap_'.$method.'.'.$id;
32+
33+
$parent = 'security.authentication.provider.ldap_'.$method;
34+
$definition = $container->setDefinition($provider, new ChildDefinition($parent))
3235
->replaceArgument(0, new Reference($userProviderId))
3336
->replaceArgument(1, new Reference('security.user_checker.'.$id))
3437
->replaceArgument(2, $id)
3538
->replaceArgument(3, new Reference($config['service']))
3639
->replaceArgument(4, $config['dn_string'])
3740
;
3841

42+
if ('query' === $method) {
43+
$definition->replaceArgument(5, $config['query_string']);
44+
}
45+
3946
return $provider;
4047
}
4148

@@ -47,6 +54,7 @@ public function addConfiguration(NodeDefinition $node)
4754
->children()
4855
->scalarNode('service')->defaultValue('ldap')->end()
4956
->scalarNode('dn_string')->defaultValue('{username}')->end()
57+
->scalarNode('query_string')->end()
5058
->end()
5159
;
5260
}

src/Symfony/Bundle/SecurityBundle/Resources/config/security_listeners.xml

+10
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,16 @@
201201
<argument>%security.authentication.hide_user_not_found%</argument>
202202
</service>
203203

204+
<service id="security.authentication.provider.ldap_query" class="Symfony\Component\Security\Core\Authentication\Provider\LdapQueryAuthenticationProvider" public="false" abstract="true">
205+
<argument /> <!-- User Provider -->
206+
<argument /> <!-- UserChecker -->
207+
<argument /> <!-- Provider-shared Key -->
208+
<argument /> <!-- LDAP -->
209+
<argument /> <!-- Base DN -->
210+
<argument /> <!-- Query DN -->
211+
<argument>%security.authentication.hide_user_not_found%</argument>
212+
</service>
213+
204214
<service id="security.authentication.provider.simple" class="Symfony\Component\Security\Core\Authentication\Provider\SimpleAuthenticationProvider" abstract="true" public="false">
205215
<argument /> <!-- Simple Authenticator -->
206216
<argument /> <!-- User Provider -->
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Security\Core\Authentication\Provider;
13+
14+
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
15+
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
16+
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
17+
use Symfony\Component\Security\Core\User\UserCheckerInterface;
18+
use Symfony\Component\Security\Core\User\UserInterface;
19+
use Symfony\Component\Security\Core\User\UserProviderInterface;
20+
use Symfony\Component\Ldap\LdapInterface;
21+
use Symfony\Component\Ldap\Exception\ConnectionException;
22+
23+
/**
24+
* LdapQueryAuthenticationProvider authenticates a user against an LDAP server.
25+
*
26+
* The only way to check user credentials is to first find the DN via query and then bind
27+
*
28+
* @author Charles Sarrazin <charles@sarraz.in>
29+
* @author Lukas Kahwe Smith <smith@pooteeweet.org>
30+
*/
31+
class LdapQueryAuthenticationProvider extends UserAuthenticationProvider
32+
{
33+
private $userProvider;
34+
private $ldap;
35+
private $dnString;
36+
private $queryString;
37+
38+
/**
39+
* Constructor.
40+
*
41+
* @param UserProviderInterface $userProvider A UserProvider
42+
* @param UserCheckerInterface $userChecker A UserChecker
43+
* @param string $providerKey The provider key
44+
* @param LdapInterface $ldap A Ldap client
45+
* @param string $dnString A string with the query DN
46+
* @param string $queryString A string used to create the query query
47+
* @param bool $hideUserNotFoundExceptions Whether to hide user not found exception or not
48+
*/
49+
public function __construct(UserProviderInterface $userProvider, UserCheckerInterface $userChecker, $providerKey, LdapInterface $ldap, $dnString, $queryString = '{username}', $hideUserNotFoundExceptions = true)
50+
{
51+
parent::__construct($userChecker, $providerKey, $hideUserNotFoundExceptions);
52+
53+
$this->userProvider = $userProvider;
54+
$this->ldap = $ldap;
55+
$this->dnString = $dnString;
56+
$this->queryString = $queryString;
57+
}
58+
59+
/**
60+
* {@inheritdoc}
61+
*/
62+
protected function retrieveUser($username, UsernamePasswordToken $token)
63+
{
64+
if (AuthenticationProviderInterface::USERNAME_NONE_PROVIDED === $username) {
65+
throw new UsernameNotFoundException('Username can not be null');
66+
}
67+
68+
return $this->userProvider->loadUserByUsername($username);
69+
}
70+
71+
/**
72+
* {@inheritdoc}
73+
*/
74+
protected function checkAuthentication(UserInterface $user, UsernamePasswordToken $token)
75+
{
76+
$username = $token->getUsername();
77+
$password = $token->getCredentials();
78+
79+
if ('' === $password) {
80+
throw new BadCredentialsException('The presented password must not be empty.');
81+
}
82+
83+
try {
84+
$username = $this->ldap->escape($username, '', LdapInterface::ESCAPE_DN);
85+
$query = str_replace('{username}', $username, $this->queryString);
86+
87+
$query = $this->ldap->query($this->dnString, $query);
88+
$result = $query->execute();
89+
if (1 !== $result->count()) {
90+
throw new BadCredentialsException('The presented password is invalid.');
91+
}
92+
93+
$this->ldap->bind($result->getIterator()->current()->getDn(), $password);
94+
} catch (ConnectionException $e) {
95+
throw new BadCredentialsException('The presented password is invalid.');
96+
}
97+
}
98+
}

0 commit comments

Comments
 (0)