support skipping of 2FA
This commit is contained in:
parent
9086f5847e
commit
9208cb2349
|
@ -11,6 +11,7 @@ use \htmlStatusMessage;
|
|||
use \htmlDiv;
|
||||
use \LAMException;
|
||||
use Webauthn\PublicKeyCredentialCreationOptions;
|
||||
use function LAM\LOGIN\WEBAUTHN\hasTokensRegistered;
|
||||
use function LAM\LOGIN\WEBAUTHN\storeNewRegistration;
|
||||
|
||||
/*
|
||||
|
@ -547,6 +548,15 @@ class WebauthnProvider extends BaseProvider {
|
|||
$row->add($loginButton, 12);
|
||||
$errorMessage = new htmlStatusMessage('ERROR', '', _('This service requires a browser with "WebAuthn" support.'));
|
||||
$row->add(new htmlDiv(null, $errorMessage, array('hidden webauthn-error')), 12);
|
||||
if ($this->config->twoFactorAuthenticationOptional === true) {
|
||||
include_once __DIR__ . '/webauthn.inc';
|
||||
$hasTokens = hasTokensRegistered($userDn);
|
||||
if (!$hasTokens) {
|
||||
$skipButton = new htmlButton('skip_webauthn', _('Skip'));
|
||||
$skipButton->setCSSClasses(array('fullwidth'));
|
||||
$row->add($skipButton, 12);
|
||||
}
|
||||
}
|
||||
$row->add(new htmlJavaScript('window.lam.webauthn.start(\'' . $pathPrefix . '\');'), 0);
|
||||
}
|
||||
|
||||
|
@ -556,8 +566,12 @@ class WebauthnProvider extends BaseProvider {
|
|||
*/
|
||||
public function verify2ndFactor($user, $password, $serial, $twoFactorInput) {
|
||||
logNewMessage(LOG_DEBUG, 'WebauthnProvider: Checking 2nd factor for ' . $user);
|
||||
$response = base64_decode($_POST['sig_response']);
|
||||
include_once __DIR__ . '/webauthn.inc';
|
||||
logNewMessage(LOG_ERR, $user);
|
||||
if ($this->config->twoFactorAuthenticationOptional && !hasTokensRegistered($user) && ($_POST['sig_response'] === 'skip')) {
|
||||
return true;
|
||||
}
|
||||
$response = base64_decode($_POST['sig_response']);
|
||||
$registrationObject = PublicKeyCredentialCreationOptions::createFromString($_SESSION['webauthn_registration']);
|
||||
if (storeNewRegistration($registrationObject, $response)) {
|
||||
return true;
|
||||
|
@ -634,6 +648,7 @@ class TwoFactorProviderService {
|
|||
$tfConfig->isSelfService = true;
|
||||
$tfConfig->twoFactorAuthentication = $profile->twoFactorAuthentication;
|
||||
$tfConfig->twoFactorAuthenticationInsecure = $profile->twoFactorAuthenticationInsecure;
|
||||
$tfConfig->twoFactorAuthenticationOptional = $profile->twoFactorAuthenticationOptional;
|
||||
if ($tfConfig->twoFactorAuthentication == TwoFactorProviderService::TWO_FACTOR_YUBICO) {
|
||||
$tfConfig->twoFactorAuthenticationURL = explode("\r\n", $profile->twoFactorAuthenticationURL);
|
||||
}
|
||||
|
@ -673,6 +688,7 @@ class TwoFactorProviderService {
|
|||
$tfConfig->isSelfService = false;
|
||||
$tfConfig->twoFactorAuthentication = $conf->getTwoFactorAuthentication();
|
||||
$tfConfig->twoFactorAuthenticationInsecure = $conf->getTwoFactorAuthenticationInsecure();
|
||||
$tfConfig->twoFactorAuthenticationOptional = $conf->getTwoFactorAuthenticationOptional();
|
||||
if ($tfConfig->twoFactorAuthentication == TwoFactorProviderService::TWO_FACTOR_YUBICO) {
|
||||
$tfConfig->twoFactorAuthenticationURL = explode("\r\n", $conf->getTwoFactorAuthenticationURL());
|
||||
}
|
||||
|
@ -741,4 +757,9 @@ class TwoFactorConfiguration {
|
|||
*/
|
||||
public $twoFactorAuthenticationSerialAttributeName = null;
|
||||
|
||||
/**
|
||||
* @var bool 2FA is optional
|
||||
*/
|
||||
public $twoFactorAuthenticationOptional = false;
|
||||
|
||||
}
|
||||
|
|
|
@ -2480,7 +2480,7 @@ class LAMConfig {
|
|||
* @return bool 2nd factor is optional
|
||||
*/
|
||||
public function getTwoFactorAuthenticationOptional() {
|
||||
return $this->twoFactorAuthenticationOptional;
|
||||
return boolval($this->twoFactorAuthenticationOptional);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -274,6 +274,19 @@ function getExtensionOutputChecker() {
|
|||
return new ExtensionOutputCheckerHandler();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if there are any tokens registered for the given DN.
|
||||
*
|
||||
* @param string $dn user DN
|
||||
* @return bool at least one token is registered
|
||||
*/
|
||||
function hasTokensRegistered($dn) {
|
||||
$repository = new PublicKeyCredentialSourceRepositorySQLite();
|
||||
$userEntity = getUserEntity($dn);
|
||||
$tokens = $repository->findAllForUserEntity($userEntity);
|
||||
return !empty($tokens);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the public key credentials in the SQLite database.
|
||||
*
|
||||
|
|
|
@ -479,7 +479,7 @@ if (extension_loaded('curl')) {
|
|||
TwoFactorProviderService::TWO_FACTOR_YUBICO => array('twoFactorURL', 'twoFactorAttribute', 'twoFactorDomain'),
|
||||
TwoFactorProviderService::TWO_FACTOR_DUO => array('twoFactorURLs', 'twoFactorOptional', 'twoFactorInsecure', 'twoFactorLabel', 'twoFactorDomain'),
|
||||
TwoFactorProviderService::TWO_FACTOR_WEBAUTHN => array('twoFactorURL', 'twoFactorURLs', 'twoFactorInsecure', 'twoFactorLabel',
|
||||
'twoFactorOptional', 'twoFactorCaption', 'twoFactorClientId', 'twoFactorSecretKey', 'twoFactorAttribute'),
|
||||
'twoFactorCaption', 'twoFactorClientId', 'twoFactorSecretKey', 'twoFactorAttribute'),
|
||||
));
|
||||
$twoFactorSelect->setTableRowsToShow(array(
|
||||
TwoFactorProviderService::TWO_FACTOR_PRIVACYIDEA => array('twoFactorURL', 'twoFactorInsecure', 'twoFactorLabel',
|
||||
|
@ -488,7 +488,7 @@ if (extension_loaded('curl')) {
|
|||
'twoFactorOptional', 'twoFactorCaption', 'twoFactorClientId', 'twoFactorSecretKey'),
|
||||
TwoFactorProviderService::TWO_FACTOR_DUO => array('twoFactorURL', 'twoFactorLabel',
|
||||
'twoFactorCaption', 'twoFactorClientId', 'twoFactorSecretKey', 'twoFactorAttribute'),
|
||||
TwoFactorProviderService::TWO_FACTOR_WEBAUTHN => array('twoFactorDomain')
|
||||
TwoFactorProviderService::TWO_FACTOR_WEBAUTHN => array('twoFactorDomain', 'twoFactorOptional')
|
||||
));
|
||||
$row->add($twoFactorSelect, 12);
|
||||
$twoFactorAttribute = new htmlResponsiveInputField(_("User name attribute"), 'twoFactorAttribute', $conf->getTwoFactorAuthenticationAttribute(), '528');
|
||||
|
|
|
@ -1377,6 +1377,12 @@ window.lam.webauthn.start = function(prefix) {
|
|||
* @param prefix path prefix for Ajax endpoint
|
||||
*/
|
||||
window.lam.webauthn.run = function(prefix) {
|
||||
jQuery('#btn_skip_webauthn').click(function () {
|
||||
let form = jQuery("#2faform");
|
||||
form.append('<input type="hidden" name="sig_response" value="skip"/>');
|
||||
form.submit();
|
||||
return;
|
||||
});
|
||||
var token = jQuery('#sec_token').val();
|
||||
// check for webauthn support
|
||||
if (!navigator.credentials || (typeof(PublicKeyCredential) === "undefined")) {
|
||||
|
|
Loading…
Reference in New Issue