Merge branch '2fa-channels-email-sms' of https://github.com/acordeddu/yii2-usuario into acordeddu-2fa-channels-email-sms

This commit is contained in:
Lorenzo Milesi
2022-08-12 09:46:32 +02:00
51 changed files with 1498 additions and 126 deletions

View File

@ -20,6 +20,9 @@ use Da\User\Service\SocialNetworkAccountConnectService;
use Da\User\Service\SocialNetworkAuthenticateService;
use Da\User\Traits\ContainerAwareTrait;
use Da\User\Traits\ModuleAwareTrait;
use Da\User\Validator\TwoFactorEmailValidator;
use Da\User\Validator\TwoFactorTextMessageValidator;
use Da\User\Model\User;
use Yii;
use yii\authclient\AuthAction;
use yii\base\InvalidConfigException;
@ -30,6 +33,7 @@ use yii\filters\VerbFilter;
use yii\web\Controller;
use yii\web\Response;
use yii\widgets\ActiveForm;
use yii\helpers\ArrayHelper;
class SecurityController extends Controller
{
@ -212,13 +216,31 @@ class SecurityController extends Controller
return $this->goBack();
}
}
}
else{
$module = Yii::$app->getModule('user');
$validators = $module->twoFactorAuthenticationValidators;
$credentials=Yii::$app->session->get('credentials');
$login= $credentials['login'];
$user = User::findOne(['email'=>$login]);
if( $user==null){
$user = User::findOne(['username'=>$login]);
}
$tfType = $user->getAuthTfType();
$class = ArrayHelper::getValue($validators,$tfType.'.class');
$object = $this
->make($class, [$user, null, $this->module->twoFactorAuthenticationCycles]);
$object->generateCode();
}
return $this->render(
'confirm',
[
'model' => $form,
'module' => $this->module,
'module' => $this->module
]
);
}

View File

@ -30,10 +30,14 @@ use Da\User\Search\SessionHistorySearch;
use Da\User\Service\EmailChangeService;
use Da\User\Service\SessionHistory\TerminateUserSessionsService;
use Da\User\Service\TwoFactorQrCodeUriGeneratorService;
use Da\User\Service\TwoFactorEmailCodeGeneratorService;
use Da\User\Service\TwoFactorSmsCodeGeneratorService;
use Da\User\Traits\ContainerAwareTrait;
use Da\User\Traits\ModuleAwareTrait;
use Da\User\Validator\AjaxRequestModelValidator;
use Da\User\Validator\TwoFactorCodeValidator;
use Da\User\Validator\TwoFactorEmailValidator;
use Da\User\Validator\TwoFactorTextMessageValidator;
use Yii;
use yii\base\DynamicModel;
use yii\filters\AccessControl;
@ -115,6 +119,7 @@ class SettingsController extends Controller
'two-factor',
'two-factor-enable',
'two-factor-disable',
'two-factor-mobile-phone'
],
'roles' => ['@'],
],
@ -392,7 +397,7 @@ class SettingsController extends Controller
public function actionConfirm($id, $code)
{
$user = $this->userQuery->whereId($id)->one();
if ($user === null || MailChangeStrategyInterface::TYPE_INSECURE === $this->module->emailChangeStrategy) {
throw new NotFoundHttpException();
}
@ -448,20 +453,29 @@ class SettingsController extends Controller
public function actionTwoFactor($id)
{
/**
*
*
* @var User $user
*/
$choice=Yii::$app->request->post('choice');
/** @var User $user */
$user = $this->userQuery->whereId($id)->one();
if (null === $user) {
throw new NotFoundHttpException();
}
$uri = $this->make(TwoFactorQrCodeUriGeneratorService::class, [$user])->run();
return $this->renderAjax('two-factor', ['id' => $id, 'uri' => $uri]);
switch($choice)
{
case 'google-authenticator':
$uri = $this->make(TwoFactorQrCodeUriGeneratorService::class, [$user])->run();
return $this->renderAjax('two-factor', ['id' => $id, 'uri' => $uri]);
case 'email':
$emailCode = $this->make(TwoFactorEmailCodeGeneratorService::class, [$user])->run();
return $this->renderAjax('two-factor-email', ['id' => $id, 'code' => $emailCode]);
case 'sms':
// get mobile phone, if exists
$mobilePhone=$user->getAuthTfMobilePhone();
$smsCode = $this->make(TwoFactorSmsCodeGeneratorService::class, [$user])->run();
return $this->renderAjax('two-factor-sms', ['id' => $id, 'code' => $smsCode, 'mobilePhone' => $mobilePhone] );
}
}
public function actionTwoFactorEnable($id)
@ -482,18 +496,21 @@ class SettingsController extends Controller
];
}
$code = Yii::$app->request->get('code');
$module = Yii::$app->getModule('user');
$validators = $module->twoFactorAuthenticationValidators;
$choice = Yii::$app->request->get('choice');
$codeDurationTime = ArrayHelper::getValue($validators,$choice.'.codeDurationTime', 300);
$class = ArrayHelper::getValue($validators,$choice.'.class');
$success = $this
->make(TwoFactorCodeValidator::class, [$user, $code, $this->module->twoFactorAuthenticationCycles])
->validate();
$success = $success && $user->updateAttributes(['auth_tf_enabled' => '1']);
$object = $this
->make($class, [$user, $code, $this->module->twoFactorAuthenticationCycles]);
$success = $object->validate();
$success = $success && $user->updateAttributes(['auth_tf_enabled' => '1','auth_tf_type' => $choice]);
$message = $success? $object->getSuccessMessage():$object->getUnsuccessMessage($codeDurationTime);
return [
'success' => $success,
'message' => $success
? Yii::t('usuario', 'Two factor authentication successfully enabled.')
: Yii::t('usuario', 'Verification failed. Please, enter new code.')
'message' => $message
];
}
@ -578,4 +595,39 @@ class SettingsController extends Controller
$account->delete();
$this->trigger(SocialNetworkConnectEvent::EVENT_AFTER_DISCONNECT, $event);
}
public function actionTwoFactorMobilePhone($id)
{
Yii::$app->response->format = Response::FORMAT_JSON;
/**
*
*
* @var User $user
*/
$user = $this->userQuery->whereId($id)->one();
if (null === $user) {
return [
'success' => false,
'message' => Yii::t('usuario', 'User not found.')
];
}
$mobilePhone = Yii::$app->request->get('mobilephone');
$currentMobilePhone = $user->getAuthTfMobilePhone();
$success=false;
if($currentMobilePhone==$mobilePhone){
$success=true;
}else{
$success = $user->updateAttributes(['auth_tf_mobile_phone' => $mobilePhone]);
$success = $success && $this->make(TwoFactorSmsCodeGeneratorService::class, [$user])->run();
}
return [
'success' => $success,
'message' => $success
? Yii::t('usuario', 'Mobile phone number successfully enabled.')
: Yii::t('usuario', 'Error while enabling SMS two factor authentication. Please reload the page.'),
];
}
}