Skip to content

Commit c757845

Browse files
committed
feature #39802 [Security] Extract password hashing from security-core - with proper wording (chalasr)
This PR was merged into the 5.3-dev branch. Discussion ---------- [Security] Extract password hashing from security-core - with proper wording | Q | A | ------------- | --- | Branch? | 5.x | Bug fix? | no | New feature? | yes | Deprecations? | no | Tickets | Fixes #39698 | License | MIT | Doc PR | todo This PR renames password "encoders" to password _hashers_ (naming widely used, see e.g. django or laravel). This also takes the opportunity to extract the logic related to password hashing from security-core, moving it to a new password-hasher component. Nowadays, many modern web apps and APIs don't deal with passwords at all, that's why splitting makes sense as a step towards making security-core not tied to the password concept. For upgrading, applications will have to use `passwords_hashers` instead of `encoders` in their security configuration, and type-hint against `PasswordHasherInterface` (and related) instead of `PasswordEncoderInterface`. The proposed API is not much different from the encoder one regarding behavior and signatures, and it is slightly more close to the PHP built-in password hashing API: ```php namespace Symfony\Component\PasswordHasher; interface PasswordHasherInterface { public function hash(string $plainPassword): string; public function verify(string $hashedPassword, string $plainPassword): bool; public function needsRehash(string $hashedPassword): bool; } ``` Commits ------- c5c981c [Security] Extract password hashing from security-core - using the right naming
2 parents fe4e295 + c5c981c commit c757845

File tree

137 files changed

+4064
-490
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

137 files changed

+4064
-490
lines changed

UPGRADE-5.3.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,19 @@ PropertyInfo
6969
Security
7070
--------
7171

