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

@@ -11,12 +11,14 @@ namespace App\Security;
use App\Entity\User;
use App\Repository\UserRepository;
use Exception;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\User\UserInterface as SecurityUserInterface;
use Symfony\Component\Security\Core\User\PasswordUpgraderInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
final class DoctrineUserProvider implements UserProviderInterface
final class DoctrineUserProvider implements UserProviderInterface, PasswordUpgraderInterface
{
/**
* @var UserRepository
@@ -51,7 +53,7 @@ final class DoctrineUserProvider implements UserProviderInterface
/**
* {@inheritdoc}
*/
public function refreshUser(SecurityUserInterface $user)
public function refreshUser(UserInterface $user)
{
if (!$user instanceof User) {
throw new UnsupportedUserException(sprintf('Expected an instance of %s, but got "%s".', User::class, \get_class($user)));
@@ -74,4 +76,15 @@ final class DoctrineUserProvider implements UserProviderInterface
{
return $class === User::class;
}
public function upgradePassword(UserInterface $user, string $newEncodedPassword): void
{
if ($user instanceof User) {
try {
$user->setPassword($newEncodedPassword);
$this->repository->saveUser($user);
} catch (Exception $e) {
}
}
}
}

View File

@@ -0,0 +1,91 @@
<?php
/*
* This file is part of the Kimai time-tracking app.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace App\Security;
use App\Configuration\SystemConfiguration;
use App\Ldap\LdapUserProvider;
use Symfony\Component\Security\Core\User\ChainUserProvider;
use Symfony\Component\Security\Core\User\PasswordUpgraderInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
class KimaiUserProvider implements UserProviderInterface, PasswordUpgraderInterface
{
private $providers;
private $provider;
private $configuration;
/**
* @param iterable|UserProviderInterface[] $providers
*/
public function __construct(iterable $providers, SystemConfiguration $configuration)
{
$this->providers = $providers;
$this->configuration = $configuration;
}
private function getInternalProvider(): ChainUserProvider
{
if ($this->provider === null) {
$activated = [];
foreach ($this->providers as $provider) {
if ($provider instanceof LdapUserProvider) {
if (!$this->configuration->isLdapActive()) {
continue;
}
}
$activated[] = $provider;
}
$this->provider = new ChainUserProvider(new \ArrayIterator($activated));
}
return $this->provider;
}
/**
* @return array
*/
public function getProviders()
{
return $this->getInternalProvider()->getProviders();
}
/**
* {@inheritdoc}
*/
public function loadUserByUsername($username)
{
return $this->getInternalProvider()->loadUserByUsername($username);
}
/**
* {@inheritdoc}
*/
public function refreshUser(UserInterface $user)
{
return $this->getInternalProvider()->refreshUser($user);
}
/**
* {@inheritdoc}
*/
public function supportsClass($class)
{
return $this->getInternalProvider()->supportsClass($class);
}
/**
* {@inheritdoc}
*/
public function upgradePassword(UserInterface $user, string $newEncodedPassword): void
{
$this->getInternalProvider()->upgradePassword($user, $newEncodedPassword);
}
}

View File

@@ -19,21 +19,16 @@ use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Guard\AbstractGuardAuthenticator;
use Symfony\Component\Security\Guard\PasswordAuthenticatedInterface;
class TokenAuthenticator extends AbstractGuardAuthenticator
class TokenAuthenticator extends AbstractGuardAuthenticator implements PasswordAuthenticatedInterface
{
public const HEADER_USERNAME = 'X-AUTH-USER';
public const HEADER_TOKEN = 'X-AUTH-TOKEN';
public const HEADER_JAVASCRIPT = 'X-AUTH-SESSION';
/**
* @var EncoderFactoryInterface
*/
protected $encoderFactory;
private $encoderFactory;
/**
* @param EncoderFactoryInterface $encoderFactory
*/
public function __construct(EncoderFactoryInterface $encoderFactory)
{
$this->encoderFactory = $encoderFactory;
@@ -163,4 +158,13 @@ class TokenAuthenticator extends AbstractGuardAuthenticator
{
return false;
}
public function getPassword($credentials): ?string
{
if (!\is_array($credentials) || !\array_key_exists('token', $credentials) || empty($credentials['token'])) {
return null;
}
return $credentials['token'];
}
}