Refactor authentication system (#2602)

Make auth configuration available via UI, remove FOSUserBundle and SAML-Bundle dependency
This commit is contained in:
Kevin Papst
2021-06-10 15:34:13 +02:00
committed by GitHub
parent 286b63e2c8
commit 7f20cb045c
155 changed files with 5590 additions and 1802 deletions

View File

@@ -20,12 +20,12 @@ use Symfony\Component\DependencyInjection\Reference;
*/
class FormLoginLdapFactory implements SecurityFactoryInterface
{
public function create(ContainerBuilder $container, $id, $config, $userProviderId, $defaultEntryPoint)
public function create(ContainerBuilder $container, $id, $config, $userProviderId, $defaultEntryPointId)
{
$authProviderId = $this->createAuthProvider($container, $id, $userProviderId);
$listenerId = $this->createListener($container, $id, $config);
return [$authProviderId, $listenerId, $defaultEntryPoint];
return [$authProviderId, $listenerId, $defaultEntryPointId];
}
public function getPosition()
@@ -38,7 +38,7 @@ class FormLoginLdapFactory implements SecurityFactoryInterface
return 'kimai_ldap';
}
public function addConfiguration(NodeDefinition $node)
public function addConfiguration(NodeDefinition $builder)
{
}

View File

@@ -12,6 +12,7 @@ namespace App\Ldap;
use App\Configuration\LdapConfiguration;
use App\Entity\User;
use Symfony\Component\Security\Core\Authentication\Provider\UserAuthenticationProvider;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\Exception\AuthenticationServiceException;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
@@ -48,6 +49,15 @@ class LdapAuthenticationProvider extends UserAuthenticationProvider
$this->userProvider = $userProvider;
}
public function supports(TokenInterface $token)
{
if (!$this->config->isActivated()) {
return false;
}
return parent::supports($token);
}
protected function retrieveUser($username, UsernamePasswordToken $token)
{
$user = $token->getUser();
@@ -56,7 +66,7 @@ class LdapAuthenticationProvider extends UserAuthenticationProvider
}
try {
// this will always query the FOSUserBundle first...
// this will always query the internal database first...
// only first-time logins from LDAP user (not yet existing in local user database)
// will actually hit the LdapUserProvider
$user = $this->userProvider->loadUserByUsername($username);

View File

@@ -15,29 +15,17 @@ use Symfony\Component\Security\Core\User\UserInterface;
/**
* Inspired by https://github.com/Maks3w/FR3DLdapBundle @ MIT License
*
* @final
*/
class LdapManager
{
/**
* @var LdapConfiguration
*/
protected $config;
/**
* @var LdapDriver
*/
protected $driver;
/**
* @var array
*/
protected $params = [];
/**
* @var LdapUserHydrator
*/
protected $hydrator;
private $driver;
private $hydrator;
private $config;
public function __construct(LdapDriver $driver, LdapUserHydrator $hydrator, LdapConfiguration $config)
{
$this->params = $config->getUserParameters();
$this->config = $config;
$this->driver = $driver;
$this->hydrator = $hydrator;
@@ -52,7 +40,9 @@ class LdapManager
*/
public function findUserByUsername(string $username): ?UserInterface
{
return $this->findUserBy([$this->params['usernameAttribute'] => $username]);
$params = $this->config->getUserParameters();
return $this->findUserBy([$params['usernameAttribute'] => $username]);
}
/**
@@ -62,8 +52,9 @@ class LdapManager
*/
public function findUserBy(array $criteria): ?UserInterface
{
$params = $this->config->getUserParameters();
$filter = $this->buildFilter($criteria);
$entries = $this->driver->search($this->params['baseDn'], $filter);
$entries = $this->driver->search($params['baseDn'], $filter);
if ($entries['count'] > 1) {
throw new LdapDriverException('This search must only return a single user');
@@ -77,10 +68,12 @@ class LdapManager
return $this->hydrator->hydrate($entries[0]);
}
protected function buildFilter(array $criteria, string $condition = '&'): string
private function buildFilter(array $criteria, string $condition = '&'): string
{
$params = $this->config->getUserParameters();
$filters = [];
$filters[] = $this->params['filter'];
$filters[] = $params['filter'];
foreach ($criteria as $key => $value) {
$value = ldap_escape($value, '', LDAP_ESCAPE_FILTER);
$filters[] = sprintf('(%s=%s)', $key, $value);
@@ -118,7 +111,8 @@ class LdapManager
}
$user->setPreferenceValue('ldap.dn', $baseDn);
$entries = $this->driver->search($baseDn, $this->params['attributesFilter']);
$params = $this->config->getUserParameters();
$entries = $this->driver->search($baseDn, $params['attributesFilter']);
if ($entries['count'] > 1) {
throw new LdapDriverException('This search must only return a single user');
@@ -151,7 +145,7 @@ class LdapManager
}
}
protected function getRoles(string $dn, array $roleParameter): array
private function getRoles(string $dn, array $roleParameter): array
{
$filter = $roleParameter['filter'] ?? '';

View File

@@ -20,21 +20,13 @@ use Symfony\Component\Security\Core\User\UserProviderInterface;
* Overwritten to be able to deactivate LDAP via config switch.
*
* Inspired by https://github.com/Maks3w/FR3DLdapBundle @ MIT License
*
* @final
*/
class LdapUserProvider implements UserProviderInterface
{
/**
* @var bool
*/
protected $activated = false;
/**
* @var LdapManager
*/
protected $ldapManager;
/**
* @var LoggerInterface|null
*/
protected $logger;
private $ldapManager;
private $logger;
public function __construct(LdapManager $ldapManager, LoggerInterface $logger = null)
{