Add two factor authentication

This commit is contained in:
Frederic Guillot
2015-03-31 22:48:14 -04:00
parent 5d393ed996
commit abeeba7167
32 changed files with 615 additions and 22 deletions

View File

@@ -176,6 +176,7 @@ abstract class Base
if (! $this->acl->isPublicAction($controller, $action)) {
$this->handleAuthentication();
$this->handle2FA($controller, $action);
$this->handleAuthorization($controller, $action);
$this->session['has_subtask_inprogress'] = $this->subtask->hasSubtaskInProgress($this->userSession->getId());
@@ -199,6 +200,26 @@ abstract class Base
}
}
/**
* Check 2FA
*
* @access public
*/
public function handle2FA($controller, $action)
{
$controllers = array('twofactor', 'user');
$actions = array('code', 'check', 'logout');
if ($this->userSession->has2FA() && ! $this->userSession->check2FA() && ! in_array($controller, $controllers) && ! in_array($action, $actions)) {
if ($this->request->isAjax()) {
$this->response->text('Not Authorized', 401);
}
$this->response->redirect($this->helper->url('twofactor', 'code', array('user_id' => $user['id'])));
}
}
/**
* Check page access and authorization
*

View File

@@ -0,0 +1,137 @@
<?php
namespace Controller;
use Otp\Otp;
use Otp\GoogleAuthenticator;
use Base32\Base32;
/**
* Two Factor Auth controller
*
* @package controller
* @author Frederic Guillot
*/
class Twofactor extends User
{
/**
* Only the current user can access to 2FA settings
*
* @access private
*/
private function checkCurrentUser(array $user)
{
if ($user['id'] != $this->userSession->getId()) {
$this->forbidden();
}
}
/**
* Index
*
* @access public
*/
public function index()
{
$user = $this->getUser();
$this->checkCurrentUser($user);
$label = $user['email'] ?: $user['username'];
$this->response->html($this->layout('twofactor/index', array(
'user' => $user,
'qrcode_url' => $user['twofactor_activated'] == 1 ? GoogleAuthenticator::getQrCodeUrl('totp', $label, $user['twofactor_secret']) : '',
'key_url' => $user['twofactor_activated'] == 1 ? GoogleAuthenticator::getKeyUri('totp', $label, $user['twofactor_secret']) : '',
)));
}
/**
* Enable/disable 2FA
*
* @access public
*/
public function save()
{
$user = $this->getUser();
$this->checkCurrentUser($user);
$values = $this->request->getValues();
if (isset($values['twofactor_activated']) && $values['twofactor_activated'] == 1) {
$this->user->update(array(
'id' => $user['id'],
'twofactor_activated' => 1,
'twofactor_secret' => GoogleAuthenticator::generateRandom(),
));
}
else {
$this->user->update(array(
'id' => $user['id'],
'twofactor_activated' => 0,
'twofactor_secret' => '',
));
}
$this->session->flash(t('User updated successfully.'));
$this->response->redirect($this->helper->url('twofactor', 'index', array('user_id' => $user['id'])));
}
/**
* Test 2FA
*
* @access public
*/
public function test()
{
$user = $this->getUser();
$this->checkCurrentUser($user);
$otp = new Otp;
$values = $this->request->getValues();
if (! empty($values['code']) && $otp->checkTotp(Base32::decode($user['twofactor_secret']), $values['code'])) {
$this->session->flash(t('The two factor authentication code is valid.'));
}
else {
$this->session->flashError(t('The two factor authentication code is not valid.'));
}
$this->response->redirect($this->helper->url('twofactor', 'index', array('user_id' => $user['id'])));
}
/**
* Check 2FA
*
* @access public
*/
public function check()
{
$user = $this->getUser();
$this->checkCurrentUser($user);
$otp = new Otp;
$values = $this->request->getValues();
if (! empty($values['code']) && $otp->checkTotp(Base32::decode($user['twofactor_secret']), $values['code'])) {
$this->session['2fa_validated'] = true;
$this->session->flash(t('The two factor authentication code is valid.'));
$this->response->redirect($this->helper->url('app', 'index'));
}
else {
$this->session->flashError(t('The two factor authentication code is not valid.'));
$this->response->redirect($this->helper->url('twofactor', 'code'));
}
}
/**
* Ask the 2FA code
*
* @access public
*/
public function code()
{
$this->response->html($this->template->layout('twofactor/check', array(
'title' => t('Check two factor authentication code'),
)));
}
}