How can I check user role in code of a symfony2 Service? Should I simply send a user roles object to a Service or is there solution which allows me to do the check from Service level?
-
What do you want to check? Do you want to check if user has a role? Or user has an access to some operation? – xurshid29 Jul 04 '15 at 14:46
-
My service defines available tags to be added to certain entity's. Adding certain tags to entities requires user having given role. I want in service to check if given tag may be added by given user (taking into account roles that he has). Thus I need to have access to information on user role in my service. – Abdel5 Jul 04 '15 at 15:39
5 Answers
The other answers have you pass the container instead of the authorization checker. While they work they create a tight dependancy on the container making it harder to migrate your code to other projects. Instead you should only pass the authorization checker.
Here is an example taken from the symfony docs.
app/config/services.yml
services:
newsletter_manager:
class: "AppBundle\Newsletter\NewsletterManager"
arguments: ["@security.authorization_checker"]
src/Appbundle/Newsletter/NewsletterManager.php
namespace AppBundle\Newsletter;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
// ...
class NewsletterManager
{
protected $authorizationChecker;
public function __construct(AuthorizationCheckerInterface $authorizationChecker)
{
$this->authorizationChecker = $authorizationChecker;
}
public function sendNewsletter()
{
if (false === $this->authorizationChecker->isGranted('ROLE_NEWSLETTER_ADMIN')) {
throw new AccessDeniedException();
}
// ...
}
// ...
}
-
4Imho this should be accepted answer. Passing the container to a service is considered bad practice. – Sander Toonen Dec 04 '15 at 20:48
Assuming that:
you inject
security.context
in your servicepublic function __construct(SecurityContext $securityContext) { $this->securityContext = $securityContext; }
you are using FosUserBundle
I understood correctly your question :-)
you should be able to do:
$token = $this->securityContext->getToken();
if (empty($token)) {
return [];
}
$user = $token->getUser();
if (empty($user)) {
return [];
}
$roles = $user->getRoles();
Updates 2016/11/28
- Answer updated to pass the specific dependency instead of the whole container, as that is a bad practice (see comment by @Shady)
- Note that starting from Symfony 2.6, SecurityContext is deprecated, you should use TokenStorage instead.

- 4,644
- 5
- 37
- 48

- 4,190
- 1
- 19
- 30
-
Thanks for the clue to pass the container to service. That was the thing that I needed. – Abdel5 Jul 05 '15 at 07:04
-
EDIT @Mick - DO NOT EVER DO THE FOLLOWING
See here for more info.
I think it would be much easier if you implemented an isGranted function in the User entity:
Class User implements UserInterface {
...
public function isGranted($role)
{
return in_array($role, $this->getRoles());
}
}
You can now easily check for granted roles in every layer of your application. In PHP:
$user->isGranted("USER_ADMIN")
Or in Twig:
user.granted("USER_ADMIN")
If you need to check a role for the current user, you can do this in Twig:
app.user.granted("USER_ADMIN")
Note: the variable "app" is globally defined.
Note 2: this code may throw an exception if you use it outside the secured area of your app, since app.user would be NULL.

- 30,759
- 16
- 111
- 130

- 1,150
- 1
- 8
- 11
-
I am using `FriendsOfSymfony/FOSUserBundle`. The question is how may I access information about roles in service? – Abdel5 Jul 04 '15 at 16:19
-
5In most cases, people will define a hierarchical role structure. The problem with this approach is that inherited roles are not taken into account. Better is to inject the ``security.authorization_checker`` service. – Sander Toonen Dec 05 '15 at 17:57
The answer is that to be able to use Symfony2 classes in service you need to provide service with a container.
Service definition:
services:
/.../:
class: /.../
arguments: ['@service_container']
Service file:
use Symfony\Component\DependencyInjection\ContainerInterface as Container;
class globalHelper {
private $container;
public function __construct(Container $container) {
$this->container = $container;
}

- 1,112
- 3
- 16
- 39
-
1Injecting the whole service container is considered bad practice. [(source 1)](http://richardmiller.co.uk/2011/05/19/when-dependency-injection-goes-wrong/) [(source 2)](http://stackoverflow.com/questions/23931321/in-symfony2-why-is-it-a-bad-idea-to-inject-the-service-container-rather-than-i) Unless you have a really good reason, inject the services that you need instead. – Sander Toonen Dec 05 '15 at 18:08
BE CAREFUL...
Be very careful about what you are doing when it comes to Security.. DO NOT DO THIS.
This is because, you need to understand that the TokenInterface is not the same as UserInterface
.
TokenInterface is the interface for the user authentication information.
You must use it - If you don't have the token made available in your current service, use the SecurityContext
or the AccessDecisionManager
.
Note: In Symfony > 2.6, some improvements were made, and SecurityContext
was deprecated, and split into TokenStorage
and AuthorizationChecker
. So, you can go ahead and use AuthorizationChecker
now.
Look! Even FOSUserBundle implementation talks about it:
/**
* Never use this to check if this user has access to anything!
*
* Use the SecurityContext, or an implementation of AccessDecisionManager
* instead, e.g.
*
* $securityContext->isGranted('ROLE_USER');
*
* @param string $role
* @return Boolean
*/
function hasRole($role);
Look how it works, look at things like getRoles, Hierarchical roles for example.
ROLES in the database are not to be trusted - if you get a User object from the database, and use your getRoles()
or even worse the special isGranted($role)
you have created, they will NOT have the roles you expect your user to have.
This should be your bible, and now you can understand the differences between:
1 $user->getRoles()
array(2) {
[0]=> string(10) "ROLE_ADMIN"
[1]=> string(9) "ROLE_USER"
}
2 $this->token->getRoles()
array(2) {
[0]=> object(Symfony\Component\Security\Core\Role\Role)
(1) { ["role":"Symfony\Component\Security\Core\Role\Role":private]=> string(10) "ROLE_ADMIN" }
[1]=> object(Symfony\Component\Security\Core\Role\Role)
(1) { ["role":"Symfony\Component\Security\Core\Role\Role":private]=> string(22) "ROLE_ALLOWED_TO_SWITCH" }
[2]=> object(Symfony\Component\Security\Core\Role\Role)
(1) { ["role":"Symfony\Component\Security\Core\Role\Role":private]=> string(9) "ROLE_USER" }
}
3 $this->token->getUser->getRoles()
array(2) {
[0]=> string(10) "ROLE_ADMIN"
[1]=> string(22) "ROLE_ALLOWED_TO_SWITCH"
[2]=> string(9) "ROLE_USER"
}
When you have security.yml
security:
role_hierarchy:
ROLE_ADMIN: [ROLE_ALLOWED_TO_SWITCH]

- 30,759
- 16
- 111
- 130