Deny Access in the Controller

Keep on Learning!

If you liked what you've learned so far, dive in!
Subscribe to get access to this tutorial plus
video, code and script downloads.

Start your All-Access Pass
Buy just this tutorial for $12.00

With a Subscription, click any sentence in the script to jump to that part of the video!

Login Subscribe

There are two main places where you can deny access. The first we just learned about: access_control in security.yaml:

security:
... lines 2 - 40
access_control:
- { path: ^/admin, roles: ROLE_ADMIN }
... lines 43 - 44

It's simple - just a regular expression and a role. It's the best way to protect entire areas of your site - like everything under /admin with ROLE_ADMIN.

I do use access controls for things like that. But, most of the time, I prefer to control access at a more granular level. Open CommentAdminController. Most of the time, I deny access right inside the controller.

To test this out - let's comment-out our access control:

security:
... lines 2 - 40
access_control:
# - { path: ^/admin, roles: ROLE_ADMIN }
... lines 43 - 44

Back in CommentAdminController, how can we deny access here? Simple: $this->denyAccessUnlessGranted() and pass this a role: ROLE_ADMIN:

... lines 1 - 10
class CommentAdminController extends Controller
{
... lines 13 - 15
public function index(CommentRepository $repository, Request $request, PaginatorInterface $paginator)
{
$this->denyAccessUnlessGranted('ROLE_ADMIN');
... lines 19 - 32
}
}

That's it. Move over and refresh!

Nice! Try changing it to ROLE_USER:

... lines 1 - 10
class CommentAdminController extends Controller
{
... lines 13 - 15
public function index(CommentRepository $repository, Request $request, PaginatorInterface $paginator)
{
$this->denyAccessUnlessGranted('ROLE_USER');
... lines 19 - 32
}
}

Access granted! I love it!

IsGranted Annotation

But wait, there's more! As simple as this is, I like to use annotations. Check this out: delete the denyAccessUnlessGranted() code. Instead, above the method, add @IsGranted() to use an annotation that comes from SensioFrameworkExtraBundle: a bundle that we installed a long time ago via composer require annotations. In double quotes, pass ROLE_ADMIN:

... lines 1 - 6
use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
... lines 8 - 11
class CommentAdminController extends Controller
{
/**
... line 15
* @IsGranted("ROLE_ADMIN")
*/
public function index(CommentRepository $repository, Request $request, PaginatorInterface $paginator)
{
... lines 20 - 32
}
}

Nice! Try it: refresh!

Access Denied by controller annotation

Pretty sweet. I know not everyone will love using annotations for this. So, if you don't love it, use the PHP version. No problem.

Protecting an Entire Controller Class

Oh, but the annotation does have one superpower. In addition to putting @IsGranted above a controller method, you can also put it above the controller class. Above CommmentAdminController, add @IsGranted("ROLE_ADMIN"):

... lines 1 - 6
use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
... lines 8 - 11
/**
* @IsGranted("ROLE_ADMIN")
*/
class CommentAdminController extends Controller
{
... lines 17 - 35
}

Now, every method inside of this controller... which is only one right now, will require this role. When you refresh... yep! Same error. That is an awesome way to deny access.

We know how to make sure a user has a role. But, how can we simply make sure a user is logged in, regardless of roles? Let's find out next - and - create our first admin users.

Leave a comment!

What PHP libraries does this tutorial use?

// composer.json
{
    "require": {
        "php": "^7.1.3",
        "ext-iconv": "*",
        "composer/package-versions-deprecated": "^1.11", // 1.11.99
        "knplabs/knp-markdown-bundle": "^1.7", // 1.7.0
        "knplabs/knp-paginator-bundle": "^2.7", // v2.8.0
        "knplabs/knp-time-bundle": "^1.8", // 1.8.0
        "nexylan/slack-bundle": "^2.0,<2.2.0", // v2.0.0
        "php-http/guzzle6-adapter": "^1.1", // v1.1.1
        "sensio/framework-extra-bundle": "^5.1", // v5.2.0
        "stof/doctrine-extensions-bundle": "^1.3", // v1.3.0
        "symfony/asset": "^4.0", // v4.1.4
        "symfony/console": "^4.0", // v4.1.4
        "symfony/flex": "^1.0", // v1.9.10
        "symfony/framework-bundle": "^4.0", // v4.1.4
        "symfony/lts": "^4@dev", // dev-master
        "symfony/orm-pack": "^1.0", // v1.0.6
        "symfony/security-bundle": "^4.0", // v4.1.4
        "symfony/serializer-pack": "^1.0", // v1.0.1
        "symfony/twig-bundle": "^4.0", // v4.1.4
        "symfony/web-server-bundle": "^4.0", // v4.1.4
        "symfony/yaml": "^4.0", // v4.1.4
        "twig/extensions": "^1.5" // v1.5.2
    },
    "require-dev": {
        "doctrine/doctrine-fixtures-bundle": "^3.0", // 3.0.2
        "easycorp/easy-log-handler": "^1.0.2", // v1.0.7
        "fzaninotto/faker": "^1.7", // v1.8.0
        "symfony/debug-bundle": "^3.3|^4.0", // v4.1.4
        "symfony/dotenv": "^4.0", // v4.1.4
        "symfony/maker-bundle": "^1.0", // v1.7.0
        "symfony/monolog-bundle": "^3.0", // v3.3.0
        "symfony/phpunit-bridge": "^3.3|^4.0", // v4.1.4
        "symfony/profiler-pack": "^1.0", // v1.0.3
        "symfony/var-dumper": "^3.3|^4.0" // v4.1.4
    }
}