1

I'm having an error:

"The token storage contains no authentication token. One possible reason may be that there is no firewall configured for this URL.

Which is caused by denyAccessUnlessGranted() added to a controller. It happens on test environment as there is security: false. Is there a mechanism to handle an environment in such a case or what should I do with it?

Trace:

0 /backend/vendor/symfony/framework-bundle/Controller/ControllerTrait.php(179): Symfony\Component\Security\Core\Authorization\AuthorizationChecker->isGranted('read', Object(App\Entity\Company))
1 /backend/vendor/symfony/framework-bundle/Controller/ControllerTrait.php(192): Symfony\Bundle\FrameworkBundle\Controller\AbstractController->isGranted('read', Object(App\Entity\Company))
2 /backend/src/Controller/CompanyController.php(125): Symfony\Bundle\FrameworkBundle\Controller\AbstractController->denyAccessUnlessGranted('read', Object(App\Entity\Company))
3 /backend/vendor/symfony/http-kernel/HttpKernel.php(150): App\Controller\CompanyController->cget(Object(Symfony\Component\HttpFoundation\Request), Object(App\Service\CompanyService))
4 /backend/vendor/symfony/http-kernel/HttpKernel.php(67): Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object(Symfony\Component\HttpFoundation\Request), 1)
5 /backend/vendor/symfony/http-kernel/Kernel.php(198): Symfony\Component\HttpKernel\HttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
6 /backend/public/index.php(37): Symfony\Component\HttpKernel\Kernel->handle(Object(Symfony\Component\HttpFoundation\Request))
7 {main}"
Roman Newaza
  • 11,405
  • 11
  • 58
  • 89
  • 1
    You could add a firewall with security enabled and `anonymous: ~` to allow access without logging in, but the security system being enabled. Instead of no token you should get the AnonmousToken instead. – dbrumann Feb 06 '19 at 12:04

1 Answers1

2

Why do you need to use security false in test environment. If you do this and you use denyAccessUnlessGranted() in your application you will get the result you mentioned. To fix this you have to use a try catch witch leaves you with 2 options, neither of them being a good one.

denyAccessUnlessGranted trows 2 types o exceptions that you need to catch

  • \LogicException
  • AuthenticationCredentialsNotFoundException

And this are the two options I mentioned

  1. you suppress the exceptions and let the script to run as nothing happened. If you do this you will not test your application security configuration, and even worse, if you take this code that suppresses the exceptions into your production environment, some production configuration mistake can leave your secured areas unprotected.

  2. You throw AccessDeniedException when you catch this exceptions. This will prevent access to areas in case of bad configuration in production environment of you app, but doing this will make this parts of the app inaccessible in test environment and i don't think you want that.

The security component of the application is as much of a part of your applications as every other business feature. It should be active on every environment and configured identically. The only difference between your test, dev or prod environment should be in the parameters file (things like where are the users stored).

Hope this helps, Alexandru Cosoi

Alexandru Cosoi
  • 1,000
  • 5
  • 9
  • Well, for now, I didn't want to handle Authentication for functional tests in an API once Voter was added - that's why I asked to disable it. I thought there is some other way of handling this issue, something like tweaking a configuration or so. And I came up with using `if(($this->container->get('security.token_storage'))->getToken()) { $this->denyAccessUnlessGranted('read', new Company); }` to solve it. – Roman Newaza Feb 06 '19 at 13:50
  • That will do it, but unit testing a controller without the security active is only testing part of your controller and the controller will behave in a different manner on your production environment. That can result in security bugs slipping by the unit tests. Anyway glad you got your issue resolved. Good luck and happy coding. – Alexandru Cosoi Feb 07 '19 at 13:17
  • If you really need to unit test this without security active, in the future you should maybe consider creating mocks for AuthorizationChecker and other security services that are used in your application, so that there is no need to alter the code in order for it to run on both environments and also doing this will allow you to unit test the security part of your controllers using different mocks. – Alexandru Cosoi Feb 07 '19 at 13:24
  • Well, this is functional test so I can't mock it. Thanks anyway. – Roman Newaza Feb 08 '19 at 13:29