How to Use A Different Password Encoder Algorithm Per User
How to Use A Different Password Encoder Algorithm Per User
Usually, the same password encoder is used for all users by configuring it to apply to all instances of a specific class:
YAML
# config/packages/security.yaml
security:
# ...
encoders:
App\Entity\User:
algorithm: auto
cost: 12
XML
<!-- config/packages/security.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<srv:container xmlns="http://symfony.com/schema/dic/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:srv="http://symfony.com/schema/dic/services"
xsi:schemaLocation="http://symfony.com/schema/dic/services
https://symfony.com/schema/dic/services/services-1.0.xsd"
>
<config>
<!-- ... -->
<encoder class="App\Entity\User"
algorithm="auto"
cost="12"
/>
</config>
</srv:container>
PHP
// config/packages/security.php
use App\Entity\User;
$container->loadFromExtension('security', [
// ...
'encoders' => [
User::class => [
'algorithm' => 'auto',
'cost' => 12,
],
],
]);
Another option is to use a “named” encoder and then select which encoder you want to use dynamically.
In the previous example, you’ve set the auto
algorithm for App\Entity\User
. This may be secure enough for a regular user, but what if you want your admins to have a stronger algorithm, for example auto
with a higher cost. This can be done with named encoders:
YAML
# config/packages/security.yaml
security:
# ...
encoders:
harsh:
algorithm: auto
cost: 15
XML
<!-- config/packages/security.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<srv:container xmlns="http://symfony.com/schema/dic/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:srv="http://symfony.com/schema/dic/services"
xsi:schemaLocation="http://symfony.com/schema/dic/services
https://symfony.com/schema/dic/services/services-1.0.xsd"
>
<config>
<!-- ... -->
<encoder class="harsh"
algorithm="auto"
cost="15"/>
</config>
</srv:container>
PHP
// config/packages/security.php
$container->loadFromExtension('security', [
// ...
'encoders' => [
'harsh' => [
'algorithm' => 'auto',
'cost' => '15',
],
],
]);
Note
If you are running PHP 7.2+ or have the libsodium extension installed, then the recommended hashing algorithm to use is Sodium.
This creates an encoder named harsh
. In order for a User
instance to use it, the class must implement Symfony\Component\Security\Core\Encoder\EncoderAwareInterface
. The interface requires one method - getEncoderName()
- which should return the name of the encoder to use:
// src/Entity/User.php
namespace App\Entity;
use Symfony\Component\Security\Core\Encoder\EncoderAwareInterface;
use Symfony\Component\Security\Core\User\UserInterface;
class User implements UserInterface, EncoderAwareInterface
{
public function getEncoderName(): ?string
{
if ($this->isAdmin()) {
return 'harsh';
}
return null; // use the default encoder
}
}
If you created your own password encoder implementing the Symfony\Component\Security\Core\Encoder\PasswordEncoderInterface
, you must register a service for it in order to use it as a named encoder:
YAML
# config/packages/security.yaml
security:
# ...
encoders:
app_encoder:
id: 'App\Security\Encoder\MyCustomPasswordEncoder'
XML
<!-- config/packages/security.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<srv:container xmlns="http://symfony.com/schema/dic/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:srv="http://symfony.com/schema/dic/services"
xsi:schemaLocation="http://symfony.com/schema/dic/services
https://symfony.com/schema/dic/services/services-1.0.xsd"
>
<config>
<!-- ... -->
<encoder class="app_encoder"
id="App\Security\Encoder\MyCustomPasswordEncoder"/>
</config>
</srv:container>
PHP
// config/packages/security.php
// ...
use App\Security\Encoder\MyCustomPasswordEncoder;
$container->loadFromExtension('security', [
// ...
'encoders' => [
'app_encoder' => [
'id' => MyCustomPasswordEncoder::class,
],
],
]);
This creates an encoder named app_encoder
from a service with the ID App\Security\Encoder\MyCustomPasswordEncoder
.
This work, including the code samples, is licensed under a Creative Commons BY-SA 3.0 license.