login consent app sql

This commit is contained in:
2022-05-03 08:54:45 +02:00
parent e7253acfd8
commit f9a6535906
1652 changed files with 187600 additions and 45 deletions

View File

@ -0,0 +1,102 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Core\Encoder;
use Symfony\Component\PasswordHasher\Hasher\CheckPasswordLengthTrait;
trigger_deprecation('symfony/security-core', '5.3', 'The "%s" class is deprecated, use "%s" instead.', BasePasswordEncoder::class, CheckPasswordLengthTrait::class);
/**
* BasePasswordEncoder is the base class for all password encoders.
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @deprecated since Symfony 5.3, use CheckPasswordLengthTrait instead
*/
abstract class BasePasswordEncoder implements PasswordEncoderInterface
{
public const MAX_PASSWORD_LENGTH = 4096;
/**
* {@inheritdoc}
*/
public function needsRehash(string $encoded): bool
{
return false;
}
/**
* Demerges a merge password and salt string.
*
* @return array An array where the first element is the password and the second the salt
*/
protected function demergePasswordAndSalt(string $mergedPasswordSalt)
{
if (empty($mergedPasswordSalt)) {
return ['', ''];
}
$password = $mergedPasswordSalt;
$salt = '';
$saltBegins = strrpos($mergedPasswordSalt, '{');
if (false !== $saltBegins && $saltBegins + 1 < \strlen($mergedPasswordSalt)) {
$salt = substr($mergedPasswordSalt, $saltBegins + 1, -1);
$password = substr($mergedPasswordSalt, 0, $saltBegins);
}
return [$password, $salt];
}
/**
* Merges a password and a salt.
*
* @return string
*
* @throws \InvalidArgumentException
*/
protected function mergePasswordAndSalt(string $password, ?string $salt)
{
if (empty($salt)) {
return $password;
}
if (false !== strrpos($salt, '{') || false !== strrpos($salt, '}')) {
throw new \InvalidArgumentException('Cannot use { or } in salt.');
}
return $password.'{'.$salt.'}';
}
/**
* Compares two passwords.
*
* This method implements a constant-time algorithm to compare passwords to
* avoid (remote) timing attacks.
*
* @return bool
*/
protected function comparePasswords(string $password1, string $password2)
{
return hash_equals($password1, $password2);
}
/**
* Checks if the password is too long.
*
* @return bool
*/
protected function isPasswordTooLong(string $password)
{
return \strlen($password) > static::MAX_PASSWORD_LENGTH;
}
}

View File

@ -0,0 +1,32 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Core\Encoder;
use Symfony\Component\PasswordHasher\Hasher\PasswordHasherAwareInterface;
/**
* @author Christophe Coevoet <stof@notk.org>
*
* @deprecated since Symfony 5.3, use {@link PasswordHasherAwareInterface} instead.
*/
interface EncoderAwareInterface
{
/**
* Gets the name of the encoder used to encode the password.
*
* If the method returns null, the standard way to retrieve the encoder
* will be used instead.
*
* @return string|null
*/
public function getEncoderName();
}

View File

