flga-8.x-1.x-dev/src/Form/FaceLoginGAuthForm.php
src/Form/FaceLoginGAuthForm.php
<?php
namespace Drupal\face_login_gauth\Form;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\face_login_gauth\FaceAuthSecretTrait;
use PragmaRX\Google2FA\Google2FA;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Aws\Rekognition\RekognitionClient;
use Drupal\Core\Session\AccountProxy;
use Drupal\user\UserDataInterface;
use Drupal\Core\Config\ConfigFactoryInterface;
/**
* Class FaceLoginGAuthForm.
*/
class FaceLoginGAuthForm extends FormBase {
use FaceAuthSecretTrait;
/**
* Drupal\Core\Entity\EntityTypeManagerInterface definition.
*
* @var entityTypeManager
*/
protected $entityTypeManager;
/**
* Drupal\Core\Session\AccountProxy definition.
*
* @var currentUser
*/
protected $currentUser;
/**
* Drupal\user\UserDataInterface definition.
*
* @var \Drupal\user\UserDataInterface
*/
protected $userData;
/**
* Drupal\Core\Config\ConfigFactoryInterface definition.
*
* @var Drupal\Core\Config\ConfigFactoryInterface
*/
protected $configFactory;
/**
* Constructs a new FaceLoginGAuthForm object.
*/
public function __construct(
EntityTypeManagerInterface $entity_type_manager,
AccountProxy $currentUser,
UserDataInterface $userData,
ConfigFactoryInterface $configFactory
) {
$this->entityTypeManager = $entity_type_manager;
$this->userStorage = $this->entityTypeManager->getStorage('user');
$this->currentUser = $currentUser;
$this->userData = $userData;
$this->configFactory = $configFactory;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('entity_type.manager'),
$container->get('current_user'),
$container->get('user.data'),
$container->get('config.factory')
);
}
/**
* {@inheritdoc}
*/
public function getFormId() {
return 'face_login_gauth_form';
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state) {
$form['webcam'] = [
'#markup' => '<div id="webcam"></div><a href="#" id="captur_image">Capture</a><div id="webcam_image"></div>',
];
$form['username'] = [
'#type' => 'textfield',
'#title' => $this->t('Username'),
'#maxlength' => 64,
'#size' => 64,
'#weight' => '0',
];
$form['code'] = [
'#type' => 'textfield',
'#title' => $this->t('Code'),
'#description' => $this->t('Google Authenticator Code.'),
'#maxlength' => 64,
'#size' => 64,
'#weight' => '0',
];
$form['target'] = [
'#type' => 'hidden',
'#value' => '',
];
$form['#validate'][] = '::validateFaces';
$form['#validate'][] = '::validateGauth';
$form['#attached']['library'][] = 'face_login_gauth/webcamjs';
$form['#attached']['library'][] = 'face_login_gauth/face_login_gauth';
$form['submit'] = [
'#type' => 'submit',
'#value' => $this->t('Submit'),
];
return $form;
}
/**
* {@inheritdoc}
*/
public function validateFaces(array &$form, FormStateInterface $form_state) {
$config = $this->configFactory
->get('face_login_gauth.facelogingauthconfig');
// Load user by username.
$accounts = $this->userStorage->loadByProperties(
['name' => $form_state->getValue('username')]
);
if (!empty($accounts)) {
$account = reset($accounts);
// Load user profile picture.
if ($account->user_picture->first()) {
$user_picture = $account->user_picture->first();
$target_id = $user_picture->getValue('target_id')['target_id'];
$image_profile = $this->entityTypeManager
->getStorage('file')->load($target_id);
// Webcam shot is saved in base64 string so need to
// decode that into image bytes.
$image_login = $form_state->getUserInput()['target'];
$image_login = base64_decode($image_login);
// If both images have been provided then proceed.
if ($image_profile) {
// Load the profile picture into image bytes.
$image_profile = file_get_contents($image_profile->getFileUri());
// Prepare some AWS config.
$options = [
'region' => $config->get('region'),
'version' => $config->get('version'),
'credentials' => [
'key' => $config->get('aws_key'),
'secret' => $config->get('aws_secret'),
],
];
try {
$client = new RekognitionClient($options);
$result = $client->compareFaces([
'SimilarityThreshold' => (float) $config->get('threshhold'),
'SourceImage' => [
'Bytes' => $image_profile,
],
'TargetImage' => [
'Bytes' => $image_login,
],
]);
if (count($result['FaceMatches']) == 0) {
$form_state->setErrorByName('form',
$this->t('Faces does not match.'));
}
else {
// Save the user account id to be used in submit handler.
$form_state->set('uid', $account->id());
}
}
catch (\Exception $e) {
$form_state->setErrorByName('form', $e->getMessage());
$form_state->setErrorByName('form',
$this->t('An error occurred.'));
}
}
}
}
else {
$form_state->setErrorByName('username',
$this->t('Username does not exist.'));
}
}
/**
* {@inheritdoc}
*/
public function validateGauth(array &$form, FormStateInterface $form_state) {
try {
$accounts = $this->userStorage->loadByProperties(['name' => $form_state->getValue('username')]);
if (!empty($accounts)) {
$account = reset($accounts);
$google2fa = new Google2FA();
$secret = $form_state->getValue('code');
$key = $this->getUserData('face_login_gauth', 'secret', $account->id(), $this->userData);
if ($google2fa->verifyKey($key, $secret) === FALSE) {
$form_state->setErrorByName('code', $this->t('Error code not matching.'));
}
}
else {
$form_state->setErrorByName('username', $this->t('Username does not exist.'));
}
}
catch (\Exception $e) {
$form_state->setErrorByName('code', $this->t('Error code not matching.'));
}
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
// Load the user account.
$account = $this->userStorage->load($form_state->get('uid'));
// Log the user in.
user_login_finalize($account);
// Redirect to user profile page.
$form_state->setRedirect('user.page');
}
}
