From: nupplaPhil Date: Fri, 27 Dec 2019 21:19:28 +0000 (+0100) Subject: Move Login/Logout/TwoFactor to bundled submodule "Security" X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=aa5771cf3e170e1a335d4f3b770693033493be99;p=friendica.git Move Login/Logout/TwoFactor to bundled submodule "Security" --- diff --git a/mod/api.php b/mod/api.php index 9a802b515a..929832480a 100644 --- a/mod/api.php +++ b/mod/api.php @@ -8,7 +8,7 @@ use Friendica\Core\Config; use Friendica\Core\L10n; use Friendica\Core\Renderer; use Friendica\Database\DBA; -use Friendica\Module\Login; +use Friendica\Module\Security\Login; require_once __DIR__ . '/../include/api.php'; diff --git a/mod/dfrn_poll.php b/mod/dfrn_poll.php index 8479217195..0641b9177b 100644 --- a/mod/dfrn_poll.php +++ b/mod/dfrn_poll.php @@ -13,7 +13,7 @@ use Friendica\Core\Logger; use Friendica\Core\System; use Friendica\Core\Session; use Friendica\Database\DBA; -use Friendica\Module\Login; +use Friendica\Module\Security\Login; use Friendica\Protocol\DFRN; use Friendica\Protocol\OStatus; use Friendica\Util\Network; diff --git a/mod/dfrn_request.php b/mod/dfrn_request.php index a9e17b34b3..28845634ad 100644 --- a/mod/dfrn_request.php +++ b/mod/dfrn_request.php @@ -25,7 +25,7 @@ use Friendica\Model\Contact; use Friendica\Model\Group; use Friendica\Model\Profile; use Friendica\Model\User; -use Friendica\Module\Login; +use Friendica\Module\Security\Login; use Friendica\Network\Probe; use Friendica\Protocol\Activity; use Friendica\Util\DateTimeFormat; diff --git a/mod/events.php b/mod/events.php index 5e129aaf61..6547a9b9ce 100644 --- a/mod/events.php +++ b/mod/events.php @@ -19,7 +19,7 @@ use Friendica\Database\DBA; use Friendica\Model\Event; use Friendica\Model\Item; use Friendica\Model\Profile; -use Friendica\Module\Login; +use Friendica\Module\Security\Login; use Friendica\Util\ACLFormatter; use Friendica\Util\DateTimeFormat; use Friendica\Util\Strings; diff --git a/mod/message.php b/mod/message.php index 393d5d276b..8efe825cd9 100644 --- a/mod/message.php +++ b/mod/message.php @@ -15,7 +15,7 @@ use Friendica\Core\System; use Friendica\Database\DBA; use Friendica\Model\Contact; use Friendica\Model\Mail; -use Friendica\Module\Login; +use Friendica\Module\Security\Login; use Friendica\Util\DateTimeFormat; use Friendica\Util\Proxy as ProxyUtils; use Friendica\Util\Strings; diff --git a/mod/network.php b/mod/network.php index 44c7c8b44f..5d8656cd35 100644 --- a/mod/network.php +++ b/mod/network.php @@ -27,7 +27,7 @@ use Friendica\Model\Group; use Friendica\Model\Item; use Friendica\Model\Profile; use Friendica\Model\Term; -use Friendica\Module\Login; +use Friendica\Module\Security\Login; use Friendica\Util\DateTimeFormat; use Friendica\Util\Proxy as ProxyUtils; use Friendica\Util\Strings; diff --git a/mod/notifications.php b/mod/notifications.php index 90036705bc..502a2397de 100644 --- a/mod/notifications.php +++ b/mod/notifications.php @@ -13,7 +13,7 @@ use Friendica\Core\Protocol; use Friendica\Core\Renderer; use Friendica\Core\System; use Friendica\Database\DBA; -use Friendica\Module\Login; +use Friendica\Module\Security\Login; use Friendica\Model\Introduction; use Friendica\Model\Notify; diff --git a/mod/oexchange.php b/mod/oexchange.php index e042a22f52..a55ee56d21 100644 --- a/mod/oexchange.php +++ b/mod/oexchange.php @@ -6,7 +6,7 @@ use Friendica\App; use Friendica\Core\L10n; use Friendica\Core\Renderer; use Friendica\Core\System; -use Friendica\Module\Login; +use Friendica\Module\Security\Login; use Friendica\Util\Network; use Friendica\Util\Strings; diff --git a/mod/profiles.php b/mod/profiles.php index d3a6c3e38a..46bc36db53 100644 --- a/mod/profiles.php +++ b/mod/profiles.php @@ -20,7 +20,7 @@ use Friendica\Model\Contact; use Friendica\Model\GContact; use Friendica\Model\Profile; use Friendica\Model\User; -use Friendica\Module\Login; +use Friendica\Module\Security\Login; use Friendica\Network\Probe; use Friendica\Util\DateTimeFormat; use Friendica\Util\Strings; diff --git a/mod/regmod.php b/mod/regmod.php index 295d8df25f..ab03f93933 100644 --- a/mod/regmod.php +++ b/mod/regmod.php @@ -11,7 +11,7 @@ use Friendica\Core\Worker; use Friendica\Database\DBA; use Friendica\Model\Register; use Friendica\Model\User; -use Friendica\Module\Login; +use Friendica\Module\Security\Login; function user_allow($hash) { diff --git a/mod/settings.php b/mod/settings.php index 8b5254976d..ad83b68210 100644 --- a/mod/settings.php +++ b/mod/settings.php @@ -24,7 +24,7 @@ use Friendica\Model\Contact; use Friendica\Model\GContact; use Friendica\Model\Group; use Friendica\Model\User; -use Friendica\Module\Login; +use Friendica\Module\Security\Login; use Friendica\Protocol\Email; use Friendica\Util\ACLFormatter; use Friendica\Util\Network; diff --git a/src/App.php b/src/App.php index 3325f5b260..3ea7d05f0c 100644 --- a/src/App.php +++ b/src/App.php @@ -18,7 +18,7 @@ use Friendica\Core\System; use Friendica\Core\Theme; use Friendica\Database\Database; use Friendica\Model\Profile; -use Friendica\Module\Login; +use Friendica\Module\Security\Login; use Friendica\Module\Special\HTTPException as ModuleHTTPException; use Friendica\Network\HTTPException; use Friendica\Util\ConfigFileLoader; diff --git a/src/Module/Bookmarklet.php b/src/Module/Bookmarklet.php index 08bac2c1d0..2993c20a7b 100644 --- a/src/Module/Bookmarklet.php +++ b/src/Module/Bookmarklet.php @@ -5,6 +5,7 @@ namespace Friendica\Module; use Friendica\BaseModule; use Friendica\Core\ACL; use Friendica\Core\L10n; +use Friendica\Module\Security\Login; use Friendica\Network\HTTPException; use Friendica\Util\Strings; diff --git a/src/Module/Contact.php b/src/Module/Contact.php index 01af275864..48bb9ba310 100644 --- a/src/Module/Contact.php +++ b/src/Module/Contact.php @@ -18,6 +18,7 @@ use Friendica\Core\System; use Friendica\Core\Worker; use Friendica\Database\DBA; use Friendica\Model; +use Friendica\Module\Security\Login; use Friendica\Network\HTTPException\BadRequestException; use Friendica\Network\HTTPException\NotFoundException; use Friendica\Network\Probe; diff --git a/src/Module/Home.php b/src/Module/Home.php index e6fb8c3496..8fdb613f9b 100644 --- a/src/Module/Home.php +++ b/src/Module/Home.php @@ -6,6 +6,7 @@ use Friendica\BaseModule; use Friendica\Core\Hook; use Friendica\Core\L10n; use Friendica\Core\Renderer; +use Friendica\Module\Security\Login; /** * Home module - Landing page of the current node diff --git a/src/Module/Item/Compose.php b/src/Module/Item/Compose.php index b9cda4863e..ded41fe392 100644 --- a/src/Module/Item/Compose.php +++ b/src/Module/Item/Compose.php @@ -17,7 +17,7 @@ use Friendica\Model\FileTag; use Friendica\Model\Group; use Friendica\Model\Item; use Friendica\Model\User; -use Friendica\Module\Login; +use Friendica\Module\Security\Login; use Friendica\Network\HTTPException\NotImplementedException; use Friendica\Util\ACLFormatter; use Friendica\Util\Crypto; diff --git a/src/Module/Login.php b/src/Module/Login.php deleted file mode 100644 index d7c537839d..0000000000 --- a/src/Module/Login.php +++ /dev/null @@ -1,217 +0,0 @@ - - */ -class Login extends BaseModule -{ - public static function content(array $parameters = []) - { - $a = self::getApp(); - - if (local_user()) { - $a->internalRedirect(); - } - - return self::form(Session::get('return_path'), intval(Config::get('config', 'register_policy')) !== \Friendica\Module\Register::CLOSED); - } - - public static function post(array $parameters = []) - { - $return_path = Session::get('return_path'); - Session::clear(); - Session::set('return_path', $return_path); - - // OpenId Login - if ( - empty($_POST['password']) - && (!empty($_POST['openid_url']) - || !empty($_POST['username'])) - ) { - $openid_url = trim(($_POST['openid_url'] ?? '') ?: $_POST['username']); - - /** @var Authentication $authentication */ - $authentication = self::getClass(Authentication::class); - $authentication->withOpenId($openid_url, !empty($_POST['remember'])); - } - - if (!empty($_POST['auth-params']) && $_POST['auth-params'] === 'login') { - /** @var Authentication $authentication */ - $authentication = self::getClass(Authentication::class); - $authentication->withPassword( - self::getApp(), - trim($_POST['username']), - trim($_POST['password']), - !empty($_POST['remember']) - ); - } - } - - /** - * @brief Wrapper for adding a login box. - * - * @param string $return_path The path relative to the base the user should be sent - * back to after login completes - * @param bool $register If $register == true provide a registration link. - * This will most always depend on the value of config.register_policy. - * @param array $hiddens optional - * - * @return string Returns the complete html for inserting into the page - * - * @throws \Friendica\Network\HTTPException\InternalServerErrorException - * @hooks 'login_hook' string $o - */ - public static function form($return_path = null, $register = false, $hiddens = []) - { - $a = self::getApp(); - $o = ''; - - $noid = Config::get('system', 'no_openid'); - - if ($noid) { - Session::remove('openid_identity'); - Session::remove('openid_attributes'); - } - - $reg = false; - if ($register && intval($a->getConfig()->get('config', 'register_policy')) !== Register::CLOSED) { - $reg = [ - 'title' => L10n::t('Create a New Account'), - 'desc' => L10n::t('Register'), - 'url' => self::getRegisterURL() - ]; - } - - if (is_null($return_path)) { - $return_path = $a->query_string; - } - - if (local_user()) { - $tpl = Renderer::getMarkupTemplate('logout.tpl'); - } else { - $a->page['htmlhead'] .= Renderer::replaceMacros( - Renderer::getMarkupTemplate('login_head.tpl'), - [ - '$baseurl' => $a->getBaseURL(true) - ] - ); - - $tpl = Renderer::getMarkupTemplate('login.tpl'); - $_SESSION['return_path'] = $return_path; - } - - if (!empty(Session::get('openid_identity'))) { - $openid_title = L10n::t('Your OpenID: '); - $openid_readonly = true; - $identity = Session::get('openid_identity'); - $username_desc = L10n::t('Please enter your username and password to add the OpenID to your existing account.'); - } else { - $openid_title = L10n::t('Or login using OpenID: '); - $openid_readonly = false; - $identity = ''; - $username_desc = ''; - } - - $o .= Renderer::replaceMacros( - $tpl, - [ - '$dest_url' => self::getApp()->getBaseURL(true) . '/login', - '$logout' => L10n::t('Logout'), - '$login' => L10n::t('Login'), - - '$lname' => ['username', L10n::t('Nickname or Email: '), '', $username_desc], - '$lpassword' => ['password', L10n::t('Password: '), '', ''], - '$lremember' => ['remember', L10n::t('Remember me'), 0, ''], - - '$openid' => !$noid, - '$lopenid' => ['openid_url', $openid_title, $identity, '', $openid_readonly], - - '$hiddens' => $hiddens, - - '$register' => $reg, - - '$lostpass' => L10n::t('Forgot your password?'), - '$lostlink' => L10n::t('Password Reset'), - - '$tostitle' => L10n::t('Website Terms of Service'), - '$toslink' => L10n::t('terms of service'), - - '$privacytitle' => L10n::t('Website Privacy Policy'), - '$privacylink' => L10n::t('privacy policy'), - ] - ); - - Hook::callAll('login_hook', $o); - - return $o; - } - - /** - * Get the URL to the register page and add OpenID parameters to it - */ - private static function getRegisterURL() - { - if (empty(Session::get('openid_identity'))) { - return 'register'; - } - - $args = []; - $attr = Session::get('openid_attributes', []); - - if (is_array($attr) && count($attr)) { - foreach ($attr as $k => $v) { - if ($k === 'namePerson/friendly') { - $nick = Strings::escapeTags(trim($v)); - } - if ($k === 'namePerson/first') { - $first = Strings::escapeTags(trim($v)); - } - if ($k === 'namePerson') { - $args['username'] = Strings::escapeTags(trim($v)); - } - if ($k === 'contact/email') { - $args['email'] = Strings::escapeTags(trim($v)); - } - if ($k === 'media/image/aspect11') { - $photosq = bin2hex(trim($v)); - } - if ($k === 'media/image/default') { - $photo = bin2hex(trim($v)); - } - } - } - - if (!empty($nick)) { - $args['nickname'] = $nick; - } elseif (!empty($first)) { - $args['nickname'] = $first; - } - - if (!empty($photosq)) { - $args['photo'] = $photosq; - } elseif (!empty($photo)) { - $args['photo'] = $photo; - } - - $args['openid_url'] = Strings::escapeTags(trim(Session::get('openid_identity'))); - - return 'register?' . http_build_query($args); - } -} diff --git a/src/Module/Logout.php b/src/Module/Logout.php deleted file mode 100644 index 9e6c674b35..0000000000 --- a/src/Module/Logout.php +++ /dev/null @@ -1,45 +0,0 @@ - - */ -class Logout extends BaseModule -{ - /** - * @brief Process logout requests - */ - public static function init(array $parameters = []) - { - $visitor_home = null; - if (remote_user()) { - $visitor_home = Profile::getMyURL(); - Cache::delete('zrlInit:' . $visitor_home); - } - - Hook::callAll("logging_out"); - Session::clear(); - - if ($visitor_home) { - System::externalRedirect($visitor_home); - } else { - info(L10n::t('Logged out.')); - self::getApp()->internalRedirect(); - } - } -} diff --git a/src/Module/Profile.php b/src/Module/Profile.php index db1a6f86b3..d399ba8ddf 100644 --- a/src/Module/Profile.php +++ b/src/Module/Profile.php @@ -19,6 +19,7 @@ use Friendica\Model\Group; use Friendica\Model\Item; use Friendica\Model\Profile as ProfileModel; use Friendica\Model\User; +use Friendica\Module\Security\Login; use Friendica\Protocol\ActivityPub; use Friendica\Protocol\DFRN; use Friendica\Util\DateTimeFormat; diff --git a/src/Module/Search/Directory.php b/src/Module/Search/Directory.php index e3515713f5..f9988c0049 100644 --- a/src/Module/Search/Directory.php +++ b/src/Module/Search/Directory.php @@ -5,7 +5,7 @@ namespace Friendica\Module\Search; use Friendica\Content\Widget; use Friendica\Core\L10n; use Friendica\Module\BaseSearchModule; -use Friendica\Module\Login; +use Friendica\Module\Security\Login; use Friendica\Util\Strings; /** diff --git a/src/Module/Security/Login.php b/src/Module/Security/Login.php new file mode 100644 index 0000000000..311cbdd9bb --- /dev/null +++ b/src/Module/Security/Login.php @@ -0,0 +1,218 @@ + + */ +class Login extends BaseModule +{ + public static function content(array $parameters = []) + { + $a = self::getApp(); + + if (local_user()) { + $a->internalRedirect(); + } + + return self::form(Session::get('return_path'), intval(Config::get('config', 'register_policy')) !== \Friendica\Module\Register::CLOSED); + } + + public static function post(array $parameters = []) + { + $return_path = Session::get('return_path'); + Session::clear(); + Session::set('return_path', $return_path); + + // OpenId Login + if ( + empty($_POST['password']) + && (!empty($_POST['openid_url']) + || !empty($_POST['username'])) + ) { + $openid_url = trim(($_POST['openid_url'] ?? '') ?: $_POST['username']); + + /** @var Authentication $authentication */ + $authentication = self::getClass(Authentication::class); + $authentication->withOpenId($openid_url, !empty($_POST['remember'])); + } + + if (!empty($_POST['auth-params']) && $_POST['auth-params'] === 'login') { + /** @var Authentication $authentication */ + $authentication = self::getClass(Authentication::class); + $authentication->withPassword( + self::getApp(), + trim($_POST['username']), + trim($_POST['password']), + !empty($_POST['remember']) + ); + } + } + + /** + * @brief Wrapper for adding a login box. + * + * @param string $return_path The path relative to the base the user should be sent + * back to after login completes + * @param bool $register If $register == true provide a registration link. + * This will most always depend on the value of config.register_policy. + * @param array $hiddens optional + * + * @return string Returns the complete html for inserting into the page + * + * @throws \Friendica\Network\HTTPException\InternalServerErrorException + * @hooks 'login_hook' string $o + */ + public static function form($return_path = null, $register = false, $hiddens = []) + { + $a = self::getApp(); + $o = ''; + + $noid = Config::get('system', 'no_openid'); + + if ($noid) { + Session::remove('openid_identity'); + Session::remove('openid_attributes'); + } + + $reg = false; + if ($register && intval($a->getConfig()->get('config', 'register_policy')) !== Register::CLOSED) { + $reg = [ + 'title' => L10n::t('Create a New Account'), + 'desc' => L10n::t('Register'), + 'url' => self::getRegisterURL() + ]; + } + + if (is_null($return_path)) { + $return_path = $a->query_string; + } + + if (local_user()) { + $tpl = Renderer::getMarkupTemplate('logout.tpl'); + } else { + $a->page['htmlhead'] .= Renderer::replaceMacros( + Renderer::getMarkupTemplate('login_head.tpl'), + [ + '$baseurl' => $a->getBaseURL(true) + ] + ); + + $tpl = Renderer::getMarkupTemplate('login.tpl'); + $_SESSION['return_path'] = $return_path; + } + + if (!empty(Session::get('openid_identity'))) { + $openid_title = L10n::t('Your OpenID: '); + $openid_readonly = true; + $identity = Session::get('openid_identity'); + $username_desc = L10n::t('Please enter your username and password to add the OpenID to your existing account.'); + } else { + $openid_title = L10n::t('Or login using OpenID: '); + $openid_readonly = false; + $identity = ''; + $username_desc = ''; + } + + $o .= Renderer::replaceMacros( + $tpl, + [ + '$dest_url' => self::getApp()->getBaseURL(true) . '/login', + '$logout' => L10n::t('Logout'), + '$login' => L10n::t('Login'), + + '$lname' => ['username', L10n::t('Nickname or Email: '), '', $username_desc], + '$lpassword' => ['password', L10n::t('Password: '), '', ''], + '$lremember' => ['remember', L10n::t('Remember me'), 0, ''], + + '$openid' => !$noid, + '$lopenid' => ['openid_url', $openid_title, $identity, '', $openid_readonly], + + '$hiddens' => $hiddens, + + '$register' => $reg, + + '$lostpass' => L10n::t('Forgot your password?'), + '$lostlink' => L10n::t('Password Reset'), + + '$tostitle' => L10n::t('Website Terms of Service'), + '$toslink' => L10n::t('terms of service'), + + '$privacytitle' => L10n::t('Website Privacy Policy'), + '$privacylink' => L10n::t('privacy policy'), + ] + ); + + Hook::callAll('login_hook', $o); + + return $o; + } + + /** + * Get the URL to the register page and add OpenID parameters to it + */ + private static function getRegisterURL() + { + if (empty(Session::get('openid_identity'))) { + return 'register'; + } + + $args = []; + $attr = Session::get('openid_attributes', []); + + if (is_array($attr) && count($attr)) { + foreach ($attr as $k => $v) { + if ($k === 'namePerson/friendly') { + $nick = Strings::escapeTags(trim($v)); + } + if ($k === 'namePerson/first') { + $first = Strings::escapeTags(trim($v)); + } + if ($k === 'namePerson') { + $args['username'] = Strings::escapeTags(trim($v)); + } + if ($k === 'contact/email') { + $args['email'] = Strings::escapeTags(trim($v)); + } + if ($k === 'media/image/aspect11') { + $photosq = bin2hex(trim($v)); + } + if ($k === 'media/image/default') { + $photo = bin2hex(trim($v)); + } + } + } + + if (!empty($nick)) { + $args['nickname'] = $nick; + } elseif (!empty($first)) { + $args['nickname'] = $first; + } + + if (!empty($photosq)) { + $args['photo'] = $photosq; + } elseif (!empty($photo)) { + $args['photo'] = $photo; + } + + $args['openid_url'] = Strings::escapeTags(trim(Session::get('openid_identity'))); + + return 'register?' . http_build_query($args); + } +} diff --git a/src/Module/Security/Logout.php b/src/Module/Security/Logout.php new file mode 100644 index 0000000000..062d55687b --- /dev/null +++ b/src/Module/Security/Logout.php @@ -0,0 +1,45 @@ + + */ +class Logout extends BaseModule +{ + /** + * @brief Process logout requests + */ + public static function init(array $parameters = []) + { + $visitor_home = null; + if (remote_user()) { + $visitor_home = Profile::getMyURL(); + Cache::delete('zrlInit:' . $visitor_home); + } + + Hook::callAll("logging_out"); + Session::clear(); + + if ($visitor_home) { + System::externalRedirect($visitor_home); + } else { + info(L10n::t('Logged out.')); + self::getApp()->internalRedirect(); + } + } +} diff --git a/src/Module/Security/TwoFactor/Recovery.php b/src/Module/Security/TwoFactor/Recovery.php new file mode 100644 index 0000000000..90e1488ed9 --- /dev/null +++ b/src/Module/Security/TwoFactor/Recovery.php @@ -0,0 +1,75 @@ +setForUser($a, $a->user, true, true); + } else { + notice(L10n::t('Invalid code, please retry.')); + } + } + } + + public static function content(array $parameters = []) + { + if (!local_user()) { + self::getApp()->internalRedirect(); + } + + // Already authenticated with 2FA token + if (Session::get('2fa')) { + self::getApp()->internalRedirect(); + } + + return Renderer::replaceMacros(Renderer::getMarkupTemplate('twofactor/recovery.tpl'), [ + '$form_security_token' => self::getFormSecurityToken('twofactor_recovery'), + + '$title' => L10n::t('Two-factor recovery'), + '$message' => L10n::t('

You can enter one of your one-time recovery codes in case you lost access to your mobile device.

'), + '$recovery_message' => L10n::t('Don’t have your phone? Enter a two-factor recovery code', '2fa/recovery'), + '$recovery_code' => ['recovery_code', L10n::t('Please enter a recovery code'), '', '', '', 'placeholder="000000-000000"'], + '$recovery_label' => L10n::t('Submit recovery code and complete login'), + ]); + } +} diff --git a/src/Module/Security/TwoFactor/Verify.php b/src/Module/Security/TwoFactor/Verify.php new file mode 100644 index 0000000000..10327aea59 --- /dev/null +++ b/src/Module/Security/TwoFactor/Verify.php @@ -0,0 +1,74 @@ +verifyKey(PConfig::get(local_user(), '2fa', 'secret'), $code); + + // The same code can't be used twice even if it's valid + if ($valid && Session::get('2fa') !== $code) { + Session::set('2fa', $code); + + // Resume normal login workflow + /** @var Authentication $authentication */ + $authentication = self::getClass(Authentication::class); + $authentication->setForUser($a, $a->user, true, true); + } else { + self::$errors[] = L10n::t('Invalid code, please retry.'); + } + } + } + + public static function content(array $parameters = []) + { + if (!local_user()) { + self::getApp()->internalRedirect(); + } + + // Already authenticated with 2FA token + if (Session::get('2fa')) { + self::getApp()->internalRedirect(); + } + + return Renderer::replaceMacros(Renderer::getMarkupTemplate('twofactor/verify.tpl'), [ + '$form_security_token' => self::getFormSecurityToken('twofactor_verify'), + + '$title' => L10n::t('Two-factor authentication'), + '$message' => L10n::t('

Open the two-factor authentication app on your device to get an authentication code and verify your identity.

'), + '$errors_label' => L10n::tt('Error', 'Errors', count(self::$errors)), + '$errors' => self::$errors, + '$recovery_message' => L10n::t('Don’t have your phone? Enter a two-factor recovery code', '2fa/recovery'), + '$verify_code' => ['verify_code', L10n::t('Please enter a code from your authentication app'), '', '', 'required', 'autofocus placeholder="000000"', 'tel'], + '$verify_label' => L10n::t('Verify code and complete login'), + ]); + } +} diff --git a/src/Module/Settings/TwoFactor/AppSpecific.php b/src/Module/Settings/TwoFactor/AppSpecific.php index 72b233f422..fe7423c5d2 100644 --- a/src/Module/Settings/TwoFactor/AppSpecific.php +++ b/src/Module/Settings/TwoFactor/AppSpecific.php @@ -9,7 +9,7 @@ use Friendica\Core\PConfig; use Friendica\Core\Renderer; use Friendica\Model\TwoFactor\AppSpecificPassword; use Friendica\Module\BaseSettingsModule; -use Friendica\Module\Login; +use Friendica\Module\Security\Login; /** * // Page 5: 2FA enabled, app-specific password generation diff --git a/src/Module/Settings/TwoFactor/Index.php b/src/Module/Settings/TwoFactor/Index.php index 34d6f97b49..03c866ce89 100644 --- a/src/Module/Settings/TwoFactor/Index.php +++ b/src/Module/Settings/TwoFactor/Index.php @@ -12,7 +12,7 @@ use Friendica\Model\TwoFactor\AppSpecificPassword; use Friendica\Model\TwoFactor\RecoveryCode; use Friendica\Model\User; use Friendica\Module\BaseSettingsModule; -use Friendica\Module\Login; +use Friendica\Module\Security\Login; use PragmaRX\Google2FA\Google2FA; class Index extends BaseSettingsModule diff --git a/src/Module/Settings/TwoFactor/Recovery.php b/src/Module/Settings/TwoFactor/Recovery.php index 0d7de7d902..8bd40bec98 100644 --- a/src/Module/Settings/TwoFactor/Recovery.php +++ b/src/Module/Settings/TwoFactor/Recovery.php @@ -9,7 +9,7 @@ use Friendica\Core\PConfig; use Friendica\Core\Renderer; use Friendica\Model\TwoFactor\RecoveryCode; use Friendica\Module\BaseSettingsModule; -use Friendica\Module\Login; +use Friendica\Module\Security\Login; /** * // Page 3: 2FA enabled but not verified, show recovery codes diff --git a/src/Module/Settings/TwoFactor/Verify.php b/src/Module/Settings/TwoFactor/Verify.php index 63c186e3a8..28ee999d14 100644 --- a/src/Module/Settings/TwoFactor/Verify.php +++ b/src/Module/Settings/TwoFactor/Verify.php @@ -14,7 +14,7 @@ use Friendica\Core\PConfig; use Friendica\Core\Renderer; use Friendica\Core\Session; use Friendica\Module\BaseSettingsModule; -use Friendica\Module\Login; +use Friendica\Module\Security\Login; use PragmaRX\Google2FA\Google2FA; /** diff --git a/src/Module/TwoFactor/Recovery.php b/src/Module/TwoFactor/Recovery.php deleted file mode 100644 index 371b7d7d53..0000000000 --- a/src/Module/TwoFactor/Recovery.php +++ /dev/null @@ -1,75 +0,0 @@ -setForUser($a, $a->user, true, true); - } else { - notice(L10n::t('Invalid code, please retry.')); - } - } - } - - public static function content(array $parameters = []) - { - if (!local_user()) { - self::getApp()->internalRedirect(); - } - - // Already authenticated with 2FA token - if (Session::get('2fa')) { - self::getApp()->internalRedirect(); - } - - return Renderer::replaceMacros(Renderer::getMarkupTemplate('twofactor/recovery.tpl'), [ - '$form_security_token' => self::getFormSecurityToken('twofactor_recovery'), - - '$title' => L10n::t('Two-factor recovery'), - '$message' => L10n::t('

You can enter one of your one-time recovery codes in case you lost access to your mobile device.

'), - '$recovery_message' => L10n::t('Don’t have your phone? Enter a two-factor recovery code', '2fa/recovery'), - '$recovery_code' => ['recovery_code', L10n::t('Please enter a recovery code'), '', '', '', 'placeholder="000000-000000"'], - '$recovery_label' => L10n::t('Submit recovery code and complete login'), - ]); - } -} diff --git a/src/Module/TwoFactor/Verify.php b/src/Module/TwoFactor/Verify.php deleted file mode 100644 index 828f125498..0000000000 --- a/src/Module/TwoFactor/Verify.php +++ /dev/null @@ -1,74 +0,0 @@ -verifyKey(PConfig::get(local_user(), '2fa', 'secret'), $code); - - // The same code can't be used twice even if it's valid - if ($valid && Session::get('2fa') !== $code) { - Session::set('2fa', $code); - - // Resume normal login workflow - /** @var Authentication $authentication */ - $authentication = self::getClass(Authentication::class); - $authentication->setForUser($a, $a->user, true, true); - } else { - self::$errors[] = L10n::t('Invalid code, please retry.'); - } - } - } - - public static function content(array $parameters = []) - { - if (!local_user()) { - self::getApp()->internalRedirect(); - } - - // Already authenticated with 2FA token - if (Session::get('2fa')) { - self::getApp()->internalRedirect(); - } - - return Renderer::replaceMacros(Renderer::getMarkupTemplate('twofactor/verify.tpl'), [ - '$form_security_token' => self::getFormSecurityToken('twofactor_verify'), - - '$title' => L10n::t('Two-factor authentication'), - '$message' => L10n::t('

Open the two-factor authentication app on your device to get an authentication code and verify your identity.

'), - '$errors_label' => L10n::tt('Error', 'Errors', count(self::$errors)), - '$errors' => self::$errors, - '$recovery_message' => L10n::t('Don’t have your phone? Enter a two-factor recovery code', '2fa/recovery'), - '$verify_code' => ['verify_code', L10n::t('Please enter a code from your authentication app'), '', '', 'required', 'autofocus placeholder="000000"', 'tel'], - '$verify_label' => L10n::t('Verify code and complete login'), - ]); - } -} diff --git a/static/routes.config.php b/static/routes.config.php index 15e7383a4b..9dced33107 100644 --- a/static/routes.config.php +++ b/static/routes.config.php @@ -23,8 +23,8 @@ return [ ], '/2fa' => [ - '[/]' => [Module\TwoFactor\Verify::class, [R::GET, R::POST]], - '/recovery' => [Module\TwoFactor\Recovery::class, [R::GET, R::POST]], + '[/]' => [Module\Security\TwoFactor\Verify::class, [R::GET, R::POST]], + '/recovery' => [Module\Security\TwoFactor\Recovery::class, [R::GET, R::POST]], ], '/api' => [ @@ -156,8 +156,8 @@ return [ '/like/{item:\d+}' => [Module\Like::class, [R::GET]], '/localtime' => [Module\Debug\Localtime::class, [R::GET, R::POST]], - '/login' => [Module\Login::class, [R::GET, R::POST]], - '/logout' => [Module\Logout::class, [R::GET, R::POST]], + '/login' => [Module\Security\Login::class, [R::GET, R::POST]], + '/logout' => [Module\Security\Logout::class, [R::GET, R::POST]], '/magic' => [Module\Magic::class, [R::GET]], '/maintenance' => [Module\Maintenance::class, [R::GET]], '/manifest' => [Module\Manifest::class, [R::GET]],