@ -0,0 +1,227 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Core\Encoder;
use Symfony\Component\PasswordHasher\Hasher\PasswordHasherAwareInterface;
use Symfony\Component\PasswordHasher\Hasher\PasswordHasherFactory;
use Symfony\Component\PasswordHasher\LegacyPasswordHasherInterface;
use Symfony\Component\PasswordHasher\PasswordHasherInterface;
use Symfony\Component\Security\Core\Exception\LogicException;
trigger_deprecation('symfony/security-core', '5.3', 'The "%s" class is deprecated, use "%s" instead.', EncoderFactory::class, PasswordHasherFactory::class);
/**
* A generic encoder factory implementation.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*
* @deprecated since Symfony 5.3, use {@link PasswordHasherFactory} instead
*/
class EncoderFactory implements EncoderFactoryInterface
{
private $encoders;
public function __construct(array $encoders)
{
$this->encoders = $encoders;
}
/**
* {@inheritdoc}
*/
public function getEncoder($user)
{
$encoderKey = null;
if (($user instanceof PasswordHasherAwareInterface && null !== $encoderName = $user->getPasswordHasherName()) || ($user instanceof EncoderAwareInterface && null !== $encoderName = $user->getEncoderName())) {
if (!\array_key_exists($encoderName, $this->encoders)) {
throw new \RuntimeException(sprintf('The encoder "%s" was not configured.', $encoderName));
}
$encoderKey = $encoderName;
} else {
foreach ($this->encoders as $class => $encoder) {
if ((\is_object($user) && $user instanceof $class) || (!\is_object($user) && (is_subclass_of($user, $class) || $user == $class))) {
$encoderKey = $class;
break;
}
}
}
if (null === $encoderKey) {
throw new \RuntimeException(sprintf('No encoder has been configured for account "%s".', \is_object($user) ? get_debug_type($user) : $user));
}
if (!$this->encoders[$encoderKey] instanceof PasswordEncoderInterface) {
if ($this->encoders[$encoderKey] instanceof LegacyPasswordHasherInterface) {
$this->encoders[$encoderKey] = new LegacyPasswordHasherEncoder($this->encoders[$encoderKey]);
} elseif ($this->encoders[$encoderKey] instanceof PasswordHasherInterface) {
$this->encoders[$encoderKey] = new PasswordHasherEncoder($this->encoders[$encoderKey]);
} else {
$this->encoders[$encoderKey] = $this->createEncoder($this->encoders[$encoderKey]);
}
}
return $this->encoders[$encoderKey];
}
/**
* Creates the actual encoder instance.
*
* @throws \InvalidArgumentException
*/
private function createEncoder(array $config, bool $isExtra = false): PasswordEncoderInterface
{
if (isset($config['algorithm'])) {
$rawConfig = $config;
$config = $this->getEncoderConfigFromAlgorithm($config);
}
if (!isset($config['class'])) {
throw new \InvalidArgumentException('"class" must be set in '.json_encode($config));
}
if (!isset($config['arguments'])) {
throw new \InvalidArgumentException('"arguments" must be set in '.json_encode($config));
}
$encoder = new $config['class'](...$config['arguments']);
if ($isExtra || !\in_array($config['class'], [NativePasswordEncoder::class, SodiumPasswordEncoder::class], true)) {
return $encoder;
}
if ($rawConfig ?? null) {
$extraEncoders = array_map(function (string $algo) use ($rawConfig): PasswordEncoderInterface {
$rawConfig['algorithm'] = $algo;
return $this->createEncoder($rawConfig);
}, ['pbkdf2', $rawConfig['hash_algorithm'] ?? 'sha512']);
} else {
$extraEncoders = [new Pbkdf2PasswordEncoder(), new MessageDigestPasswordEncoder()];
}
return new MigratingPasswordEncoder($encoder, ...$extraEncoders);
}
private function getEncoderConfigFromAlgorithm(array $config): array
{
if ('auto' === $config['algorithm']) {
$encoderChain = [];
// "plaintext" is not listed as any leaked hashes could then be used to authenticate directly
foreach ([SodiumPasswordEncoder::isSupported() ? 'sodium' : 'native', 'pbkdf2', $config['hash_algorithm']] as $algo) {
$config['algorithm'] = $algo;
$encoderChain[] = $this->createEncoder($config, true);
}
return [
'class' => MigratingPasswordEncoder::class,
'arguments' => $encoderChain,
];
}
if ($fromEncoders = ($config['migrate_from'] ?? false)) {
unset($config['migrate_from']);
$encoderChain = [$this->createEncoder($config, true)];
foreach ($fromEncoders as $name) {
if ($encoder = $this->encoders[$name] ?? false) {
$encoder = $encoder instanceof PasswordEncoderInterface ? $encoder : $this->createEncoder($encoder, true);
} else {
$encoder = $this->createEncoder(['algorithm' => $name], true);
}
$encoderChain[] = $encoder;
}
return [
'class' => MigratingPasswordEncoder::class,
'arguments' => $encoderChain,
];
}
switch ($config['algorithm']) {
case 'plaintext':
return [
'class' => PlaintextPasswordEncoder::class,
'arguments' => [$config['ignore_case']],
];
case 'pbkdf2':
return [
'class' => Pbkdf2PasswordEncoder::class,
'arguments' => [
$config['hash_algorithm'] ?? 'sha512',
$config['encode_as_base64'] ?? true,
$config['iterations'] ?? 1000,
$config['key_length'] ?? 40,
],
];
case 'bcrypt':
$config['algorithm'] = 'native';
$config['native_algorithm'] = \PASSWORD_BCRYPT;
return $this->getEncoderConfigFromAlgorithm($config);
case 'native':
return [
'class' => NativePasswordEncoder::class,
'arguments' => [
$config['time_cost'] ?? null,
(($config['memory_cost'] ?? 0) << 10) ?: null,
$config['cost'] ?? null,
] + (isset($config['native_algorithm']) ? [3 => $config['native_algorithm']] : []),
];
case 'sodium':
return [
'class' => SodiumPasswordEncoder::class,
'arguments' => [
$config['time_cost'] ?? null,
(($config['memory_cost'] ?? 0) << 10) ?: null,
],
];
case 'argon2i':
if (SodiumPasswordEncoder::isSupported() && !\defined('SODIUM_CRYPTO_PWHASH_ALG_ARGON2ID13')) {
$config['algorithm'] = 'sodium';
} elseif (\defined('PASSWORD_ARGON2I')) {
$config['algorithm'] = 'native';
$config['native_algorithm'] = \PASSWORD_ARGON2I;
} else {
throw new LogicException(sprintf('Algorithm "argon2i" is not available. Either use %s"auto" or upgrade to PHP 7.2+ instead.', \defined('SODIUM_CRYPTO_PWHASH_ALG_ARGON2ID13') ? '"argon2id", ' : ''));
}
return $this->getEncoderConfigFromAlgorithm($config);
case 'argon2id':
if (($hasSodium = SodiumPasswordEncoder::isSupported()) && \defined('SODIUM_CRYPTO_PWHASH_ALG_ARGON2ID13')) {
$config['algorithm'] = 'sodium';
} elseif (\defined('PASSWORD_ARGON2ID')) {
$config['algorithm'] = 'native';
$config['native_algorithm'] = \PASSWORD_ARGON2ID;
} else {
throw new LogicException(sprintf('Algorithm "argon2id" is not available. Either use %s"auto", upgrade to PHP 7.3+ or use libsodium 1.0.15+ instead.', \defined('PASSWORD_ARGON2I') || $hasSodium ? '"argon2i", ' : ''));
}
return $this->getEncoderConfigFromAlgorithm($config);
}
return [
'class' => MessageDigestPasswordEncoder::class,
'arguments' => [
$config['algorithm'],
$config['encode_as_base64'] ?? true,
$config['iterations'] ?? 5000,
],
];
}
}

