1
0
mirror of https://github.com/processwire/processwire.git synced 2025-08-22 14:23:05 +02:00

Upgrade the two-factor authentication system (Tfa) so that it now supports the ability to fingerprint and remember a user’s browser and other aspects, so that the user doesn't have to re-enter their TFA code on every login (optional).

This commit is contained in:
Ryan Cramer
2020-06-05 13:44:05 -04:00
parent 4c83f401ba
commit d99abac75c
5 changed files with 740 additions and 40 deletions

View File

@@ -16,3 +16,19 @@ ul.Inputfields .InputfieldSubmit {
clear: both;
}
#wrap_tfa_remember {
border: none;
outline: none;
padding: 0;
}
#wrap_tfa_remember .InputfieldHeader {
display: none;
}
#wrap_tfa_remember .InputfieldContent {
padding: 0 0 20px 0;
}
.ProcessLogin #ProcessLoginForm.tfa {
width: 300px;
}

View File

@@ -15,6 +15,8 @@
* @property bool|int $allowEmail Whether or not email login is allowed (0|false=off, 1|true=Yes, 2=Yes or name also allowed)
* @property string $emailField Field name used for email login (when enabled).
* @property array $tfaRecRoleIDs Role IDs where admin prompts/recommends them to enable TFA.
* @property int $tfaRememberDays Allow user to remember their browser and bypass TFA for this many days (-1=no limit, 0=disabled)
* @property array $tfaRememberFingerprints Means by which to fingerprint users browser
*
* @method void beforeLogin() #pw-hooker
* @method void afterLogin() #pw-hooker
@@ -154,6 +156,8 @@ class ProcessLogin extends Process implements ConfigurableModule {
*/
public function __construct() {
$this->set('tfaRecRoleIDs', array());
$this->set('tfaRememberDays', 90);
$this->set('tfaRememberFingerprints', array('agentVL', 'accept', 'scheme', 'host'));
$this->set('allowEmail', false);
$this->set('emailField', 'email');
$this->customMarkup['forgot-icon'] = wireIconMarkup('question-circle', 'fw');
@@ -336,6 +340,8 @@ class ProcessLogin extends Process implements ConfigurableModule {
if(count($tfas)) {
$tfa = new Tfa();
$this->wire($tfa);
$tfa->rememberDays = $this->tfaRememberDays;
$tfa->rememberFingerprints = $this->tfaRememberFingerprints;
}
if($tfa && $tfa->active()) {
@@ -735,7 +741,7 @@ class ProcessLogin extends Process implements ConfigurableModule {
}
$home = $this->pages->get('/');
$icon = $this->markup('home-icon');
$label = $home->getFormatted('title');
$label = $this->wire()->sanitizer->entities($home->getUnformatted('title'));
$links['home'] = str_replace(
array('{url}', '{out}'),
array($home->url, "$icon $label"),
@@ -953,6 +959,40 @@ class ProcessLogin extends Process implements ConfigurableModule {
}
$f->attr('value', $this->get('tfaRecRoleIDs'));
$fieldset->add($f);
/** @var InputfieldInteger $f */
$f = $modules->get('InputfieldInteger');
$f->attr('name', 'tfaRememberDays');
$f->label = $this->_('Allow users the option to skip code entry when their browser/location is remembered?');
$f->description = $this->_('Enter the number of days that browser/location will be remembered or 0 to disable.');
$f->attr('value', (int) $this->tfaRememberDays);
$fieldset->add($f);
$fingerprints = array(
'agent' => $this->_('User agent (browser, platform, and versions of each)'),
'agentVL' => $this->_('Non-versioned user agent (browser and platform, but no versions—less likely to change often)'),
'accept' => $this->_('Accept header (content types users browser accepts)'),
'scheme' => $this->_('Current request scheme whether HTTP or HTTPS'),
'host' => $this->_('Server hostname (value of $config->httpHost)'),
'ip' => $this->_('Users IP address (REMOTE_ADDR)'),
'fwip' => $this->_('Users forwarded or client IP address (HTTP_X_FORWARDED_FOR or HTTP_CLIENT_IP)'),
);
/** @var InputfieldCheckboxes $f */
$f = $modules->get('InputfieldCheckboxes');
$f->attr('name', 'tfaRememberFingerprints');
$f->label = $this->_('Do not allow user to skip code entry when any of these properties change');
$f->description =
$this->_('Changes to password, name, email, or a random cookie in the users browser, will always require code entry at login.') . ' ' .
$this->_('In addition, changes to any checked items below will also require code entry at login.') . ' ' .
$this->_('These properties form a fingerprint of the users browser beyond the random cookie that we set.');
$f->notes = $this->_('This setting only applies when the option to remember browser/location is enabled.');
foreach($fingerprints as $name => $label) {
$f->addOption($name, $label);
}
$f->showIf = 'tfaRememberDays!=0';
$f->attr('value', $this->tfaRememberFingerprints);
$fieldset->add($f);
} else {
$fieldset->description = $this->_('To configure this you must first install one or more Tfa modules and then return here.');