Skip to content

Commit

Permalink
Add translation, backend templates and authentication logic
Browse files Browse the repository at this point in the history
  • Loading branch information
Christopher Mühl committed Jan 4, 2018
1 parent dbb5cfd commit 9c45544
Show file tree
Hide file tree
Showing 6 changed files with 191 additions and 0 deletions.
27 changes: 27 additions & 0 deletions src/Resources/contao/classes/TwoFactorAuthentication.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

namespace Contao;

use RobThree\Auth\TwoFactorAuth;

class TwoFactorAuthentication extends \Backend
{
public function __construct()
{
$this->import('BackendUser', 'user');

parent::__construct();
}

public static function generateAuthenticator()
{
$title = $GLOBALS['TL_CONFIG']['websiteTitle'];
return new TwoFactorAuth($title);
}

public static function verifyCode($secret, $code)
{
$auth = self::generateAuthenticator();
return $auth->verifyCode($secret, $code);
}
}
51 changes: 51 additions & 0 deletions src/Resources/contao/classes/TwoFactorWidget.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

namespace Contao;

use RobThree\Auth\TwoFactorAuth;

class TwoFactorWidget extends \Widget
{
/**
* Submit user input
* @var boolean
*/
protected $blnSubmitInput = true;

protected $strTemplate = 'be_2fa_field';

public function __construct($arrAttributes = null)
{
$this->import('BackendUser', 'user');

parent::__construct($arrAttributes);
}

protected function validator($secret)
{
$code = $this->Input->post('tfaToken');

if (!TwoFactorAuthentication::verifyCode($secret, $code)) {
$this->addError($GLOBALS['TL_LANG']['tl_user']['tfa_exception_invalid']);
}

return parent::validator($secret);
}

public function parse()
{
$auth = TwoFactorAuthentication::generateAuthenticator();

// Only create a new secret, if it isn't already set.
$this->secret = $this->value ? $this->value : $auth->createSecret();
$this->imageUrl = $auth->getQrCodeImageAsDataUri($this->user->email, $this->secret, 200);
$this->tfaEnabled = (bool) $this->value;

return parent::parse();
}

public function generate()
{
return $this->parse();
}
}
7 changes: 7 additions & 0 deletions src/Resources/contao/languages/de/modules.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php

$GLOBALS['TL_LANG']['MOD']['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']['MOD']['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']['MOD']['tfa_token'] = 'Von App generierter Code';

$GLOBALS['TL_LANG']['MSC']['abort'] = 'Abbrechen';
4 changes: 4 additions & 0 deletions src/Resources/contao/languages/de/tl_user.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?php

$GLOBALS['TL_LANG']['tl_user']['tfa_title'] = 'Zwei-Faktor-Authentifizierung';
$GLOBALS['TL_LANG']['tl_user']['tfa_exception_invalid'] = 'Der eingegebene Code ist nicht gültig.';
32 changes: 32 additions & 0 deletions src/Resources/contao/templates/be_2fa_field.html5
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<div>
<div class="widget">
<?php if ($this->tfaEnabled): ?>
<p class="tl_info"><?= $GLOBALS['TL_LANG']['MOD']['tfa_activated']; ?></p>

<div class="w50 widget cbx">
<div id="ctrl_useCE" class="tl_checkbox_single_container"><input type="hidden" name="useCE" value=""><input type="checkbox" name="useCE" id="opt_useCE_0" class="tl_checkbox" value="1" checked="" onfocus="Backend.getScrollOffset()"> <label for="opt_useCE_0">Zwei-Faktor-Authentifizierung deaktivieren</label></div>
<p class="tl_help tl_tip" title="">Zur Bestätigung bitte rechts den aktuellen Code eingeben.</p>
</div>
<?php else: ?>
<p class="tl_info"><?= $GLOBALS['TL_LANG']['MOD']['tfa_explanation']; ?></p>

<div class="w50" style="height:auto;text-align:center;">
<img src="<?= $this->imageUrl ?>">
<input type="hidden" name="tfaSecret" value="<?= $this->secret ?>">
</div>
<?php endif; ?>

<div class="w50">
<h3>
<label for="ctrl_tfa_token" <?php if ($this->hasErrors()): ?> class="error"<?php endif; ?>>
<?= $GLOBALS['TL_LANG']['MOD']['tfa_token']; ?>
</label>
</h3>
<input class="tl_text" id="ctrl_tfa_token" name="tfaToken">
<?php if ($this->hasErrors()): ?>
<p class="tl_error tl_tip" title><?= $this->getErrorAsString() ?></p>
<?php endif; ?>
</div>
</div>

</div>
70 changes: 70 additions & 0 deletions src/Resources/contao/templates/be_2fa_loginform.html5
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<!DOCTYPE html>
<html lang="<?= $this->language ?>">
<head>

<meta charset="<?= $this->charset ?>">
<title><?= $this->title ?> - Contao Open Source CMS</title>
<base href="<?= $this->base ?>">
<meta name="generator" content="Contao Open Source CMS">
<meta name="viewport" content="width=device-width,initial-scale=1.0,shrink-to-fit=no">
<meta name="referrer" content="origin">
<meta name="robots" content="noindex,follow">

<link rel="stylesheet" href="<?php
$objCombiner = new Combiner();
$objCombiner->add('system/themes/'. $this->theme .'/fonts.css');
$objCombiner->add('system/themes/'. $this->theme .'/basic.css');
$objCombiner->add('system/themes/'. $this->theme .'/login.css');
echo $objCombiner->getCombinedFile();
?>">
<?= $this->stylesheets ?>

<script><?= $this->getLocaleString() ?></script>
<script src="<?php
$objCombiner = new Combiner();
$objCombiner->add('assets/mootools/js/mootools.min.js');
$objCombiner->add('bundles/contaocore/mootao.min.js');
$objCombiner->add('bundles/contaocore/core.min.js');
echo $objCombiner->getCombinedFile();
?>"></script>
<script><?= $this->getDateString() ?></script>
<?= $this->javascripts ?>

</head>
<body class="<?= $this->ua ?>">

<div id="container" class="cf">
<main id="main">
<form action="<?= $this->action ?>" class="tl_login_form" method="post">
<div class="formbody">
<input type="hidden" name="FORM_SUBMIT" value="tl_login">
<input type="hidden" name="REQUEST_TOKEN" value="<?= REQUEST_TOKEN ?>">
<h1><?= $this->headline ?></h1>
<div class="widget">
<input type="text" name="2fa_code" id="2fa_code" class="tl_text" value="<?= $this->curUsername ?>" autocapitalize="off" placeholder="<?= $this->f2a_code ?>" required>
</div>
<div class="submit_container cf">
<button type="submit" name="login" id="login" class="tl_submit"><?= $this->loginButton ?></button>
<a href="<?= $this->route('contao_backend_logout') ?>" class="footer_preview"><?= $this->feLink ?> ›</a>
</div>
</div>
</form>
</main>
<?= $this->messages ?>
</div>

<div class="tl_info" id="javascript">
<?= $this->jsDisabled ?>
</div>

<script>
window.addEvent('domready', function() {
if (parent.frames[0] && parent.frames[0].name == 'switch') {
parent.location.reload();
}
$('2fa_code').focus();
});
</script>

</body>
</html>

0 comments on commit 9c45544

Please sign in to comment.