View File

@ -0,0 +1,38 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Core\Encoder;
use Symfony\Component\PasswordHasher\Hasher\PasswordHasherFactoryInterface;
use Symfony\Component\Security\Core\User\UserInterface;
trigger_deprecation('symfony/security-core', '5.3', 'The "%s" class is deprecated, use "%s" instead.', EncoderFactoryInterface::class, PasswordHasherFactoryInterface::class);
/**
* EncoderFactoryInterface to support different encoders for different accounts.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*
* @deprecated since Symfony 5.3, use {@link PasswordHasherFactoryInterface} instead
*/
interface EncoderFactoryInterface
{
/**
* Returns the password encoder to use for the given account.
*
* @param UserInterface|string $user A UserInterface instance or a class name
*
* @return PasswordEncoderInterface
*
* @throws \RuntimeException when no password encoder could be found for the user
*/
public function getEncoder($user);
}

View File

@ -0,0 +1,56 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Core\Encoder;
use Symfony\Component\PasswordHasher\Exception\InvalidPasswordException;
use Symfony\Component\PasswordHasher\LegacyPasswordHasherInterface;
use Symfony\Component\PasswordHasher\PasswordHasherInterface;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
/**
* @internal
*/
trait LegacyEncoderTrait
{
/**
* @var PasswordHasherInterface|LegacyPasswordHasherInterface
*/
private $hasher;
/**
* {@inheritdoc}
*/
public function encodePassword(string $raw, ?string $salt): string
{
try {
return $this->hasher->hash($raw, $salt);
} catch (InvalidPasswordException $e) {
throw new BadCredentialsException('Bad credentials.');
}
}
/**
* {@inheritdoc}
*/
public function isPasswordValid(string $encoded, string $raw, ?string $salt): bool
{
return $this->hasher->verify($encoded, $raw, $salt);
}
/**
* {@inheritdoc}
*/
public function needsRehash(string $encoded): bool
{
return $this->hasher->needsRehash($encoded);
}
}

