Search code examples
phpajaxsymfonysymfony4symfony-security

What’s the proper way to handle an AJAX call behind Symfony 4 firewall?


I need to send AJAX requests to parts of my website where my user is authenticated. Unfortunately, Symfony 4 rejects those requests (and sends them to login page) as it doesn’t detect it as authenticated access to my controller/route.

How do you make sure your ajax requests gets through Symfony 4 access control ? In my security.yaml i have configured the security as follow:

access_control:
    - { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/profile, roles: ROLE_USER }

I need to access /profile/update with an ajax call. How do I provide credentials to symfony?

Thanks!


Solution

  • Your controller method redirects the Ajax call to the login page, because your JS doesn't send credentials (read: cookies).

    If you're using fetch, use credentials:

    fetch(url, {
      credentials: "same-origin"
    }).then(...).catch(...);
    

    See https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials

    If you're using another way to create the Ajax call, please update your question with some JS code and let me know :).

    If you don't want to redirect the user to the login page when executing an XMLHttpRequest ('ajax'), use this listener to send a 403 response instead:

    class AjaxAuthenticationListener implements EventSubscriberInterface
    {
        public static function getSubscribedEvents()
        {
            return [
                KernelEvents::EXCEPTION => [
                    ['onCoreException', 10],
                ],
            ];
        }
    
        public function onCoreException(GetResponseForExceptionEvent $event)
        {
            $exception = $event->getException();
            $request   = $event->getRequest();
    
            if (! $request->isXmlHttpRequest()) {
                return;
            }
    
            if (! ($exception instanceof AuthenticationException) && ! ($exception instanceof AccessDeniedException)) {
                return;
            }
    
            $event->setResponse(new Response('No access', 403));
        }
    }