Symfony2 Ajax Login

Symfony2 : AJAX request : How to handle authentication when needed?

Here is a solution (see here for details) :

Security :

firewalls:
main:
pattern: ^/
anonymous: true
provider: fos_userbundle
entry_point: fbn_user.login_entry_point
#...
access_control:
- { path: ^/(fr|en)/bookmark/manage, role: ROLE_USER }

Services :

services:

fbn_user.login_entry_point:
class: FBN\UserBundle\EventListener\LoginEntryPoint
arguments: [ @router ]

Service class :

namespace FBN\UserBundle\EventListener;

use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\JsonResponse;

/**
* When the user is not authenticated at all (i.e. when the security context has no token yet),
* the firewall's entry point will be called to start() the authentication process.
*/

class LoginEntryPoint implements AuthenticationEntryPointInterface
{
protected $router;

public function __construct($router)
{
$this->router = $router;
}

/**
* This method receives the current Request object and the exception by which the exception
* listener was triggered.
*
* The method should return a Response object
*/
public function start(Request $request, AuthenticationException $authException = null)
{
if ($request->isXmlHttpRequest()) {

return new JsonResponse('',401);

}

return new RedirectResponse($this->router->generate('fos_user_security_login'));
}
}

jQuery :

$(function() {
$('#bookmark').click(function() {
// DATA PROCESSING
$.ajax({
type: 'POST',
url: Routing.generate('fbn_guide_manage_bookmark'),
data : xxxx, // SOME DATA,
success: function(data) {
// DO THE STUFF
},
error: function(jqXHR, textStatus, errorThrown) {
switch (jqXHR.status) {
case 401:
var redirectUrl = Routing.generate('fos_user_security_login');
window.location.replace(redirectUrl);
break;
case 403: // (Invalid CSRF token for example)
// Reload page from server
window.location.reload(true);
}
},
});
});
});

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.yml

parameters:
vendor_security.authentication_handler: Vendor\BundleName\Handler\AuthenticationHandler

services:
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.yml

security:
firewalls:
secured_area:
pattern: ^/
anonymous: ~
form_login:
login_path: /login
check_path: /login_check
success_handler: authentication_handler
failure_handler: authentication_handler

Symfony2 Login redirect after ajax request

You can force your security to always redirect to target path instead of checking referer:

firewalls:
secured_area:
form_login:
always_use_default_target_path: true
default_target_path: /userProfilePage

P.S. You should read documentation better

How to login using ajax in Symfony 2?

I made it work by creating a LoginListener

PS: If someone wants to explain how to do that, I will mark that as the correct answer.

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

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));
}
}


Related Topics



Leave a reply



Submit