09/02/2026
Leaving FOSUserBundle: what replaces each piece
FOSUserBundle's own README is the clearest statement of where it stands: it receives minimal maintenance so existing projects can upgrade, existing projects are expected to plan a migration away, and new projects should not use it.
That is not a bundle that went bad. It is a bundle whose job the framework absorbed. When it was written, Symfony gave you a firewall and left registration, password resets, email confirmation and user management as an exercise. Most of that is now either in the framework or in a bundle that does one thing.
What replaces what
| FOSUserBundle gave you | Now |
|---|---|
A User entity and base class |
make:user, generating an entity you own |
| A user provider | Symfony's EntityUserProvider, configured in security.yaml |
| Password encoding | The PasswordHasher component, and UserPasswordHasherInterface |
| Registration form | A normal Symfony form; make:registration-form scaffolds it |
| Email confirmation | SymfonyCasts VerifyEmailBundle |
| Password reset | SymfonyCasts ResetPasswordBundle |
| Change password | A form and one call to the hasher |
fos:user:* console commands |
Commands you write, if you still want them |
The through-line is that you end up owning the User entity rather than
inheriting from one. That is the actual benefit and the actual cost: no
more fighting a base class over a field you wanted shaped differently, and
no more getting four features for free.
The user provider is most of the configuration
# config/packages/security.yaml
security:
password_hashers:
App\Entity\User: 'auto'
providers:
app_user_provider:
entity:
class: App\Entity\User
property: email
firewalls:
main:
lazy: true
provider: app_user_provider
property: email is the field the identifier is looked up on, and it is
the same value your entity's getUserIdentifier() should return. If those
two disagree, authentication succeeds and then behaves strangely, which is
an unpleasant afternoon.
The old password hashes still work
This is the part people expect to be hard and is not. password_hashers
set to auto uses the best hasher available and verifies against
whatever algorithm each stored hash actually used, so accounts created
under FOSUserBundle keep working after the bundle is gone.
Symfony can also upgrade them in place as people sign in, if the user
class and provider implement PasswordUpgraderInterface — which
make:user generates for you. Old hashes get replaced with current ones
one successful login at a time, and nobody is asked to reset anything.
What to delete, and in what order
- Generate the replacement pieces first, while the bundle is still
installed:
make:useragainst your existing table, then the registration and reset flows. - Point
security.yamlat the new provider and hasher. - Replace the bundle's routes and templates with your own.
- Remove the bundle last, and only once nothing references
FOS\UserBundleanywhere.
Doing it in that order means the application authenticates throughout. The version where the bundle comes out first has a window where nobody can log in, including you.
One thing not to carry across
If your migration notes include re-authenticating somebody from a value read out of a cookie, leave it behind. Encryption is not authentication, and a cookie that says who you are without proving it is an authentication bypass regardless of how it is encoded. Symfony's remember-me handles the legitimate version of that requirement, signed, and it is one line of firewall configuration.