Insights

How To Add An AJAX Login Form To A Symfony2 Project

Adding an AJAX login form to a Symfony2 project is quite easy but it covers few things. The first thing is that the Symfony firewall handles authentications by sending a form to the route defined in the apps/config/security.yml as the check path for the firewall. So, if you want to login using AJAX, a form needs to be posted to that route along with few fields like username, password, remember me and if you have enabled CSRF for your form then the csrf token field. The firewall will then allow the user to login or reject it and will redirect to the login route or any of the routes set in the app/config/security.yml file.

The steps involved are:

Firstly, create a class that can handle authentication. It must implement the AuthenticationSuccessHandlerInterface and AuthenticationFailureHandlerInterface. The methods i.e onAuthenticationSuccess and onAuthenticationFailure will be called to handle authentication. If you wish to check the request to find out if its an AJAX call simply you need to call the isXmlHttpRequest() method and if it is an AJAX call you’ve to return a JSON response. If it isn’t then you’ve to return a RedirectResponse to appropriate destination. In the onAuthenticationFailure method you can even return a error message which will be displayed to the user.

// AuthenticationHandler.php
 
namespace path\to\your\class;
 
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;
use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface;
 
class AuthenticationHandler implements AuthenticationSuccessHandlerInterface, AuthenticationFailureHandlerInterface
{
    private $router;
    private $session;
 
    /**
     * Constructor
     *
     * @author     Joe Sexton <[email protected]>
     * @param     RouterInterface $router
     * @param     Session $session
     */
    public function __construct( RouterInterface $router, Session $session )
    {
        $this->router  = $router;
        $this->session = $session;
    }    /**
     * onAuthenticationSuccess
      *
     * @author     Joe Sexton <[email protected]>
     * @param     Request $request
     * @param     TokenInterface $token
     * @return     Response
     */
    public function onAuthenticationSuccess( Request $request, TokenInterface $token )
    {
        // if AJAX login
        if ( $request->isXmlHttpRequest() ) {
 
            $array = array( 'success' => true ); // data to return via JSON
            $response = new Response( json_encode( $array ) );
            $response->headers->set( 'Content-Type', 'application/json' );
 
            return $response;
 
        // if form login
        } else {
 
            if ( $this->session->get('_security.main.target_path' ) ) {
 
                $url = $this->session->get( '_security.main.target_path' );
 
            } else {
 
                $url = $this->router->generate( 'home_page' );
 
            } // end if
 
            return new RedirectResponse( $url );
 
        }
    }
 
    /**
     * onAuthenticationFailure
     *
     * @author     Joe Sexton <[email protected]>
     * @param     Request $request
     * @param     AuthenticationException $exception
     * @return     Response
     */
     public function onAuthenticationFailure( Request $request, AuthenticationException $exception )
    {
        // if AJAX login
        if ( $request->isXmlHttpRequest() ) {
 
            $array = array( 'success' => false, 'message' => $exception->getMessage() ); // data to return via JSON
            $response = new Response( json_encode( $array ) );
            $response->headers->set( 'Content-Type', 'application/json' );
 
            return $response;
 / if form login
        } else {
 
            // set authentication exception to session
            $request->getSession()->set(SecurityContextInterface::AUTHENTICATION_ERROR, $exception);
 
            return new RedirectResponse( $this->router->generate( 'login_route' ) );
        }
    }
}

Next step is you’ve to register a service for this class  in your bundle’s Resources/config/services.yml file.

# Resources/config/services.yml
 
acme.security.authentication_handler:
        class: path\to\your\class\AuthenticationHandler
        public: false
        arguments:
            - @router
            - @session

The final step is you’ve to register this service as the handler for authentication success and failure in the app/config/security.yml file. You’ve to simply add the success handler and failure handler parameters to your firewall configuration.

# app/config/security.yml
 
security:
    firewalls:
        main:
            form_login:
                check_path:      security_check_route
                success_handler: acme.security.authentication_handler
                failure_handler: acme.security.authentication_handler

So, what keeps you waiting? Contact us today for Symfony Development Services…!

Banner
In search for strategic sessions?
Let us understand your business thoroughly and help you strategies your digital product..
Book a session