Is there any sort of pre login event or similar?
So, there's no 'official' pre-login event. But thankfully it's not hard to set one up since Symfony2 is so extendable. The trick is to use your own service to handle authentication.
Symfony uses this class when using a login form:
Symfony\Component\Security\Http\Firewall\UsernamePasswordFormAuthenticationListener
If you override the security.authentication.listener.form.class
parameter (originally defined in Symfony\Bundle\SecurityBundle\Resources\config\security_listeners.xml
) you can use a custom listener that extends UsernamePasswordFormAuthenticationListener
.
All that's left to do is override the attemptAuthentication()
method to dispatch the custom event.
(Actually you also need to store the event dispatcher as a class property in __construct()
)
This method should work with other authentication methods - all you'd need to do is modify the appropriate listener (ie BasicAuthenticationListener
, X509AuthenticationListener
, etc.)
Symfony - Pre login event listener
Generally all login stuff in symfony is executed by a listener to the kernel.request
event, mostly within the Firewall
listener of the Symfony security component. I did not use the HWIOAuthBundle bundle yet, but it seems it also just uses the Symfony Security component.
If you just want to execute certain actions before the login/authentication happens, you only need to register an event listener to the kernel.request
with a higher priority than the Firewall
listener.
You can do that as described in the Symfony docs (Events and Event Listeners). First create your Event listener class in src/AppBundle/EventListener/YourListener.php
:
namespace AppBundle\EventListener;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
class YourListener
{
public function onKernelRequest(GetResponseEvent $event)
{
// do stuff
}
}
Then register your service in your app/config/services.yml
file:
services:
AppBundle\EventListener\YourListener:
tags:
- { name: kernel.event_listener, event: kernel.request, priority: 9 }
According to this page the Firewall has a priority of 8. So the priority of your event listener should be higher than that to be executed before the login happens (I used 9 in the example above).
FOSUserBundle - perform function upon initial login
I just had a look at this and it seems you can use an eventSubscriber to subscribe to the SecurityEvents::INTERACTIVE_LOGIN event to get where you need to be.
class RegistrationSubscriber implements EventSubscriberInterface
{
private $tokenStorage;
public function __construct(TokenStorage $tokenStorage)
{
$this->tokenStorage = $tokenStorage;
}
public static function getSubscribedEvents()
{
return [
SecurityEvents::INTERACTIVE_LOGIN => [
['lastLogin', 150],
],
];
}
public function lastLogin(InteractiveLoginEvent $event){
$user = $this->tokenStorage->getToken()->getUser();
if($user->getLastLogin() == null){
//Do something
}
}
In my testing on the first login $user->getLastLogin() is null so you can put any logic you need here.
How to make some security checks before the user will be granted to log-in (pre-login)?
To perform some pre/post-login checks (that means before/after the user authentication) one of the most simple and flexible solutions, offered by the Symfony framework, is to learn How to Create and Enable Custom User Checkers.
If you need more control and flexibility the best option is to learn How to Create a Custom Authentication System with Guard.
Take a look at the simple implementation example below:
security.yml
firewall_name:
guard:
authenticators:
- service_name_for_guard_authenticator
entry_point: service_name_for_guard_authenticator <-- important to add a default one (as described in the docs) if you have many custom authenticators (facebook...)
service.xml
<service id="service_name_for_guard_authenticator"
class="AppBundle\ExampleFolderName\YourGuardAuthClassName">
<argument type="service" id="router"/>
<argument type="service" id="security.password_encoder"/>
</service>
YourGuardAuthClassName.php
use Symfony\Component\Security\Guard\AbstractGuardAuthenticator;
use use Symfony\Bundle\FrameworkBundle\Routing\Router;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoder;
class YourGuardAuthClassName extends AbstractGuardAuthenticator
{
private $router;
private $passwordEncoder;
public function __construct(
Router $router,
UserPasswordEncoder $passwordEncoder)
{
$this->router = $router;
$this->passwordEncoder = $passwordEncoder;
}
public function start(Request $request, AuthenticationException $authException = null)
{
$response = new RedirectResponse($this->router->generate('your_user_login_route_name'));
return $response;
}
public function getCredentials(Request $request)
{
# CHECK IF IT'S THE CHECK LOGIN ROUTE
if ($request->attributes->get('_route') !== 'your_user_login_route_name'
|| !$request->isMethod('POST')) {
return null;
}
# GRAB ALL REQUEST PARAMETERS
$params = $request->request->all();
# SET LOGIN CREDENTIALS
return array(
'email' => $params['email'],
'password' => $params['password'],
);
}
public function getUser($credentials, UserProviderInterface $userProvider)
{
$email = $credentials['email'];
$user = $userProvider->loadUserByUsername($email);
if (! $user){
throw new UsernameNotFoundException();
}
return $user;
}
public function checkCredentials($credentials, UserInterface $user)
{
# YOU CAN ADD YOUR CHECKS HERE!
if (! $this->passwordEncoder->isPasswordValid($user, $credentials['password'])) {
throw new BadCredentialsException();
}
return true;
}
public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
{
# OYU CAN ALSO USE THE EXCEPTIONS TO ADD A FLASH MESSAGE (YOU HAVE TO INJECT YOUR OWN FLASH MESSAGE SERVICE!)
if ($exception instanceof UsernameNotFoundException){
$this->flashMessage->error('user.login.exception.credentials_invalid');
}
if ($exception instanceof BadCredentialsException){
$this->flashMessage->error('user.login.exception.credentials_invalid');
}
return new RedirectResponse($this->router->generate('your_user_login_route_name'));
}
public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
{
return new RedirectResponse($this->router->generate('your_success_login_route_name'));
}
public function supportsRememberMe()
{
return false;
}
}
Mixpanel - Linking pre login and post login events to user on android
As per MixPanel guidance events can be linked if alias is set first and then identifier.
//set alias when user signs up
MixpanelAPI mixpanelAPI = MixpanelAPI.getInstance(context, MixPanelConstants.MIX_PANEL_TOKEN);
mixpanelAPI.alias("myAlias", mixpanelAPI.getDistinctId());
//set identifier when user logs in
mixpanelAPI.identify("user.alias");
Alias is set when user performs registration, right? Mixpanel recommends to set Alias once during the life time of the user. However this guidance doesn't support linking of pre-login and post-login events if user doesn't perform registration and logins directly (Existing user scenario)
Related Topics
How to Pass a PHP Variable to Vue Component Instance in Laravel Blade
How to Display Special Characters in PHP
Transfer Variables Between PHP Pages
Is MySQLi_Real_Escape_String Safe
Mysqli Prepared Statement Column with Variable
Practical Zend_Acl + Zend_Auth Implementation and Best Practices
Best Way to Access Exchange Using PHP
PHP Include Causes White Space at the Top of the Page
PHP Strtotime +1 Month Behaviour
JavaScript Function Post and Call PHP Script
PHP Warning: Exec() Unable to Fork
How Does PHP Compare Strings with Comparison Operators
Is There a Built-In Function or Plugin to Handle Date Formatting in JavaScript
Leverage Browser Caching, How on Apache or .Htaccess
PHP Best Practices for User Authentication and Password Security