View File

@ -0,0 +1,52 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Core\Encoder;
use Symfony\Component\PasswordHasher\Exception\InvalidPasswordException;
use Symfony\Component\PasswordHasher\LegacyPasswordHasherInterface;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
/**
* Forward compatibility for new new PasswordHasher component.
*
* @author Alexander M. Turek <me@derrabus.de>
*
* @internal To be removed in Symfony 6
*/
final class LegacyPasswordHasherEncoder implements PasswordEncoderInterface
{
private $passwordHasher;
public function __construct(LegacyPasswordHasherInterface $passwordHasher)
{
$this->passwordHasher = $passwordHasher;
}
public function encodePassword(string $raw, ?string $salt): string
{
try {
return $this->passwordHasher->hash($raw, $salt);
} catch (InvalidPasswordException $e) {
throw new BadCredentialsException($e->getMessage(), $e->getCode(), $e);
}
}
public function isPasswordValid(string $encoded, string $raw, ?string $salt): bool
{
return $this->passwordHasher->verify($encoded, $raw, $salt);
}
public function needsRehash(string $encoded): bool
{
return $this->passwordHasher->needsRehash($encoded);
}
}

View File

@ -0,0 +1,87 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Core\Encoder;
use Symfony\Component\PasswordHasher\Hasher\MessageDigestPasswordHasher;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
trigger_deprecation('symfony/security-core', '5.3', 'The "%s" class is deprecated, use "%s" instead.', MessageDigestPasswordEncoder::class, MessageDigestPasswordHasher::class);
/**
* MessageDigestPasswordEncoder uses a message digest algorithm.
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @deprecated since Symfony 5.3, use {@link MessageDigestPasswordHasher} instead
*/
class MessageDigestPasswordEncoder extends BasePasswordEncoder
{
private $algorithm;
private $encodeHashAsBase64;
private $iterations = 1;
private $encodedLength = -1;
/**
* @param string $algorithm The digest algorithm to use
* @param bool $encodeHashAsBase64 Whether to base64 encode the password hash
* @param int $iterations The number of iterations to use to stretch the password hash
*/
public function __construct(string $algorithm = 'sha512', bool $encodeHashAsBase64 = true, int $iterations = 5000)
{
$this->algorithm = $algorithm;
$this->encodeHashAsBase64 = $encodeHashAsBase64;
try {
$this->encodedLength = \strlen($this->encodePassword('', 'salt'));
} catch (\LogicException $e) {
// ignore algorithm not supported
}
$this->iterations = $iterations;
}
/**
* {@inheritdoc}
*/
public function encodePassword(string $raw, ?string $salt)
{
if ($this->isPasswordTooLong($raw)) {
throw new BadCredentialsException('Invalid password.');
}
if (!\in_array($this->algorithm, hash_algos(), true)) {
throw new \LogicException(sprintf('The algorithm "%s" is not supported.', $this->algorithm));
}
$salted = $this->mergePasswordAndSalt($raw, $salt);
$digest = hash($this->algorithm, $salted, true);
// "stretch" hash
for ($i = 1; $i < $this->iterations; ++$i) {
$digest = hash($this->algorithm, $digest.$salted, true);
}
return $this->encodeHashAsBase64 ? base64_encode($digest) : bin2hex($digest);
}
/**
* {@inheritdoc}
*/
public function isPasswordValid(string $encoded, string $raw, ?string $salt)
{
if (\strlen($encoded) !== $this->encodedLength || str_contains($encoded, '$')) {
return false;
}
return !$this->isPasswordTooLong($raw) && $this->comparePasswords($encoded, $this->encodePassword($raw, $salt));
}
}

