-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[Security] Decouple passwords from UserInterface #40267
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
f46b6eb
to
fa3f599
Compare
4063d16
to
c4a7af5
Compare
Build failure with high-deps expected (will be fixed once merged). |
fbdf20c
to
08e04e6
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for working on this feature!
src/Symfony/Bridge/Doctrine/Security/User/EntityUserProvider.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/PasswordHasher/Hasher/UserPasswordHasher.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/PasswordHasher/Tests/Hasher/UserPasswordHasherTest.php
Outdated
Show resolved
Hide resolved
08e04e6
to
c2a72bd
Compare
c2a72bd
to
74330bc
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking great. It doesn't look like it causes much of change in the internals, which is great :). Just some small comments found while looking at the diff. I'll find some time this week to test it in a real project.
I think we should also add this to the guard. This is the most tricky, but I think we can trigger the deprecation in GuardAuthenticationProvider
and GuardBridgeAuthenticator
if we check for $guard instanceof PasswordAuthenticatedInterface && !$user instanceof PasswordAuthenticatedUserInterface
(or maybe directly test whether the user's getPassword
or getSalt
don't return null?).
8716067
to
1054ba7
Compare
Good idea. Done, thank you. Note that |
770e25b
to
aacfbd0
Compare
Added one compile-time deprecation to ease upgrading. Fixed psalm reports also. |
5066319
to
8e1a5d6
Compare
8e1a5d6
to
2764225
Compare
Thank you @chalasr. |
…oic425) This PR was merged into the 1.10-dev branch. Discussion ---------- | Q | A | --------------- | ----- | Branch? | 1.7, 1.8 or master <!-- see the comment below --> | Bug fix? | no/yes | New feature? | no/yes | BC breaks? | no/yes | Deprecations? | no/yes <!-- don't forget to update the UPGRADE-*.md file --> | Related tickets | fixes #X, partially #Y, mentioned in #Z | License | MIT <!-- - Bug fixes must be submitted against the 1.7 or 1.8 branch (the lowest possible) - Features and deprecations must be submitted against the master branch - Make sure that the correct base branch is set To be sure you are not breaking any Backward Compatibilities, check the documentation: https://docs.sylius.com/en/latest/book/organization/backward-compatibility-promise.html --> When using a SSO such as Keycloak, you don't need a password. It's better to allow null instead of setting plain password with a random value. Moreover, password will be decoupled from user interface on Symfony security user. symfony/symfony#40267 Commits ------- e20f871 Allow user password to be null 9daecf6 Move migration into core bundle
…oic425) This PR was merged into the 1.10-dev branch. Discussion ---------- | Q | A | --------------- | ----- | Branch? | 1.7, 1.8 or master <!-- see the comment below --> | Bug fix? | no/yes | New feature? | no/yes | BC breaks? | no/yes | Deprecations? | no/yes <!-- don't forget to update the UPGRADE-*.md file --> | Related tickets | fixes #X, partially #Y, mentioned in #Z | License | MIT <!-- - Bug fixes must be submitted against the 1.7 or 1.8 branch (the lowest possible) - Features and deprecations must be submitted against the master branch - Make sure that the correct base branch is set To be sure you are not breaking any Backward Compatibilities, check the documentation: https://docs.sylius.com/en/latest/book/organization/backward-compatibility-promise.html --> When using a SSO such as Keycloak, you don't need a password. It's better to allow null instead of setting plain password with a random value. Moreover, password will be decoupled from user interface on Symfony security user. symfony/symfony#40267 Commits ------- e20f871d9a49c6028ba7c1cd3708f7986ebe32aa Allow user password to be null 9daecf696b3c489dbe56f7ba26b162527a7948c9 Move migration into core bundle
…serIdentifier() (wouterj) This PR was squashed before being merged into the 5.3-dev branch. Discussion ---------- [Security] Rename UserInterface::getUsername() to getUserIdentifier() | Q | A | ------------- | --- | Branch? | 5.x | Bug fix? | no | New feature? | yes | Deprecations? | yes | Tickets | Fix part of #39308 | License | MIT | Doc PR | tbd This continues the great work by @chalasr in #40267 and rounds up the `UserInterface` cleanup. The `getUsername()` has been a point of confusion for many years. In today's applications, many domains no longer have a username, but instead rely on a user's email address or the like. Even more, this username has to be unique for all Security functionality to work correctly - so it's more confusing in complex applications relying on e.g. "username+company" to be unique. **This PR proposes to rename the method to `getUserIdentifier()`**, to more clearly indicate the goal of the method (note: I'm open for any other suggestion). For BC, the `getUsername()` method is deprecated in 5.3 and `getUserIdentifier()` will be added to the `UserInterface` in 6.0. PHPdocs are used to improve type-hinting for 5.3 & 5.4. Both authentication managers (the legacy and experimental one) check the authenticated user object and trigger a deprecation if `getUserIdentifier()` is not implemented. * [x] **judge whether we need to have better deprecations for calling `getUsername()` in the application code.** Consistent with these changes, I've also done the same BC change for `TokenInterface::getUsername()`. * [x] **do the same for remember me's `PersistentTokenInterface::getUsername()`** * [x] **also rename `UserProviderInterface::loadUserByUsername()` & `UsernameNotFoundException`** * [x] **also rename `UserLoaderInterface::loadUserByUsername()`** I'm very much looking forward for feedback and help for this important, but BC-heavy, rename. 😃 Commits ------- 8afd7a3 [Security] Rename UserInterface::getUsername() to getUserIdentifier()
…dUserInterface (jrushlow) This PR was squashed before being merged into the 1.0-dev branch. Discussion ---------- [make:user] user entities implement PasswordAuthenticatedUserInterface Starting in Symfony 5.3 - PR symfony/symfony#40267 introduces the new `PasswordAuthenticatedUserInterface` ~& `LegacyPasswordAuthenticatedUserInterface`~ aimed at decoupling passwords from the `UserInterface`. - Generated `User` entity implements `PasswordAuthenticatedUserInterface` if it exists. - Adds correct type hint to the generated `UserRepository::upgradePassword()` method. Authentication related changes are handled in #824 // cc @chalasr Commits ------- f9d9d03 [make:user] user entities implement PasswordAuthenticatedUserInterface
…rInterface (chalasr) This PR was merged into the 6.0 branch. Discussion ---------- [Security] Remove getPassword() and getSalt() from UserInterface | Q | A | ------------- | --- | Branch? | 6.0 | Bug fix? | no | New feature? | no | Deprecations? | no | Tickets | - | License | MIT | Doc PR | - with BC layers from #40267 Commits ------- 30e2c00 [Security] Remove getPassword() and getSalt() from UserInterface
This PR addresses a long-standing issue of the Security component: UserInterface is coupled to passwords.
It does it by moving the
getPassword()
method fromUserInterface
to aPasswordAuthenticatedUserInterface
, and thegetSalt()
method to aLegacyPasswordAuthenticatedUserInterface
.Steps:
UserInterface
object does not implement the new interface(s). The UserInterface is kept as-is until 6.0.UserInterface
as well as support for using password authentication with user objects not implementing the new interface(s).As a side-effect, some password-related interfaces (
UserPasswordHasherInterface
andPasswordUpgraderInterface
) must change their signatures to type-hint against the new interface.That is done in a BC way, which is to make the concerned methods virtual until 6.0, with deprecation notices triggered from callers and concrete implementations.
Benefits:
In 6.0, applications that use password-less authentication (e.g. login links) won't need to write no-op
getPassword()
andgetSalt()
in order to fulfil theUserInterface
contract.For applications that do use password-based authentication, they will need to opt-in explicitly by implementing the relevant interface(s).
This build on great discussions with @wouterj and @nicolas-grekas, and it is part of the overall rework of the Security component.