4 namespace Friendica\Module\Settings\TwoFactor;
7 use BaconQrCode\Renderer\Image\SvgImageBackEnd;
8 use BaconQrCode\Renderer\ImageRenderer;
9 use BaconQrCode\Renderer\RendererStyle\RendererStyle;
10 use BaconQrCode\Writer;
11 use Friendica\BaseModule;
12 use Friendica\Core\L10n;
13 use Friendica\Core\PConfig;
14 use Friendica\Core\Renderer;
15 use Friendica\Core\Session;
17 use Friendica\Module\BaseSettingsModule;
18 use Friendica\Module\Security\Login;
19 use PragmaRX\Google2FA\Google2FA;
22 * // Page 4: 2FA enabled but not verified, QR code and verification
24 * @package Friendica\Module\TwoFactor\Settings
26 class Verify extends BaseSettingsModule
28 public static function init(array $parameters = [])
34 $secret = DI::pConfig()->get(local_user(), '2fa', 'secret');
35 $verified = DI::pConfig()->get(local_user(), '2fa', 'verified');
37 if ($secret && $verified) {
38 DI::baseUrl()->redirect('settings/2fa');
41 if (!self::checkFormSecurityToken('settings_2fa_password', 't')) {
42 notice(L10n::t('Please enter your password to access this page.'));
43 DI::baseUrl()->redirect('settings/2fa');
47 public static function post(array $parameters = [])
53 if (($_POST['action'] ?? '') == 'verify') {
54 self::checkFormSecurityTokenRedirectOnError('settings/2fa/verify', 'settings_2fa_verify');
56 $google2fa = new Google2FA();
58 $valid = $google2fa->verifyKey(DI::pConfig()->get(local_user(), '2fa', 'secret'), $_POST['verify_code'] ?? '');
61 PConfig::set(local_user(), '2fa', 'verified', true);
62 Session::set('2fa', true);
64 notice(L10n::t('Two-factor authentication successfully activated.'));
66 DI::baseUrl()->redirect('settings/2fa');
68 notice(L10n::t('Invalid code, please retry.'));
73 public static function content(array $parameters = [])
76 return Login::form('settings/2fa/verify');
79 parent::content($parameters);
81 $company = 'Friendica';
82 $holder = Session::get('my_address');
83 $secret = DI::pConfig()->get(local_user(), '2fa', 'secret');
85 $otpauthUrl = (new Google2FA())->getQRCodeUrl($company, $holder, $secret);
87 $renderer = (new \BaconQrCode\Renderer\Image\Svg())
91 $writer = new Writer($renderer);
93 $qrcode_image = str_replace('<?xml version="1.0" encoding="UTF-8"?>', '', $writer->writeString($otpauthUrl));
95 $shortOtpauthUrl = explode('?', $otpauthUrl)[0];
97 $manual_message = L10n::t('<p>Or you can submit the authentication settings manually:</p>
101 <dt>Account Name</dt>
107 <dt>Number of digits</dt>
109 <dt>Hashing algorithm</dt>
111 </dl>', $company, $holder, $secret);
113 return Renderer::replaceMacros(Renderer::getMarkupTemplate('settings/twofactor/verify.tpl'), [
114 '$form_security_token' => self::getFormSecurityToken('settings_2fa_verify'),
115 '$password_security_token' => self::getFormSecurityToken('settings_2fa_password'),
117 '$title' => L10n::t('Two-factor code verification'),
118 '$help_label' => L10n::t('Help'),
119 '$message' => L10n::t('<p>Please scan this QR Code with your authenticator app and submit the provided code.</p>'),
120 '$qrcode_image' => $qrcode_image,
121 '$qrcode_url_message' => L10n::t('<p>Or you can open the following URL in your mobile devicde:</p><p><a href="%s">%s</a></p>', $otpauthUrl, $shortOtpauthUrl),
122 '$manual_message' => $manual_message,
123 '$company' => $company,
124 '$holder' => $holder,
125 '$secret' => $secret,
127 '$verify_code' => ['verify_code', L10n::t('Please enter a code from your authentication app'), '', '', 'required', 'autofocus placeholder="000000"'],
128 '$verify_label' => L10n::t('Verify code and enable two-factor authentication'),