View File

@ -0,0 +1,77 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Core\Encoder;
use Symfony\Component\PasswordHasher\Hasher\MigratingPasswordHasher;
trigger_deprecation('symfony/security-core', '5.3', 'The "%s" class is deprecated, use "%s" instead.', MigratingPasswordEncoder::class, MigratingPasswordHasher::class);
/**
* Hashes passwords using the best available encoder.
* Validates them using a chain of encoders.
*
* /!\ Don't put a PlaintextPasswordEncoder in the list as that'd mean a leaked hash
* could be used to authenticate successfully without knowing the cleartext password.
*
* @author Nicolas Grekas <p@tchwork.com>
*
* @deprecated since Symfony 5.3, use {@link MigratingPasswordHasher} instead
*/
final class MigratingPasswordEncoder extends BasePasswordEncoder implements SelfSaltingEncoderInterface
{
private $bestEncoder;
private $extraEncoders;
public function __construct(PasswordEncoderInterface $bestEncoder, PasswordEncoderInterface ...$extraEncoders)
{
$this->bestEncoder = $bestEncoder;
$this->extraEncoders = $extraEncoders;
}
/**
* {@inheritdoc}
*/
public function encodePassword(string $raw, ?string $salt): string
{
return $this->bestEncoder->encodePassword($raw, $salt);
}
/**
* {@inheritdoc}
*/
public function isPasswordValid(string $encoded, string $raw, ?string $salt): bool
{
if ($this->bestEncoder->isPasswordValid($encoded, $raw, $salt)) {
return true;
}
if (!$this->bestEncoder->needsRehash($encoded)) {
return false;
}
foreach ($this->extraEncoders as $encoder) {
if ($encoder->isPasswordValid($encoded, $raw, $salt)) {
return true;
}
}
return false;
}
/**
* {@inheritdoc}
*/
public function needsRehash(string $encoded): bool
{
return $this->bestEncoder->needsRehash($encoded);
}
}

View File

@ -0,0 +1,38 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Core\Encoder;
use Symfony\Component\PasswordHasher\Hasher\NativePasswordHasher;
trigger_deprecation('symfony/security-core', '5.3', 'The "%s" class is deprecated, use "%s" instead.', NativePasswordEncoder::class, NativePasswordHasher::class);
/**
* Hashes passwords using password_hash().
*
* @author Elnur Abdurrakhimov <elnur@elnur.pro>
* @author Terje Bråten <terje@braten.be>
* @author Nicolas Grekas <p@tchwork.com>
*
* @deprecated since Symfony 5.3, use {@link NativePasswordHasher} instead
*/
final class NativePasswordEncoder implements PasswordEncoderInterface, SelfSaltingEncoderInterface
{
use LegacyEncoderTrait;
/**
* @param string|null $algo An algorithm supported by password_hash() or null to use the stronger available algorithm
*/
public function __construct(int $opsLimit = null, int $memLimit = null, int $cost = null, string $algo = null)
{
$this->hasher = new NativePasswordHasher($opsLimit, $memLimit, $cost, $algo);
}
}

