Kritim Yantra
Apr 18, 2025
Managing user access is crucial for web applications. Symfony provides a powerful role-based access control (RBAC) system to restrict what users can do.
In this guide, you’ll learn:
✅ How to define roles in Symfony
✅ Restricting routes by roles
✅ Creating custom permissions with voters
✅ Best practices for security
Let’s build a secure role-based system step by step!
Roles define user access levels (e.g., ROLE_USER
, ROLE_ADMIN
).
ROLE_USER
→ Basic authenticated user ROLE_ADMIN
→ Full accessIn the User
entity (generated by make:user
):
// src/Entity/User.php
#[ORM\Column(type: 'json')]
private array $roles = [];
public function getRoles(): array
{
$roles = $this->roles;
$roles[] = 'ROLE_USER'; // Every user has ROLE_USER by default
return array_unique($roles);
}
Edit a user in the database:
UPDATE user SET roles = '["ROLE_ADMIN"]' WHERE id = 1;
// src/Controller/RegistrationController.php
$user->setRoles(['ROLE_USER']); // Default role
$user->setRoles(['ROLE_ADMIN', 'ROLE_USER']);
security.yaml
# config/packages/security.yaml
security:
access_control:
- { path: ^/admin, roles: ROLE_ADMIN }
- { path: ^/profile, roles: ROLE_USER }
// src/Controller/AdminController.php
use Symfony\Component\Security\Http\Attribute\IsGranted;
#[IsGranted('ROLE_ADMIN')]
public function adminDashboard(): Response
{
return $this->render('admin/dashboard.html.twig');
}
{% if is_granted('ROLE_ADMIN') %}
<a href="/admin">Admin Panel</a>
{% endif %}
Sometimes, roles aren’t enough (e.g., "Can this user edit this post?"). For fine-grained control, use Voters.
php bin/console make:voter
Name it PostVoter
.
Edit src/Security/Voter/PostVoter.php
:
protected function supports(string $attribute, mixed $subject): bool
{
return in_array($attribute, ['EDIT', 'DELETE']) && $subject instanceof Post;
}
protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool
{
$user = $token->getUser();
if (!$user instanceof User) return false;
$post = $subject;
return match ($attribute) {
'EDIT' => $user === $post->getAuthor() || in_array('ROLE_ADMIN', $user->getRoles()),
'DELETE' => in_array('ROLE_ADMIN', $user->getRoles()),
default => false,
};
}
#[IsGranted('EDIT', subject: 'post')]
public function edit(Post $post): Response
{
// Only the author or admin can edit
}
Define role hierarchy in security.yaml
:
security:
role_hierarchy:
ROLE_ADMIN: [ROLE_USER, ROLE_MODERATOR]
ROLE_MODERATOR: [ROLE_USER]
Now:
ROLE_MODERATOR
and ROLE_USER
. ROLE_USER
.$this->isGranted('ROLE_ADMIN'); // Returns true/false
$user = new User();
$user->setRoles(['ROLE_ADMIN']);
$this->client->loginUser($user);
🔹 Always use ROLE_
prefix (Symfony convention).
🔹 Prefer voters over multiple roles for complex rules.
🔹 Never store sensitive logic in Twig (handle in PHP).
🔹 Use $this->denyAccessUnlessGranted()
for quick checks.
You’ve now mastered Symfony’s role and permission system!
✅ Defined roles and restricted routes
✅ Created custom permissions with voters
✅ Used role hierarchy for inheritance
➡️ Try API tokens for stateless auth (lexik/jwt-authentication-bundle
)
➡️ Explore Symfony ACL for advanced permissions
Transform from beginner to Laravel expert with our personalized Coaching Class starting June 20, 2025. Limited enrollment ensures focused attention.
1-hour personalized coaching
Build portfolio applications
Industry-standard techniques
Interview prep & job guidance
Complete your application to secure your spot
Thank you for your interest in our Laravel mentorship program. We'll contact you within 24 hours with next steps.
No comments yet. Be the first to comment!
Please log in to post a comment:
Sign in with Google