I have a basic api that authenticates users using FOSOAuthServerBundle. Users can have ROLE_USER and ROLE_ADMIN roles. Based on FOSOAuthServerBundle docs, the default behavior is to use scopes as roles, so I've thought that when I have a regular user, the bundle would return scope: user
in the response, and when it's a admin user, would return scope: admin
. But it's not working like this. The bundle is returning whatever is configured in the supported_scopes
entry. Below is my config.yml
.
fos_oauth_server:
service:
options:
supported_scopes: user admin
My access_control
section in security.yml
is empty, and my firewalls
section is below:
firewalls:
users_create:
pattern: ^/v1/users
methods: [POST]
security: false
api:
pattern: ^/
security: true
fos_oauth: true
stateless: true
access_control:
# You can omit this if /api can be accessed both authenticated and anonymously
This way the bundle always return user admin
as scope, even if the user does not have the ROLE_ADMIN role.
{
"access_token": "ZGQ2ODE5ZjAzNTZkOWY0OWMyNmZmODE4MjcwZTJmYjExNzY0NzQxOTRmMzk4NzA2Mjc2NjIyZmY1ZDgwMzk4NA"
"expires_in": 3600
"token_type": "bearer"
"scope": "user admin"
"refresh_token": "NmM5ZGFmNzBiNTNjYmQzMTQ1MTk0ODJjOTAxMWU0YWIwMzM1MzgyODg4ZTAzNTI5ZTk2MDc3OGU2MTg0MWZiMA"
}
What I'm I missing? Isn't the user role attached to token scope? Is there any better way to know if my user is an admin or not?
From the doc, the default behaviour is to map scopes with roles. In your case, the roles would be ROLE_USER and ROLE_ADMIN.
Now to restrict usage, you'd edit your security.yml file somewhat like this:
# app/config/security.yml
security:
access_control:
- { path: ^/api/super/secured, role: ROLE_ADMIN }
- { path: ^/api/general, role: ROLE_USER }
To restrict access inside controller, you can use this:
if ($this->get('security.context')->isGranted('ROLE_ADMIN')) {
// the user has the ROLE_ADMIN role, so act accordingly
}
Again from the doc,
Now, clients will be able to pass a scope parameter when they request an access token.
Hope this helps.
UPDATE:
Look at this answer here to a similar question and this article on setting up FOSOAuthServerBundle . Pay close attention to the configuration part.
FOSOAuthServerBundle
authenticate your user, based on token, so you dont have to worry about scopes, it is a different thing then roles. Inside your controller you can get $this->getUser()
to get the current authenticated user. If this works then checking if isGranted
works as well.
http://symfony.com/doc/current/book/security.html
public function helloAction($name)
{
// The second parameter is used to specify on what object the role is tested.
$this->denyAccessUnlessGranted('ROLE_ADMIN', null, 'Unable to access this page!');
// Old way :
// if (false === $this->get('security.authorization_checker')->isGranted('ROLE_ADMIN')) {
// throw $this->createAccessDeniedException('Unable to access this page!');
// }
// ...
}
In case of $this->getUser()
doesnt work you will have to set fetch
to EAGER
on the AccessToken
entity.
class AccessToken extends BaseAccessToken
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\Client")
* @ORM\JoinColumn(nullable=false)
*/
protected $client;
/**
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\User", fetch="EAGER")
*/
protected $user;
}
There is an issue on github that dates back to 2013 for this. If you read that issue and follow the links you will eventually end up with the user Spomky creating his own library and Symfony bundle and being suggested as a maintainer of the FOSAuthServerBundle. It appears the FOS organisation will merge Spomky's work into the next major version of FOSOAuthServerBundle once it is stable.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With