Skip to content

Commit

Permalink
Make admin force users to reset 2FA tokens
Browse files Browse the repository at this point in the history
  • Loading branch information
Christopher Mühl committed Jan 5, 2018
1 parent dd6d7db commit 8ac8a50
Show file tree
Hide file tree
Showing 9 changed files with 85 additions and 31 deletions.
33 changes: 19 additions & 14 deletions src/Controller/BackendEnterTFACode.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,25 @@ public function __construct()

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

$this->template = new BackendTwoFactorTemplate('be_2fa_loginform');
}

protected function handleInput()
{
if (\Input::post('FORM_SUBMIT') == 'tl_2fa_code') {
$secret = $this->user->tfaSecret;
$code = \Input::post('tfa_code');

if (TwoFactorFactory::verifyCode($secret, $code)) {
$session->set('2fa_required', false);

$this->redirect('contao/main.php');
} else {
$this->template->incorrect = $GLOBALS['TL_LANG']['tl_user']['tfa_exception_invalid'];
}
}
}
/**
* Run the controller and parse the two-factor template
*
Expand All @@ -24,25 +41,13 @@ public function __construct()
public function run()
{
$session = \Session::getInstance();
$template = new BackendTwoFactorTemplate('be_2fa_loginform');

if (!$session->get('2fa_required')) {
$this->redirect('contao/main.php');
}

if (\Input::post('FORM_SUBMIT') == 'tl_2fa_code') {
$secret = $this->user->tfaSecret;
$code = \Input::post('tfa_code');

if (TwoFactorFactory::verifyCode($secret, $code)) {
$session->set('2fa_required', false);

$this->redirect('contao/main.php');
} else {
$template->incorrect = $GLOBALS['TL_LANG']['tl_user']['tfa_exception_invalid'];
}
}
$this->handleInput();

return $template->getResponse();
return $this->template->getResponse();
}
}
9 changes: 6 additions & 3 deletions src/Controller/BackendSetupTFA.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,20 @@ public function __construct()
$this->secret = $this->auth->createSecret();
}

protected function checkInput()
protected function handleInput()
{
if (\Input::post('tfa_secret')) {
$this->secret = \Input::post('tfa_secret');
}

if (\Input::post('FORM_SUBMIT') == 'tl_2fa_setup') {
if (TwoFactorFactory::verifyCode($this->secret, \Input::post('tfa_code'))) {
// Save secret for user.

// Save the user's new secret.
$this->user->tfaSecret = $this->secret;
$this->user->tfaChange = '';
$this->user->save();

// Redirect back to backend index
$this->redirect('/contao/main.php');
} else {
$this->template->incorrect = $GLOBALS['TL_LANG']['tl_user']['tfa_exception_invalid'];
Expand All @@ -49,6 +50,8 @@ public function run()
$this->redirect('/contao/main.php');
}

$this->handleInput();

$this->template->imageUrl = $this->auth->getQrCodeImageAsDataUri($this->user->email, $this->secret, 200);
$this->template->secret = $this->secret;

Expand Down
11 changes: 8 additions & 3 deletions src/EventListener/RequestListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use Contao\TwoFactorAuthTemplate;
use Contao\Controller;
use Contao\Session;
use Contao\BackendUser;

class RequestListener
{
Expand Down Expand Up @@ -57,9 +58,13 @@ public function onKernelRequest(GetResponseEvent $event)
}

// Force a user to set up 2FA
$user = $this->tokenStorage->getToken()->getUser();

if (TwoFactorFactory::tfaSetupRequired($user) && $event->getRequest()->get('_route') != 'contao_backend_set_tfa') {
$token = $this->tokenStorage->getToken();
if (!$token) {
return;
}

$user = $token->getUser();
if ($user instanceof BackendUser && TwoFactorFactory::tfaSetupRequired($user) && $event->getRequest()->get('_route') != 'contao_backend_set_tfa') {
Controller::redirect('/contao/tfa/set');
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace Contao;

class TwoFactorSaveListener extends \Backend
class TwoFactorFieldListener extends \Backend
{
/**
* {@inheritdoc}
Expand All @@ -20,7 +20,7 @@ public function __construct()
* @param string $value The secret that is trying to be saved
* @return string The secret that will be persisted to the database
*/
public function save($value)
public function saveSecret($value)
{
// Return an empty string if the user wishes to deactivate 2FA.
if ($this->Input->post('deactivate_tfa')) {
Expand All @@ -34,4 +34,12 @@ public function save($value)

return $value;
}

public function saveForceChangeField($value, $dataContainer)
{
var_dump($value);
die();

return $value;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

use DieSchittigs\TwoFactorAuth\TwoFactorFactory;

class TwoFactorWidget extends \Widget
class TwoFactorSecretWidget extends \Widget
{
/**
* {@inheritdoc}
Expand Down
5 changes: 4 additions & 1 deletion src/Resources/contao/config/config.php
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
<?php

$GLOBALS['BE_FFL']['tfaSecret'] = 'TwoFactorWidget';
$GLOBALS['BE_FFL']['tfaSecret'] = 'TwoFactorSecretWidget';
$GLOBALS['BE_FFL']['tfaReset'] = 'TwoFactorResetWidget';

$GLOBALS['TL_HOOKS']['storeFormData'][] = ['TwoFactorFieldListener', 'store'];
32 changes: 25 additions & 7 deletions src/Resources/contao/dca/tl_user.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
'inputType' => 'tfaSecret',
'sql' => "varchar(64) NOT NULL default ''",
'save_callback' => [
['TwoFactorSaveListener', 'save'],
['TwoFactorSaveListener', 'saveSecret'],
],
];

Expand All @@ -15,9 +15,27 @@

// Add the tfaChange field to the tl_user table.
$GLOBALS['TL_DCA']['tl_user']['fields']['tfaChange'] = [
'label' => &$GLOBALS['TL_LANG']['tl_user']['tfaChange'],
'excluded' => true,
'inputType' => 'checkbox',
'filter' => true,
'sql' => "char(1) NOT NULL default ''",
];
'label' => &$GLOBALS['TL_LANG']['tl_user']['tfaChange'],
'inputType' => 'checkbox',
'excluded' => true,
'filter' => true,
'sql' => "char(1) NOT NULL default ''",
'eval' => ['tl_class' => 'w50']
];

// Add the tfaChange field to the tl_user table.
$GLOBALS['TL_DCA']['tl_user']['fields']['tfaReset'] = [
'label' => &$GLOBALS['TL_LANG']['tl_user']['tfaReset'],
'inputType' => 'checkbox',
'excluded' => true,
'filter' => true,
'sql' => "char(1) NOT NULL default ''",
'eval' => ['tl_class' => 'w50'],
'save_callback' => [
['TwoFactorSaveListener', 'saveForceChangeField'],
],
];

foreach ($GLOBALS['TL_DCA']['tl_user']['palettes'] as &$palette) {
$palette = str_replace('{admin_legend}', '{tfa_title:hide},tfaChange,tfaReset;{admin_legend}', $palette);
}
6 changes: 6 additions & 0 deletions src/Resources/contao/languages/de/tl_user.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@
$GLOBALS['TL_LANG']['tl_user']['tfa_deactivate'] = 'Zwei-Faktor-Authentifizierung deaktivieren';
$GLOBALS['TL_LANG']['tl_user']['tfa_deactivate_explanation'] = 'Zur Bestätigung bitte rechts den aktuellen Code eingeben.';

$GLOBALS['TL_LANG']['tl_user']['tfaChange'][0] = 'Zwei-Faktor Aktualisierung notwendig';
$GLOBALS['TL_LANG']['tl_user']['tfaChange'][1] = 'Zwingt den Benutzer, seine Zwei-Faktor-Authentifizierung bei der nächsten Anmeldung neu zu initialisieren.';

$GLOBALS['TL_LANG']['tl_user']['tfaReset'][0] = 'Zwei-Faktor-Einstellung zurücksetzen';
$GLOBALS['TL_LANG']['tl_user']['tfaReset'][1] = 'Setzt die Einstellungen des Nutzers zurück und entfernt die Zwei-Faktor-Authentifizierung von seinem Account.';

$GLOBALS['TL_LANG']['tl_user']['tfa_explanation'] = 'Um die Zwei-Faktor-Authentifizierung für Ihren Account zu aktivieren, scannen Sie bitte diesen QR-Code mit einer kompatiblen App wie dem <strong>Google Authenticator</strong> (verfügbar für iOS und Android) und geben Sie danach den generierten Code ein.';
$GLOBALS['TL_LANG']['tl_user']['tfa_activated'] = 'Sie haben die Zwei-Faktor-Authentifizierung bereits aktiviert. Bitte halten Sie Ihre Authenticator-App bereit, wenn Sie sich zukünftig in Contao einloggen.';
$GLOBALS['TL_LANG']['tl_user']['tfa_token'] = 'Von App generierter Code';
Expand Down
6 changes: 6 additions & 0 deletions src/Resources/contao/languages/en/tl_user.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@
$GLOBALS['TL_LANG']['tl_user']['tfa_deactivate'] = 'Deactivate Two-Factor Authentication';
$GLOBALS['TL_LANG']['tl_user']['tfa_deactivate_explanation'] = 'To verify please type in the current code.';

$GLOBALS['TL_LANG']['tl_user']['tfaChange'][0] = 'Force two-factor reset';
$GLOBALS['TL_LANG']['tl_user']['tfaChange'][1] = 'Make the user reset his two-factor authentication upon the next login.';

$GLOBALS['TL_LANG']['tl_user']['tfaReset'][0] = 'Reset Two-Factor Settings';
$GLOBALS['TL_LANG']['tl_user']['tfaReset'][1] = 'Resets the two-factor authentication settings of this user, disabling 2FA for him.';

$GLOBALS['TL_LANG']['tl_user']['tfa_explanation'] = 'To activate two-factor authentication for your account please scan the QR code with a compatible app such as <strong>Google Authenticator</strong> (available for iOS and Android) and type in the generated code afterwards.';
$GLOBALS['TL_LANG']['tl_user']['tfa_activated'] = 'You have already activated two-factor authentication. Please keep your authenticator app at the ready when you log into Contao in the future.';
$GLOBALS['TL_LANG']['tl_user']['tfa_token'] = 'Code generated by your app';

0 comments on commit 8ac8a50

Please sign in to comment.