View File

@ -0,0 +1,55 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Core\Encoder;
use Symfony\Component\PasswordHasher\PasswordHasherInterface;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
trigger_deprecation('symfony/security-core', '5.3', 'The "%s" class is deprecated, use "%s" instead.', PasswordEncoderInterface::class, PasswordHasherInterface::class);
/**
* PasswordEncoderInterface is the interface for all encoders.
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @deprecated since Symfony 5.3, use {@link PasswordHasherInterface} instead
*/
interface PasswordEncoderInterface
{
/**
* Encodes the raw password.
*
* @return string
*
* @throws BadCredentialsException If the raw password is invalid, e.g. excessively long
* @throws \InvalidArgumentException If the salt is invalid
*/
public function encodePassword(string $raw, ?string $salt);
/**
* Checks a raw password against an encoded password.
*
* @param string $encoded An encoded password
* @param string $raw A raw password
* @param string|null $salt The salt
*
* @return bool
*
* @throws \InvalidArgumentException If the salt is invalid
*/
public function isPasswordValid(string $encoded, string $raw, ?string $salt);
/**
* Checks if an encoded password would benefit from rehashing.
*/
public function needsRehash(string $encoded): bool;
}

View File

@ -0,0 +1,46 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Core\Encoder;
use Symfony\Component\PasswordHasher\LegacyPasswordHasherInterface;
/**
* Forward compatibility for new new PasswordHasher component.
*
* @author Alexander M. Turek <me@derrabus.de>
*
* @internal To be removed in Symfony 6
*/
final class PasswordHasherAdapter implements LegacyPasswordHasherInterface
{
private $passwordEncoder;
public function __construct(PasswordEncoderInterface $passwordEncoder)
{
$this->passwordEncoder = $passwordEncoder;
}
public function hash(string $plainPassword, string $salt = null): string
{
return $this->passwordEncoder->encodePassword($plainPassword, $salt);
}
public function verify(string $hashedPassword, string $plainPassword, string $salt = null): bool
{
return $this->passwordEncoder->isPasswordValid($hashedPassword, $plainPassword, $salt);
}
public function needsRehash(string $hashedPassword): bool
{
return $this->passwordEncoder->needsRehash($hashedPassword);
}
}

View File

@ -0,0 +1,60 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Core\Encoder;
use Symfony\Component\PasswordHasher\Exception\InvalidPasswordException;
use Symfony\Component\PasswordHasher\PasswordHasherInterface;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
/**
* Forward compatibility for new new PasswordHasher component.
*
* @author Alexander M. Turek <me@derrabus.de>
*
* @internal To be removed in Symfony 6
*/
final class PasswordHasherEncoder implements PasswordEncoderInterface, SelfSaltingEncoderInterface
{
private $passwordHasher;
public function __construct(PasswordHasherInterface $passwordHasher)
{
$this->passwordHasher = $passwordHasher;
}
public function encodePassword(string $raw, ?string $salt): string
{
if (null !== $salt) {
throw new \InvalidArgumentException('This password hasher does not support passing a salt.');
}
try {
return $this->passwordHasher->hash($raw);
} catch (InvalidPasswordException $e) {
throw new BadCredentialsException($e->getMessage(), $e->getCode(), $e);
}
}
public function isPasswordValid(string $encoded, string $raw, ?string $salt): bool
{
if (null !== $salt) {
throw new \InvalidArgumentException('This password hasher does not support passing a salt.');
}
return $this->passwordHasher->verify($encoded, $raw);
}
public function needsRehash(string $encoded): bool
{
return $this->passwordHasher->needsRehash($encoded);
}
}