72+
* Deprecate all classes in the `Core\Encoder\` sub-namespace, use the `PasswordHasher` component instead
7273
* Deprecated voters that do not return a valid decision when calling the `vote` method
7374

75+
SecurityBundle
76+
--------------
77+
78+
* Deprecate `UserPasswordEncoderCommand` class and the corresponding `user:encode-password` command,
79+
use `UserPasswordHashCommand` and `user:hash-password` instead
80+
* Deprecate the `security.encoder_factory.generic` service, the `security.encoder_factory` and `Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface` aliases,
81+
use `security.password_hasher_factory` and `Symfony\Component\PasswordHasher\Hasher\PasswordHasherFactoryInterface` instead
82+
* Deprecate the `security.user_password_encoder.generic` service, the `security.password_encoder` and the `Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface` aliases,
83+
use `security.user_password_hasher`, `security.password_hasher` and `Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface` instead
84+
7485
Serializer
7586
----------
7687

UPGRADE-6.0.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ Routing
166166
Security
167167
--------
168168

169+
* Drop all classes in the `Core\Encoder\` sub-namespace, use the `PasswordHasher` component instead
169170
* Drop support for `SessionInterface $session` as constructor argument of `SessionTokenStorage`, inject a `\Symfony\Component\HttpFoundation\RequestStack $requestStack` instead
170171
* Drop support for `session` provided by the ServiceLocator injected in `UsageTrackingTokenStorage`, provide a `request_stack` service instead
171172
* Make `SessionTokenStorage` throw a `SessionNotFoundException` when called outside a request context
@@ -179,6 +180,16 @@ Security
179180
* Removed the `AbstractRememberMeServices::$providerKey` property in favor of `AbstractRememberMeServices::$firewallName`
180181
* `AccessDecisionManager` now throw an exception when a voter does not return a valid decision.
181182

183+
SecurityBundle
184+
--------------
185+
186+
* Remove the `UserPasswordEncoderCommand` class and the corresponding `user:encode-password` command,
187+
use `UserPasswordHashCommand` and `user:hash-password` instead
188+
* Remove the `security.encoder_factory.generic` service, the `security.encoder_factory` and `Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface` aliases,
189+
use `security.password_hasher_factory` and `Symfony\Component\PasswordHasher\Hasher\PasswordHasherFactoryInterface` instead
190+
* Remove the `security.user_password_encoder.generic` service, the `security.password_encoder` and the `Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface` aliases,
191+
use `security.user_password_hasher`, `security.password_hasher` and `Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface` instead
192+
182193
Serializer
183194
----------
184195

composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@
8686
"symfony/monolog-bridge": "self.version",
8787
"symfony/notifier": "self.version",
8888
"symfony/options-resolver": "self.version",
89+
"symfony/password-hasher": "self.version",
8990
"symfony/process": "self.version",
9091
"symfony/property-access": "self.version",
9192
"symfony/property-info": "self.version",

src/Symfony/Bundle/FrameworkBundle/composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151
"symfony/messenger": "^5.2",
5252
"symfony/mime": "^4.4|^5.0",
5353
"symfony/process": "^4.4|^5.0",
54-
"symfony/security-bundle": "^5.2",
54+
"symfony/security-bundle": "^5.3",
5555
"symfony/serializer": "^5.2",
5656
"symfony/stopwatch": "^4.4|^5.0",
5757
"symfony/string": "^5.0",

src/Symfony/Bundle/SecurityBundle/CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,16 @@
11
CHANGELOG
22
=========
33

4+
5.3
5+
---
6+
7+
* Deprecate `UserPasswordEncoderCommand` class and the corresponding `user:encode-password` command,
8+
use `UserPasswordHashCommand` and `user:hash-password` instead
9+
* Deprecate the `security.encoder_factory.generic` service, the `security.encoder_factory` and `Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface` aliases,
10+
use `security.password_hasher_factory` and `Symfony\Component\PasswordHasher\Hasher\PasswordHasherFactoryInterface` instead
11+
* Deprecate the `security.user_password_encoder.generic` service, the `security.password_encoder` and the `Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface` aliases,
12+
use `security.user_password_hasher`, `security.password_hasher` and `Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface` instead
13+
414
5.2.0
515
-----
616

src/Symfony/Bundle/SecurityBundle/Command/UserPasswordEncoderCommand.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
use Symfony\Component\Console\Output\OutputInterface;
2222
use Symfony\Component\Console\Question\Question;
2323
use Symfony\Component\Console\Style\SymfonyStyle;
24+
use Symfony\Component\PasswordHasher\Command\UserPasswordHashCommand;
2425
use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface;
2526
use Symfony\Component\Security\Core\Encoder\SelfSaltingEncoderInterface;
2627

@@ -30,6 +31,8 @@
3031
* @author Sarah Khalil <mkhalil.sarah@gmail.com>
3132
*
3233
* @final
34+
*
35+
* @deprecated since Symfony 5.3, use {@link UserPasswordHashCommand} instead
3336
*/
3437
class UserPasswordEncoderCommand extends Command
3538
{
@@ -107,6 +110,8 @@ protected function execute(InputInterface $input, OutputInterface $output): int
107110
$io = new SymfonyStyle($input, $output);
108111
$errorIo = $output instanceof ConsoleOutputInterface ? new SymfonyStyle($input, $output->getErrorOutput()) : $io;
109112

113+
$errorIo->caution('The use of the "security:encode-password" command is deprecated since version 5.3 and will be removed in 6.0. Use "security:hash-password" instead.');
114+
110115
$input->isInteractive() ? $errorIo->title('Symfony Password Encoder Utility') : $errorIo->newLine();
111116

112117
$password = $input->getArgument('password');

src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,23 @@ public function getConfigTreeBuilder()
6565
return $v;
6666
})
6767
->end()
68+
->beforeNormalization()
69+
->ifTrue(function ($v) {
70+
if ($v['encoders'] ?? false) {
71+
trigger_deprecation('symfony/security-bundle', '5.3', 'The child node "encoders" at path "security" is deprecated, use "password_hashers" instead.');
72+
73+
return true;
74+
}
75+
76+
return $v['password_hashers'] ?? false;
77+
})
78+
->then(function ($v) {
79+
$v['password_hashers'] = array_merge($v['password_hashers'] ?? [], $v['encoders'] ?? []);
80+
$v['encoders'] = $v['password_hashers'];
81+
82+
return $v;
83+
})
84+
->end()
6885
->children()
6986
->scalarNode('access_denied_url')->defaultNull()->example('/foo/error403')->end()
7087
->enumNode('session_fixation_strategy')
@@ -94,6 +111,7 @@ public function getConfigTreeBuilder()
94111
;
95112

96113
$this->addEncodersSection($rootNode);
114+
$this->addPasswordHashersSection($rootNode);
97115
$this->addProvidersSection($rootNode);
98116
$this->addFirewallsSection($rootNode, $this->factories);
99117
$this->addAccessControlSection($rootNode);
@@ -401,6 +419,57 @@ private function addEncodersSection(ArrayNodeDefinition $rootNode)
401419
;
402420
}
403421

422+
private function addPasswordHashersSection(ArrayNodeDefinition $rootNode)
423+
{
424+
$rootNode
425+
->fixXmlConfig('password_hasher')
426+
->children()
427+
->arrayNode('password_hashers')
428+
->example([
429+
'App\Entity\User1' => 'auto',
430+
'App\Entity\User2' => [
431+
'algorithm' => 'auto',
432+
'time_cost' => 8,
433+
'cost' => 13,
434+
],
435+
])
436+
->requiresAtLeastOneElement()
437+
->useAttributeAsKey('class')
438+
->prototype('array')
439+
->canBeUnset()
440+
->performNoDeepMerging()
441+
->beforeNormalization()->ifString()->then(function ($v) { return ['algorithm' => $v]; })->end()
442+
->children()
443+
->scalarNode('algorithm')
444+
->cannotBeEmpty()
445+
->validate()
446+
->ifTrue(function ($v) { return !\is_string($v); })
447+
->thenInvalid('You must provide a string value.')
448+
->end()
449+
->end()
450+
->arrayNode('migrate_from')
451+
->prototype('scalar')->end()
452+
->beforeNormalization()->castToArray()->end()
453+
->end()
454+
->scalarNode('hash_algorithm')->info('Name of hashing algorithm for PBKDF2 (i.e. sha256, sha512, etc..) See hash_algos() for a list of supported algorithms.')->defaultValue('sha512')->end()
455+
->scalarNode('key_length')->defaultValue(40)->end()
456+
->booleanNode('ignore_case')->defaultFalse()->end()
457+
->booleanNode('encode_as_base64')->defaultTrue()->end()
458+
->scalarNode('iterations')->defaultValue(5000)->end()
459+
->integerNode('cost')
460+
->min(4)
461+
->max(31)
462+
->defaultNull()
463+
->end()
464+
->scalarNode('memory_cost')->defaultNull()->end()
465+
->scalarNode('time_cost')->defaultNull()->end()
466+
->scalarNode('id')->end()
467+
->end()
468+
->end()
469+
->end()
470+
->end();
471+
}
472+
404473
private function getAccessDecisionStrategies()
405474
{
406475
$strategies = [

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy