30

I get the following error when I try to reach app/example on symfony demo

Error: The Symfony\Component\Security\Core\SecurityContext class is deprecated since version 2.6 and will be removed in 3.0. Use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage or Symfony\Component\Security\Core\Authorization\AuthorizationChecker instead.

The server is returning the right answer with a 200 status code though.

I've found nothing on Google about it. Has anybody encounter this error before and/or know how to fix it ?

Harijoe
  • 1,771
  • 1
  • 16
  • 27
  • Disable the warning with: http://stackoverflow.com/questions/28850809/disable-deprecated-warning-in-symfony-2-7 – Cerad Apr 13 '15 at 13:40
  • I have this same issue, caused by FOSUserBundle which is still using the deprecated call and doesn't seem to be updated even in the 2.0dev version. – Tom Oct 20 '15 at 08:53

3 Answers3

53

Explanation

Starting with Symfony 2.6 the SecurityContext got split into the TokenStorage and the AuthorizationChecker (see: Symfony Blog - "New in Symfony 2.6: Security component improvements").

The main reason for this was to prevent circular reference which occurred quite often when injecting the SecurityContext into your own services.

Solution

The change itself is 100% backwards compatible (as stated in the linked blog post), you just need to rewrite how you accessed the SecurityContext.

// Symfony 2.5
$user = $this->get('security.context')->getToken()->getUser();
// Symfony 2.6
$user = $this->get('security.token_storage')->getToken()->getUser();

// Symfony 2.5
if (false === $this->get('security.context')->isGranted('ROLE_ADMIN')) { ... }
// Symfony 2.6
if (false === $this->get('security.authorization_checker')->isGranted('ROLE_ADMIN')) { ... }

You can simply try to find the culprit by doing a text-search for security.context or SecurityContext in your source code (including the vendor directory).

But as you stated that you're using vanilla Symfony 2.6 it seems that it simply uses some soon to be deprecated methods. So you might simply use this...

Workaround

As Symfony does it's deprecation by triggering E_USER_DEPRECATED errors, you can simply disable them when booting your Symfony AppKernel:

// app/AppKernel.php
class AppKernel extends Kernel
{
    public function __construct($environment, $debug) {
        // Keep error reporting like it was and disable only deprecation warnings.
        error_reporting(error_reporting() & (-1 ^ E_DEPRECATED));
        // ...
    }
}

I personally like the deprecation warnings, because Symfony's changelogs tend to give very detailed information on how you need to change your code to support future versions of Symfony and the deprecation warnings normally are triggered months before the methods are actually deprecated.

flu
  • 14,307
  • 8
  • 74
  • 71
  • Thanks for your very clear anwser. I like deprecated warnings too, the problem was they were spoiling my newRelic monitoring. – Harijoe Apr 16 '15 at 12:38
  • Flu could you please advise how one may use annotation security system with new classes? – Abdel5 Aug 09 '15 at 08:50
  • 1
    @Abdel5 I think it would be better to put this into a question on your own as this question here is solely about getting rid of the error the OP was having trouble with. – flu Aug 10 '15 at 12:13
  • Thank u @flu. You saved my several hours! – sadiq Aug 14 '19 at 19:29
1

It's not a proper error, just a warning.

A deprecated class is a class that is planned to be removed in future releases (of Symfony, in this case).

It suggest you to stop using it, and points you to the newer (and substitutes) class, TokenStorage and AuthorizationChecker, that will take completly over to do the same tasks.

Alessandro Lai
  • 2,254
  • 2
  • 24
  • 32
  • The thing is, I've just forked and deployed the [symfony-standard](https://github.com/symfony/symfony-standard) so I have no idea where the deprecated class is used. In addition, even though it's only a warning, it completely spoils my new relic monitoring : that's why I want to get rid of it. – Harijoe Apr 13 '15 at 13:27
  • So, that's completly normal, there's some deprecated code inside Symfony. You could try Symfony 2.7 or put an ignore under New Relic. – Alessandro Lai Apr 13 '15 at 13:30
  • What do you mean by "trying Symfony 2.7" ? The symfony-standard repo is already based on Symfony 2.7, isn't it ? – Harijoe Apr 13 '15 at 13:35
  • But still, I've got these deprecated warnings. Is it possible to configure Symfony to avoid those ? – Harijoe Apr 13 '15 at 14:07
  • You could configure your php.ini to ignore them – Alessandro Lai Apr 13 '15 at 14:16
0

It gets so annoying to see that warning. At the same time you don't want to turn off the warnings. So I thought maybe it's useful to give an example of changing your code to get rid of it. Here's how I changed HWIOAuthBundle's OAuthUtils class to do so. First, I changed /vendor/hwi/oauth-bundle/HWI/Bundle/OAuthBundle/Resources/config/oauth.html from this:

<service id="hwi_oauth.security.oauth_utils" class="%hwi_oauth.security.oauth_utils.class%">
    <argument type="service" id="security.http_utils" />
    <argument type="service" id="security.context" />
    <argument>%hwi_oauth.connect%</argument>
</service>

to this:

<service id="hwi_oauth.security.oauth_utils" class="%hwi_oauth.security.oauth_utils.class%">
    <argument type="service" id="security.http_utils" />
    <argument type="service" id="security.authorization_checker" />
    <argument>%hwi_oauth.connect%</argument>
</service>

Now we have to change it in the /vendor/hwi/oauth-bundle/HWI/Bundle/OAuthBundle/Security/OAuthUtils class from this:

    use Symfony\Component\Security\Core\SecurityContextInterface;
    ...

    /**
     * @var SecurityContextInterface
     */
    private $securityContext;

    /**
     * @param HttpUtils                $httpUtils
     * @param SecurityContextInterface $securityContext
     * @param boolean                  $connect
     */
    public function __construct(HttpUtils $httpUtils, SecurityContextInterface $securityContext, $connect)
    {
        $this->httpUtils       = $httpUtils;
        $this->securityContext = $securityContext;
        $this->connect         = $connect;
    }

to this:

    use Symfony\Component\Security\Core\Authorization\AuthorizationChecker;
    ...

    /**
     * @var AuthorizationChecker
     */
    private $authorizationChecker;

    /**
     * @param HttpUtils                $httpUtils
     * @param AuthorizationChecker     $authorizationChecker
     * @param boolean                  $connect
     */
    public function __construct(HttpUtils $httpUtils, AuthorizationChecker $authorizationChecker, $connect)
    {
        $this->httpUtils            = $httpUtils;
        $this->authorizationChecker = $authorizationChecker;
        $this->connect              = $connect;
    }

Then I made changes where the securityContext was used. Replaced it with authorizationChecker.

    public function getAuthorizationUrl(Request $request, $name, $redirectUrl = null, array $extraParameters = array())
    {
        $resourceOwner = $this->getResourceOwner($name);
        if (null === $redirectUrl) {
            if (!$this->connect || !$this->authorizationChecker->isGranted('IS_AUTHENTICATED_REMEMBERED')) {
                $redirectUrl = $this->httpUtils->generateUri($request, $this->ownerMap->getResourceOwnerCheckPath($name));
            } else {
                $redirectUrl = $this->getServiceAuthUrl($request, $resourceOwner);
            }
        }

        return $resourceOwner->getAuthorizationUrl($redirectUrl, $extraParameters);
    }

The reason of replacing SecurityContext with AuthorizationChecker is because only isGranted method is used in this case. Maybe you could replace it with TokenStorage or use both AuthorizationChecker and TokenStorage if you needed for your case.