View File

@ -0,0 +1,47 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Core\Encoder;
use Symfony\Component\PasswordHasher\Hasher\Pbkdf2PasswordHasher;
trigger_deprecation('symfony/security-core', '5.3', 'The "%s" class is deprecated, use "%s" instead.', Pbkdf2PasswordEncoder::class, Pbkdf2PasswordHasher::class);
/**
* Pbkdf2PasswordEncoder uses the PBKDF2 (Password-Based Key Derivation Function 2).
*
* Providing a high level of Cryptographic security,
* PBKDF2 is recommended by the National Institute of Standards and Technology (NIST).
*
* But also warrants a warning, using PBKDF2 (with a high number of iterations) slows down the process.
* PBKDF2 should be used with caution and care.
*
* @author Sebastiaan Stok <s.stok@rollerscapes.net>
* @author Andrew Johnson
* @author Fabien Potencier <fabien@symfony.com>
*
* @deprecated since Symfony 5.3, use {@link Pbkdf2PasswordHasher} instead
*/
class Pbkdf2PasswordEncoder extends BasePasswordEncoder
{
use LegacyEncoderTrait;
/**
* @param string $algorithm The digest algorithm to use
* @param bool $encodeHashAsBase64 Whether to base64 encode the password hash
* @param int $iterations The number of iterations to use to stretch the password hash
* @param int $length Length of derived key to create
*/
public function __construct(string $algorithm = 'sha512', bool $encodeHashAsBase64 = true, int $iterations = 1000, int $length = 40)
{
$this->hasher = new Pbkdf2PasswordHasher($algorithm, $encodeHashAsBase64, $iterations, $length);
}
}

View File

@ -0,0 +1,38 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Core\Encoder;
use Symfony\Component\PasswordHasher\Hasher\PlaintextPasswordHasher;
trigger_deprecation('symfony/security-core', '5.3', 'The "%s" class is deprecated, use "%s" instead.', PlaintextPasswordEncoder::class, PlaintextPasswordHasher::class);
/**
* PlaintextPasswordEncoder does not do any encoding but is useful in testing environments.
*
* As this encoder is not cryptographically secure, usage of it in production environments is discouraged.
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @deprecated since Symfony 5.3, use {@link PlaintextPasswordHasher} instead
*/
class PlaintextPasswordEncoder extends BasePasswordEncoder
{
use LegacyEncoderTrait;
/**
* @param bool $ignorePasswordCase Compare password case-insensitive
*/
public function __construct(bool $ignorePasswordCase = false)
{
$this->hasher = new PlaintextPasswordHasher($ignorePasswordCase);
}
}

View File

@ -0,0 +1,28 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Core\Encoder;
use Symfony\Component\PasswordHasher\LegacyPasswordHasherInterface;
trigger_deprecation('symfony/security-core', '5.3', 'The "%s" interface is deprecated, use "%s" on hasher implementations that deal with salts instead.', SelfSaltingEncoderInterface::class, LegacyPasswordHasherInterface::class);
/**
* SelfSaltingEncoderInterface is a marker interface for encoders that do not
* require a user-generated salt.
*
* @author Zan Baldwin <hello@zanbaldwin.com>
*
* @deprecated since Symfony 5.3, use {@link LegacyPasswordHasherInterface} instead
*/
interface SelfSaltingEncoderInterface
{
}

View File

