Skip to content

Commit

Permalink
Refactored to throw exceptions instead of immediate actions
Browse files Browse the repository at this point in the history
Added ValidateAuthenticationFilter
Added stack of exceptions
  • Loading branch information
SilverFire committed Aug 4, 2017
1 parent 89ee1fa commit c82ddcc
Show file tree
Hide file tree
Showing 8 changed files with 158 additions and 15 deletions.
8 changes: 4 additions & 4 deletions src/Module.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
namespace hiqdev\yii2\mfa;

use hiqdev\yii2\mfa\base\Totp;
use hiqdev\yii2\mfa\exceptions\IpNotAllowedException;
use hiqdev\yii2\mfa\exceptions\TotpVerificationFailedException;
use Yii;
use yii\di\Instance;
use yii\helpers\StringHelper;
Expand Down Expand Up @@ -87,8 +89,7 @@ public function validateIps(IdentityInterface $identity)
return;
}

Yii::$app->response->redirect('/mfa/allowed-ips/not-allowed-ip');
Yii::$app->end();
throw new IpNotAllowedException();
}

public function validateTotp(IdentityInterface $identity)
Expand All @@ -100,7 +101,6 @@ public function validateTotp(IdentityInterface $identity)
return;
}

Yii::$app->response->redirect('/mfa/totp/check');
Yii::$app->end();
throw new TotpVerificationFailedException();
}
}
12 changes: 10 additions & 2 deletions src/behaviors/ValidateMfaBehavior.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

namespace hiqdev\yii2\mfa\behaviors;

use hiqdev\yii2\mfa\exceptions\AuthenticationException;
use hiqdev\yii2\mfa\Module;
use Yii;
use yii\base\Event;
use yii\web\User;
Expand All @@ -25,10 +27,16 @@ public function events()

public function beforeLogin(Event $event)
{
/** @var Module $module */
$module = Yii::$app->getModule('mfa');
$identity = $event->identity;
$module->setHalfUser($identity);
$module->validateIps($identity);
$module->validateTotp($identity);

try {
$module->validateIps($identity);
$module->validateTotp($identity);
} catch (AuthenticationException $e) {
$e->redirect();
}
}
}
23 changes: 14 additions & 9 deletions src/controllers/AllowedIpsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

namespace hiqdev\yii2\mfa\controllers;

use hiqdev\yii2\mfa\exceptions\AuthenticationException;
use hiqdev\yii2\mfa\filters\ValidateAuthenticationFilter;
use Yii;
use yii\filters\AccessControl;

Expand All @@ -28,18 +30,21 @@ public function behaviors()
return $this->goHome();
},
'rules' => [
// ? - guest
[
'actions' => ['not-allowed-ip'],
'roles' => ['?'],
'allow' => true,
],
// @ - authenticated
[
'actions' => ['other'],
'roles' => ['@'],
'allow' => true,
],
'matchCallback' => function ($action) {
$filter = new ValidateAuthenticationFilter();
try {
$filter->validateAuthentication(Yii::$app->user->identity);
} catch (AuthenticationException $e) {
// Show this page only when user have problems with IP
return true;
}

return false;
}
]
],
],
];
Expand Down
10 changes: 10 additions & 0 deletions src/exceptions/AuthenticationException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace hiqdev\yii2\mfa\exceptions;

use yii\base\Exception;

abstract class AuthenticationException extends Exception
{
abstract public function redirect();
}
19 changes: 19 additions & 0 deletions src/exceptions/IpNotAllowedException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

namespace hiqdev\yii2\mfa\exceptions;

use Yii;

class IpNotAllowedException extends AuthenticationException
{
public function getName()
{
return 'IP address is not allowed';
}

public function redirect()
{
Yii::$app->response->redirect('/mfa/allowed-ips/not-allowed-ip');
Yii::$app->end();
}
}
19 changes: 19 additions & 0 deletions src/exceptions/NotAuthenticatedException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

namespace hiqdev\yii2\mfa\exceptions;

use Yii;

class NotAuthenticatedException extends AuthenticationException
{
public function getName()
{
return 'You are not authenticated';
}

public function redirect()
{
Yii::$app->response->redirect('/site/login');
Yii::$app->end();
}
}
19 changes: 19 additions & 0 deletions src/exceptions/TotpVerificationFailedException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

namespace hiqdev\yii2\mfa\exceptions;

use Yii;

class TotpVerificationFailedException extends AuthenticationException
{
public function getName()
{
return 'Token verification failed';
}

public function redirect()
{
Yii::$app->response->redirect('/mfa/totp/check');
Yii::$app->end();
}
}
63 changes: 63 additions & 0 deletions src/filters/ValidateAuthenticationFilter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?php

namespace hiqdev\yii2\mfa\filters;

use Closure;
use hiqdev\yii2\mfa\exceptions\AuthenticationException;
use hiqdev\yii2\mfa\exceptions\NotAuthenticatedException;
use hiqdev\yii2\mfa\Module;
use Yii;
use yii\base\ActionFilter;
use yii\web\IdentityInterface;

class ValidateAuthenticationFilter extends ActionFilter
{
/**
* @var Closure
*/
public $denyCallback;

/**
* @var bool
*/
public $invert = false;

public function beforeAction($action)
{
if (Yii::$app->user->isGuest) {
return $this->denyAccess(new NotAuthenticatedException());
}

$identity = Yii::$app->user->identity;
try {
$this->validateAuthentication($identity);
} catch (AuthenticationException $e) {
return $this->denyAccess($e);
}

return true;
}

public function validateAuthentication(IdentityInterface $identity)
{
/** @var Module $module */
$module = Yii::$app->getModule('mfa');

$module->validateIps($identity);
$module->validateTotp($identity);
}

/**
* @param AuthenticationException $exception
* @return mixed
*/
protected function denyAccess($exception)
{
if ($this->denyCallback instanceof Closure) {
return call_user_func($this->denyCallback, $exception);
}

$exception->redirect();
}

}

0 comments on commit c82ddcc

Please sign in to comment.