Skip to content

Commit

Permalink
Add event listeners
Browse files Browse the repository at this point in the history
  • Loading branch information
Christopher Mühl committed Jan 4, 2018
1 parent 47c6ee7 commit f5e955c
Show file tree
Hide file tree
Showing 6 changed files with 152 additions and 2 deletions.
5 changes: 4 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@
"autoload": {
"psr-4": {
"DieSchittigs\\TwoFactorAuth\\": "src/"
}
},
"classmap": [
"src/Resources/contao/classes/"
]
},
"extra": {
"contao-manager-plugin": "DieSchittigs\\TwoFactorAuth\\ContaoManager\\Plugin"
Expand Down
2 changes: 1 addition & 1 deletion src/DependencyInjection/TwoFactorAuthExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@ class TwoFactorAuthExtension extends Extension
public function load(array $configs, ContainerBuilder $container)
{
$loader = new YamlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config'));
$loader->load('parameters.yml');
$loader->load('listener.yml');
}
}
42 changes: 42 additions & 0 deletions src/EventListener/InteractiveLoginListener.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

namespace DieSchittigs\TwoFactorAuth\EventListener;

use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use Contao\CoreBundle\Framework\ContaoFrameworkInterface;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Contao\User;

class InteractiveLoginListener
{
/**
* @var ContaoFrameworkInterface
*/
private $framework;

/**
* @var SessionInterface
*/
private $session;

public function __construct(ContaoFrameworkInterface $framework, SessionInterface $session)
{
$this->framework = $framework;
$this->session = $session;
}

public function onInteractiveLogin(InteractiveLoginEvent $event)
{
$user = $event->getAuthenticationToken()->getUser();

// Return if ...
// - we couldn't retrieve a user
// - the user doesn't have 2FA enabled
// - a frontend member tries to login (we currently only support Backend users)
if (!$user instanceof User || !$user->tfaSecret || TL_MODE == 'FE') {
return;
}

$this->session->set('2fa_required', true);
}
}
88 changes: 88 additions & 0 deletions src/EventListener/RequestListener.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
<?php

namespace DieSchittigs\TwoFactorAuth\EventListener;

use Contao\CoreBundle\Framework\ContaoFrameworkInterface;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpFoundation\Response;
use Contao\User;
use Contao\BackendTemplate;
use Contao\TwoFactorAuthentication;

class RequestListener
{
/**
* @var ContaoFrameworkInterface
*/
private $framework;

/**
* @var SessionInterface
*/
private $session;

/**
* @var TokenStorageInterface
*/
private $tokenStorage;

// TokenStorage
public function __construct(ContaoFrameworkInterface $framework, SessionInterface $session, TokenStorageInterface $tokenStorage)
{
$this->framework = $framework;
$this->session = $session;
$this->tokenStorage = $tokenStorage;
}

private function initializeFramework()
{
$this->framework->initialize();

\System::loadLanguageFile('default');
\System::loadLanguageFile('tl_user');
}

public function onKernelRequest(GetResponseEvent $event)
{
// If the session isn't running, or a 2FA token isn't required, return.
if (!$this->session->isStarted() || !$this->session->get('2fa_required')) {
return;
}

if ($_POST['FORM_SUBMIT'] == 'tl_login') {
$secret = $this->tokenStorage->getToken()->getUser()->tfaSecret;
$code = \Input::post('2fa_code');

if (TwoFactorAuthentication::verifyCode($secret, $code)) {
$this->session->set('2fa_required', false);
return;
}
}

$this->initializeFramework();

$template = new BackendTemplate('be_2fa_loginform');

$template->theme = \Backend::getTheme();
$template->base = \Environment::get('base');
$template->language = $GLOBALS['TL_LANGUAGE'];
$template->messages = \Message::generate();
$template->languages = \System::getLanguages(true); // backwards compatibility
$template->charset = \Config::get('characterSet');
$template->action = ampersand(\Environment::get('request'));
$template->userLanguage = $GLOBALS['TL_LANG']['tl_user']['language'][0];
$template->curLanguage = \Input::post('language') ?: str_replace('-', '_', $GLOBALS['TL_LANGUAGE']);
$template->curUsername = \Input::post('username') ?: '';
$template->loginButton = \StringUtil::specialchars($GLOBALS['TL_LANG']['MSC']['continue']);
$template->jsDisabled = $GLOBALS['TL_LANG']['MSC']['jsDisabled'];

$template->title = \StringUtil::specialchars(sprintf($GLOBALS['TL_LANG']['MSC']['loginTo'], \Config::get('websiteTitle')));
$template->headline = 'Zwei-Faktor-Authentifizierung';
$template->feLink = $GLOBALS['TL_LANG']['MSC']['abort'];
$template->f2a_code = 'Code';

$event->setResponse(Response::create($template->parse()));
}
}
17 changes: 17 additions & 0 deletions src/Resources/config/listener.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
services:
dieschittigs.twofactor.listener.interactive_login:
class: DieSchittigs\TwoFactorAuth\EventListener\InteractiveLoginListener
arguments:
- "@contao.framework"
- "@session"
tags:
- { name: kernel.event_listener, event: security.interactive_login, method: onInteractiveLogin, priority: 10 }

dieschittigs.twofactor.listener.request:
class: DieSchittigs\TwoFactorAuth\EventListener\RequestListener
arguments:
- "@contao.framework"
- "@session"
- "@security.token_storage"
tags:
- { name: kernel.event_listener, event: kernel.request, method: onKernelRequest, priority: -10 }
Empty file.

0 comments on commit f5e955c

Please sign in to comment.