@ -0,0 +1,40 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Core\Encoder;
use Symfony\Component\PasswordHasher\Hasher\SodiumPasswordHasher;
trigger_deprecation('symfony/security-core', '5.3', 'The "%s" class is deprecated, use "%s" instead.', SodiumPasswordEncoder::class, SodiumPasswordHasher::class);
/**
* Hashes passwords using libsodium.
*
* @author Robin Chalas <robin.chalas@gmail.com>
* @author Zan Baldwin <hello@zanbaldwin.com>
* @author Dominik Müller <dominik.mueller@jkweb.ch>
*
* @deprecated since Symfony 5.3, use {@link SodiumPasswordHasher} instead
*/
final class SodiumPasswordEncoder implements PasswordEncoderInterface, SelfSaltingEncoderInterface
{
use LegacyEncoderTrait;
public function __construct(int $opsLimit = null, int $memLimit = null)
{
$this->hasher = new SodiumPasswordHasher($opsLimit, $memLimit);
}
public static function isSupported(): bool
{
return SodiumPasswordHasher::isSupported();
}
}

View File

@ -0,0 +1,83 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Core\Encoder;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasher;
use Symfony\Component\Security\Core\User\LegacyPasswordAuthenticatedUserInterface;
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
use Symfony\Component\Security\Core\User\UserInterface;
trigger_deprecation('symfony/security-core', '5.3', 'The "%s" class is deprecated, use "%s" instead.', UserPasswordEncoder::class, UserPasswordHasher::class);
/**
* A generic password encoder.
*
* @author Ariel Ferrandini <arielferrandini@gmail.com>
*
* @deprecated since Symfony 5.3, use {@link UserPasswordHasher} instead
*/
class UserPasswordEncoder implements UserPasswordEncoderInterface
{
private $encoderFactory;
public function __construct(EncoderFactoryInterface $encoderFactory)
{
$this->encoderFactory = $encoderFactory;
}
/**
* {@inheritdoc}
*/
public function encodePassword(UserInterface $user, string $plainPassword)
{
$encoder = $this->encoderFactory->getEncoder($user);
if (!$user instanceof PasswordAuthenticatedUserInterface) {
trigger_deprecation('symfony/password-hasher', '5.3', 'Not implementing the "%s" interface while using "%s" is deprecated, the "%s" class should implement it.', PasswordAuthenticatedUserInterface::class, __CLASS__, get_debug_type($user));
}
$salt = $user->getSalt();
if ($salt && !$user instanceof LegacyPasswordAuthenticatedUserInterface) {
trigger_deprecation('symfony/password-hasher', '5.3', 'Returning a string from "getSalt()" without implementing the "%s" interface is deprecated, the "%s" class should implement it.', LegacyPasswordAuthenticatedUserInterface::class, get_debug_type($user));
}
return $encoder->encodePassword($plainPassword, $user->getSalt());
}
/**
* {@inheritdoc}
*/
public function isPasswordValid(UserInterface $user, string $raw)
{
if (null === $user->getPassword()) {
return false;
}
$encoder = $this->encoderFactory->getEncoder($user);
return $encoder->isPasswordValid($user->getPassword(), $raw, $user->getSalt());
}
/**
* {@inheritdoc}
*/
public function needsRehash(UserInterface $user): bool
{
if (null === $user->getPassword()) {
return false;
}
$encoder = $this->encoderFactory->getEncoder($user);
return $encoder->needsRehash($user->getPassword());
}
}

View File

@ -0,0 +1,44 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Security\Core\Encoder;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
use Symfony\Component\Security\Core\User\UserInterface;
trigger_deprecation('symfony/security-core', '5.3', 'The "%s" interface is deprecated, use "%s" instead.', UserPasswordEncoderInterface::class, UserPasswordHasherInterface::class);
/**
* UserPasswordEncoderInterface is the interface for the password encoder service.
*
* @author Ariel Ferrandini <arielferrandini@gmail.com>
*
* @deprecated since Symfony 5.3, use {@link UserPasswordHasherInterface} instead
*/
interface UserPasswordEncoderInterface
{
/**
* Encodes the plain password.
*
* @return string
*/
public function encodePassword(UserInterface $user, string $plainPassword);
/**
* @return bool
*/
public function isPasswordValid(UserInterface $user, string $raw);
/**
* Checks if an encoded password would benefit from rehashing.
*/
public function needsRehash(UserInterface $user): bool;
}