fastfony/identity-bundle
A Symfony bundle that adds a complete identity and access management layer to your app. It provides user accounts, authentication, roles and permissions, registration and password flows, plus ready-to-use security configuration so you can ship secure, manageable user systems faster.
Reality check first. fastfony/identity-bundle is a Symfony bundle, not a Laravel package. If you're a Laravel developer, "day-to-day leverage" splits into two honest scenarios: you're maintaining or integrating with a Symfony service (then this is directly usable), or you're looking for a Laravel auth/roles/groups solution (then this is a reference model, not a dependency). Do not try to composer require this into a Laravel app — it will pull Symfony security/Doctrine contracts and fight Laravel's container.
Concept translation table (useful before you read any of the code):
| Bundle concept | Laravel equivalent | Notes |
|---|---|---|
| User entity | App\Models\User |
Doctrine entity vs Eloquent model |
| Role | spatie/laravel-permission Role |
Persisted vs config-driven |
| Group | Laravel "teams" / permission teams | Group as a bag of roles is the key idea |
| Security voters | Gates/Policies | Same authorization shape, different wiring |
| User provider | Auth::provider() |
Swap-in extension point |
Minimal Symfony-side steps (verify exact names against the README and composer show; the package is low-adoption, so trust the source over blog posts):
composer require fastfony/identity-bundle in a Symfony 6/7 app with Doctrine ORM and symfony/security-bundle present.config/bundles.php manually.config/packages/ for the bundle's config file; the package almost certainly expects a configurable user entity class. Set it to your app's User entity.php bin/console doctrine:migrations:diff and review the generated schema before applying — do not assume the bundle ships migrations you want verbatim.security.yaml points at the bundle's user provider.Where to look first: the bundle's DependencyInjection/Configuration.php (tells you every knob it actually supports), then its entity/repository classes, then Resources/config/services.php. That trio tells you more than the README will.
First use case: a "group grants a role" flow — create a group, attach roles to it, assign users to the group, and check authorization with $this->isGranted('ROLE_X') in a controller. That single path exercises the entity relations, the repository queries, and the security integration at once, which is the fastest way to know whether the bundle fits.
Centralize role names as constants. The moment roles live in the database and in security.yaml and in string literals in controllers, you have three sources of truth. Define App\Security\Roles::ADMIN etc., seed the DB from those constants, and reference the constants in access checks and voters.
Treat groups as role bundles, not as a second permission system. The clean pattern is: User -> Groups -> Roles -> Voter checks. Groups should never be checked directly in authorization logic; resolve a user's effective roles through their groups and let voters work on roles only. This keeps the model portable if you later rewrite it in Laravel with spatie/laravel-permission teams.
Seed, don't hand-create. Write a fixture or a console command that creates the baseline roles and groups idempotently. Day-to-day, every environment (test, staging, prod) needs the same role skeleton, and hand-clicking an admin UI for that is how you get drift.
Wrap role assignment in a service, not controllers. A small IdentityManager (assign group, revoke role, resolve effective roles) gives you one place to fire events, clear caches, and audit. It also becomes your seam if you swap the bundle out later.
Use the security voter as the integration boundary. Don't call isGranted('ROLE_ADMIN') scatter-shot. Write attributes like POST_EDIT and have one voter that consults effective roles. If you ever port to Laravel, that voter maps 1:1 onto a Policy.
If you're the Laravel side of a mixed stack: mirror the bundle's model in Eloquent deliberately — users, roles, groups, group_role, group_user pivots — and sync from the Symfony service via an API or a queue message rather than a shared database. Shared ORM schemas across frameworks are a durable source of pain (see Gotchas).
Testing pattern: load a fixture user per role tier (guest, member, group-admin, super-admin) and assert authorization on each route. This is cheap and catches role-hierarchy misconfiguration immediately, which is the most common wiring bug in bundles like this.
composer.json — an unpinned minor bump from a single-maintainer package is a real regression vector.users table.security.yaml, not the bundle. role_hierarchy is Symfony security config; the bundle stores roles but won't expand them for you. If a group assigns ROLE_ADMIN and you expect ROLE_USER to follow, that expansion must be declared in the firewall config.bin/console cache:clear — a classic "my role change didn't apply" red herring.bin/console debug:container --tag=security.voter to confirm the bundle's voter (if any) is registered, and bin/console debug:config <bundle_alias> to see the merged config rather than what you think you wrote.final and whether the bundle maps them itself.spatie/laravel-permission will do roles + permissions + teams with a maintained migration path; the only thing worth borrowing from this bundle is the group-as-role-container abstraction, not its schema.composer.json constraint rather than discovering incompatibility at runtime.How can I help you explore Laravel packages today?