Symfony2 AJAX Login
David's answer is good, but it's lacking a little detail for newbs - so this is to fill in the blanks.
In addition to creating the AuthenticationHandler you'll need to set it up as a service using the service configuration in the bundle where you created the handler. The default bundle generation creates an xml file, but I prefer yml. Here's an example services.yml file:
#src/Vendor/BundleName/Resources/config/services.ymlparameters: vendor_security.authentication_handler: Vendor\BundleName\Handler\AuthenticationHandlerservices: authentication_handler: class: %vendor_security.authentication_handler% arguments: [@router] tags: - { name: 'monolog.logger', channel: 'security' }
You'd need to modify the DependencyInjection bundle extension to use yml instead of xml like so:
#src/Vendor/BundleName/DependencyInjection/BundleExtension.php$loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));$loader->load('services.yml');
Then in your app's security configuration you set up the references to the authentication_handler service you just defined:
# app/config/security.ymlsecurity: firewalls: secured_area: pattern: ^/ anonymous: ~ form_login: login_path: /login check_path: /login_check success_handler: authentication_handler failure_handler: authentication_handler
namespace YourVendor\UserBundle\Handler;use Symfony\Component\HttpFoundation\Response;use Symfony\Component\HttpFoundation\RedirectResponse;use Symfony\Bundle\FrameworkBundle\Routing\Router;use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;use Symfony\Component\HttpFoundation\Request;use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface;use Symfony\Component\Security\Core\Exception\AuthenticationException;class AuthenticationHandlerimplements AuthenticationSuccessHandlerInterface, AuthenticationFailureHandlerInterface{ private $router; public function __construct(Router $router) { $this->router = $router; } public function onAuthenticationSuccess(Request $request, TokenInterface $token) { if ($request->isXmlHttpRequest()) { // Handle XHR here } else { // If the user tried to access a protected resource and was forces to login // redirect him back to that resource if ($targetPath = $request->getSession()->get('_security.target_path')) { $url = $targetPath; } else { // Otherwise, redirect him to wherever you want $url = $this->router->generate('user_view', array( 'nickname' => $token->getUser()->getNickname() )); } return new RedirectResponse($url); } } public function onAuthenticationFailure(Request $request, AuthenticationException $exception) { if ($request->isXmlHttpRequest()) { // Handle XHR here } else { // Create a flash message with the authentication error message $request->getSession()->setFlash('error', $exception->getMessage()); $url = $this->router->generate('user_login'); return new RedirectResponse($url); } }}
If you want the FOS UserBundle form error support, you must use:
$request->getSession()->set(SecurityContext::AUTHENTICATION_ERROR, $exception);
instead of:
$request->getSession()->setFlash('error', $exception->getMessage());
In the first answer.
(of course remember about the header: use Symfony\Component\Security\Core\SecurityContext;)