diff --git a/out/out.SetupWebauthn.php b/out/out.SetupWebauthn.php deleted file mode 100644 index 95034333e..000000000 --- a/out/out.SetupWebauthn.php +++ /dev/null @@ -1,41 +0,0 @@ - - * @copyright Copyright (C) 2016 Uwe Steinmann - * @version Release: @package_version@ - */ - -if(!isset($settings)) - require_once("../inc/inc.Settings.php"); -require_once("inc/inc.Utils.php"); -require_once("inc/inc.LogInit.php"); -require_once("inc/inc.Language.php"); -require_once("inc/inc.Init.php"); -require_once("inc/inc.Extension.php"); -require_once("inc/inc.DBInit.php"); -require_once("inc/inc.ClassUI.php"); -require_once("inc/inc.WebAuthn.php"); -require_once("inc/inc.Authentication.php"); - -$tmp = explode('.', basename($_SERVER['SCRIPT_FILENAME'])); -$view = UI::factory($theme, $tmp[1], array('dms'=>$dms, 'user'=>$user)); -$accessop = new SeedDMS_AccessOperation($dms, $user, $settings); - -if ($user->isGuest()) { - UI::exitError(getMLText("webauthn"),getMLText("access_denied")); -} - -if($view) { - $view->setParam('sitename', $settings->_siteName); - $view->setParam('enable2factauth', $settings->_enable2FactorAuthentication); - $view->setParam('accessobject', $accessop); - $view($_REQUEST); - exit; -} - diff --git a/views/bootstrap/class.SetupWebauthn.php b/views/bootstrap/class.SetupWebauthn.php deleted file mode 100644 index d5055fc24..000000000 --- a/views/bootstrap/class.SetupWebauthn.php +++ /dev/null @@ -1,425 +0,0 @@ - - * @copyright Copyright (C) 2016 Uwe Steinmann - * @version Release: @package_version@ - */ - -/** - * Include parent class - */ -//require_once("class.Bootstrap.php"); - -/** - * Include classes for 2-factor authentication - */ -require "vendor/autoload.php"; - -/** - * Class which outputs the html page for ForcePasswordChange view - * - * @category DMS - * @package SeedDMS - * @author Markus Westphal, Malcolm Cowe, Uwe Steinmann - * @copyright Copyright (C) 2016 Uwe Steinmann - * @version Release: @package_version@ - */ -class SeedDMS_View_SetupWebauthn extends SeedDMS_Bootstrap_Style { - - function css() { /* {{{ */ - header('Content-Type: text/css; charset=UTF-8'); -?> -.cdokey { - display: none; - background-color: orange; - color: white; - font-weight: bold; - margin: 10px 0; - padding: 10px; -} - -function webauthnRegister(key, callback){ - key = JSON.parse(key); - key.publicKey.attestation = undefined; - key.publicKey.challenge = new Uint8Array(key.publicKey.challenge); // convert type for use by key - key.publicKey.user.id = new Uint8Array(key.publicKey.user.id); - - //console.log(key); - navigator.credentials.create({publicKey: key.publicKey}) - .then(function (aNewCredentialInfo) { - console.log("Credentials.Create response: ", aNewCredentialInfo); - var cd = JSON.parse(String.fromCharCode.apply(null, new Uint8Array(aNewCredentialInfo.response.clientDataJSON))); - if (key.b64challenge != cd.challenge) { - return callback(false, 'key returned something unexpected (1)'); - } - if ('https://'+key.publicKey.rp.name != cd.origin) { - console.log(key.publicKey.rp.name); - console.log(cd.origin); - return callback(false, 'key returned something unexpected (2)'); - } - if (! ('type' in cd)) { - return callback(false, 'key returned something unexpected (3)'); - } - if (cd.type != 'webauthn.create') { - return callback(false, 'key returned something unexpected (4)'); - } - - var ao = []; - (new Uint8Array(aNewCredentialInfo.response.attestationObject)).forEach(function(v){ - ao.push(v); - }); - var rawId = []; - (new Uint8Array(aNewCredentialInfo.rawId)).forEach(function(v){ - rawId.push(v); - }); - var info = { - rawId: rawId, - id: aNewCredentialInfo.id, - type: aNewCredentialInfo.type, - response: { - attestationObject: ao, - clientDataJSON: - JSON.parse(String.fromCharCode.apply(null, new Uint8Array(aNewCredentialInfo.response.clientDataJSON))) - } - }; - console.log("Info: ", info); - callback(true, JSON.stringify(info)); - }) - .catch(function (aErr) { - if ( - ("name" in aErr) && (aErr.name == "AbortError" || aErr.name == "NS_ERROR_ABORT") - || aErr.name == 'NotAllowedError' - ) { - callback(false, 'abort'); - } else { - callback(false, aErr.toString()); - } - }); -} -function webauthnAuthenticate(key, cb){ - var pk = JSON.parse(key); - var originalChallenge = pk.challenge; - pk.challenge = new Uint8Array(pk.challenge); - pk.allowCredentials.forEach(function(k, idx){ - pk.allowCredentials[idx].id = new Uint8Array(k.id); - }); - /* ask the browser to prompt the user */ - navigator.credentials.get({publicKey: pk}) - .then(function(aAssertion) { - // console.log("Credentials.Get response: ", aAssertion); - var ida = []; - (new Uint8Array(aAssertion.rawId)).forEach(function(v){ ida.push(v); }); - var cd = JSON.parse(String.fromCharCode.apply(null, - new Uint8Array(aAssertion.response.clientDataJSON))); - var cda = []; - (new Uint8Array(aAssertion.response.clientDataJSON)).forEach(function(v){ cda.push(v); }); - var ad = []; - (new Uint8Array(aAssertion.response.authenticatorData)).forEach(function(v){ ad.push(v); }); - var sig = []; - (new Uint8Array(aAssertion.response.signature)).forEach(function(v){ sig.push(v); }); - var info = { - type: aAssertion.type, - originalChallenge: originalChallenge, - rawId: ida, - response: { - authenticatorData: ad, - clientData: cd, - clientDataJSONarray: cda, - signature: sig - } - }; - cb(true, JSON.stringify(info)); - }) - .catch(function (aErr) { - if (("name" in aErr) && (aErr.name == "AbortError" || aErr.name == "NS_ERROR_ABORT" || - aErr.name == "NotAllowedError")) { - cb(false, 'abort'); - } else { - cb(false, aErr.toString()); - } - }); -} - - $(function(){ - - $('#iregisterform').submit(function(ev){ - var self = $(this); - ev.preventDefault(); - var cp = $('select[name=cp]').val(); - if (cp == "") { - $('.cerror').show().text("Please choose cross-platform setting - see note below about what this means"); - return; - } - - $('.cerror').empty().hide(); - - $.ajax({url: '../out/out.SetupWebauthn.php', - method: 'POST', - data: {action: 'registeruser', registerusername: self.find('[name=registerusername]').val(), crossplatform: cp}, - dataType: 'json', - success: function(j){ - /* activate the key and get the response */ - webauthnRegister(j.challenge, function(success, info){ - if (success) { - $.ajax({url: '../out/out.SetupWebauthn.php', - method: 'POST', - data: {action: 'register', register: info}, - dataType: 'json', - success: function(j){ - noty({ - text: 'registration completed successfully', - type: 'success', - dismissQueue: true, - layout: 'topRight', - theme: 'defaultTheme', - timeout: 1500, - }); - }, - error: function(xhr, status, error){ - noty({ - text: 'registration failed: '+error+": "+xhr.responseText, - type: 'error', - dismissQueue: true, - layout: 'topRight', - theme: 'defaultTheme', - timeout: 1500, - }); -// $('.cerror').text("registration failed: "+error+": "+xhr.responseText).show(); - } - }); - } else { - noty({ - text: info, - type: 'error', - dismissQueue: true, - layout: 'topRight', - theme: 'defaultTheme', - timeout: 1500, - }); -// $('.cerror').text(info).show(); - } - }); - }, - - error: function(xhr, status, error){ - noty({ - text: "couldn't initiate registration: "+error+": "+xhr.responseText, - type: 'error', - dismissQueue: true, - layout: 'topRight', - theme: 'defaultTheme', - timeout: 1500, - }); - } - }); - }); - - $('#iloginform').submit(function(ev){ - var self = $(this); - ev.preventDefault(); - $('.cerror').empty().hide(); - - $.ajax({url: '../out/out.SetupWebauthn.php', - method: 'POST', - data: {action: 'preparelogin', loginusername: self.find('[name=loginusername]').val()}, - dataType: 'json', - success: function(j){ - /* activate the key and get the response */ - webauthnAuthenticate(j.challenge, function(success, info){ - if (success) { - $.ajax({url: '../out/out.SetupWebauthn.php', - method: 'POST', - data: {action: 'login', login: info}, - dataType: 'json', - success: function(j){ - noty({ - text: 'login completed successfully', - type: 'success', - dismissQueue: true, - layout: 'topRight', - theme: 'defaultTheme', - timeout: 1500, - }); - }, - error: function(xhr, status, error){ - noty({ - text: 'login failed: '+error+": "+xhr.responseText, - type: 'error', - dismissQueue: true, - layout: 'topRight', - theme: 'defaultTheme', - timeout: 1500, - }); -// $('.cerror').text("login failed: "+error+": "+xhr.responseText).show(); - } - }); - } else { - noty({ - text: info, - type: 'error', - dismissQueue: true, - layout: 'topRight', - theme: 'defaultTheme', - timeout: 1500, - }); -// $('.cerror').text(info).show(); - } - }); - }, - - error: function(xhr, status, error){ - noty({ - text: "couldn't initiate login: "+error+": "+xhr.responseText, - type: 'error', - dismissQueue: true, - layout: 'topRight', - theme: 'defaultTheme', - timeout: 1500, - }); - } - }); - }); - }); -params['dms']; - $user = $this->params['user']; - - $webauthn = new \Davidearl\WebAuthn\WebAuthn($_SERVER['HTTP_HOST']); - - /* initiate the registration */ - $username = $user->getLogin(); - $userid = $user->getId(); - $crossplatform = ! empty($_POST['crossplatform']) && $_POST['crossplatform'] == 'Yes'; - -// $user->setWebauthn($webauthn->cancel()); - - $j = ['challenge' => $webauthn->prepareChallengeForRegistration($username, $userid, $crossplatform)]; - header('Content-type: application/json'); - echo json_encode($j); - } /* }}} */ - - function register() { /* {{{ */ - $dms = $this->params['dms']; - $user = $this->params['user']; - - $webauthn = new \Davidearl\WebAuthn\WebAuthn($_SERVER['HTTP_HOST']); - - /* The heart of the matter */ - $user->setWebauthn($webauthn->register($_POST['register'], $user->getWebauthn())); - - $j = 'ok'; - - header('Content-type: application/json'); - echo json_encode($j); - } /* }}} */ - - /** - * Return challange for login process - * - * This method is quite similar to the one in controllers/class.Login.php - */ - function preparelogin() { /* {{{ */ - $dms = $this->params['dms']; - $user = $this->params['user']; - - $webauthn = new \Davidearl\WebAuthn\WebAuthn($_SERVER['HTTP_HOST']); - - $j['challenge'] = $webauthn->prepareForLogin($user->getWebauthn()); - header('Content-type: application/json'); - echo json_encode($j); - } /* }}} */ - - /** - * Do a fake login to check if authentication works - * - * This method is quite similar to the one in controllers/class.Login.php - */ - function login() { /* {{{ */ - $dms = $this->params['dms']; - $user = $this->params['user']; - - $webauthn = new \Davidearl\WebAuthn\WebAuthn($_SERVER['HTTP_HOST']); - - if (! $webauthn->authenticate($_POST['login'], $user->getWebauthn())) { - http_response_code(401); - echo 'failed to authenticate with that key'; - exit; - } - $j = 'ok'; - header('Content-type: application/json'); - echo json_encode($j); - } /* }}} */ - - function show() { /* {{{ */ - $dms = $this->params['dms']; - $user = $this->params['user']; - $sitename = $this->params['sitename']; - - $this->htmlStartPage(getMLText("webauthn"), "forcepasswordchange"); - $this->globalNavigation(); - $this->contentStart(); - $this->pageNavigation(getMLText("my_account"), "my_account"); - $this->contentHeading(getMLText('webauthn_auth')); - echo "
".getMLText('webauthn_info')."
"; - echo '
'; - echo '
'; - $this->contentHeading(getMLText('webauthn_registration')); - $this->contentContainerStart(); -?> -
-
- -
-
- - - - -formSubmit(getMLText('submit_webauthn_register')); -?> -
-contentContainerEnd(); - - echo $this->infoMsg(getMLText('webauthn_crossplatform_info')); - echo "
"; - if($user->getWebauthn()) { - echo '
'; - $this->contentHeading(getMLText('webauthn_login_test')); - $this->contentContainerStart(); -?> -
- -formSubmit(getMLText('submit_webauthn_login')); -?> -
-contentContainerEnd(); - } - - echo '
'; - echo '
'; - $this->contentEnd(); - $this->htmlEndPage(); - } /* }}} */ -} -