I'm implementing a password reset functionality using Symfony2. I have questions about hashing and salting the confirmation code used to validate the reset request.
The $user
variable contains an instance of Acme\SecurityBundle\Model\User
. The algorithm for this class is bcrypt and the cost is 15.
Acme\SecurityBundle\Model\User
namespace Acme\SecurityBundle\Model;
use Acme\SecurityBundle\Model\om\BaseUser;
use Symfony\Component\Security\Core\Util\SecureRandom;
class User extends BaseUser
{
public function getSalt()
{
$random = new SecureRandom();
return base64_encode($random->nextBytes(128 / 8));
}
}
Hashing and validating happens inside a controller as follows.
Hashing:
// Generate confirmation code
$tokenGenerator = new UriSafeTokenGenerator();
$resetConfirmationCodePlain = substr($tokenGenerator->generateToken(), 0, 20);
// Hash confirmation code
$factory = $this->get('security.encoder_factory');
$encoder = $factory->getEncoder($user);
$resetConfirmationCode = $encoder->encodePassword($resetConfirmationCodePlain, $user->getSalt());
Validating:
// Validate confirmation code
$factory = $this->get('security.encoder_factory');
$encoder = $factory->getEncoder($user);
$isValid = $encoder->isPasswordValid(
$user->getResetConfirmationCode(), $confirmationCode, null
);
As you can see a salt is added while hashing, but not added while validating. Nonetheless the confirmation code validated successfully.
Can someone explain this? Does Symfony derive the salt from the hash or isn't the hash salted at all?
P.S. I update a user's password in the same way.