3 * @copyright Copyright (C) 2010-2022, the Friendica project
5 * @license GNU AGPL version 3 or any later version
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Affero General Public License as
9 * published by the Free Software Foundation, either version 3 of the
10 * License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Affero General Public License for more details.
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
22 namespace Friendica\Module\Security;
25 use Friendica\BaseModule;
26 use Friendica\Core\Config\Capability\IManageConfigValues;
27 use Friendica\Core\Hook;
28 use Friendica\Core\L10n;
29 use Friendica\Core\Renderer;
30 use Friendica\Core\Session\Capability\IHandleUserSessions;
32 use Friendica\Module\Register;
33 use Friendica\Module\Response;
34 use Friendica\Security\Authentication;
35 use Friendica\Util\Profiler;
36 use Psr\Log\LoggerInterface;
41 class Login extends BaseModule
43 /** @var Authentication */
46 /** @var IManageConfigValues */
49 /** @var IHandleUserSessions */
52 public function __construct(Authentication $auth, IManageConfigValues $config, IHandleUserSessions $session, L10n $l10n, App\BaseURL $baseUrl, App\Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, array $server, array $parameters = [])
54 parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters);
57 $this->config = $config;
58 $this->session = $session;
61 protected function content(array $request = []): string
63 $return_path = $request['return_path'] ?? $this->session->pop('return_path', '') ;
65 if ($this->session->getLocalUserId()) {
66 $this->baseUrl->redirect($return_path);
69 return self::form($return_path, intval($this->config->get('config', 'register_policy')) !== \Friendica\Module\Register::CLOSED);
72 protected function post(array $request = [])
74 $this->session->clear();
78 empty($request['password'])
79 && (!empty($request['openid_url'])
80 || !empty($request['username']))
82 $openid_url = trim(($request['openid_url'] ?? '') ?: $request['username']);
84 $this->auth->withOpenId($openid_url, !empty($request['remember']));
87 if (!empty($request['auth-params']) && $request['auth-params'] === 'login') {
88 $this->auth->withPassword(
90 trim($request['username']),
91 trim($request['password']),
92 !empty($request['remember']),
93 $request['return_path'] ?? ''
99 * Wrapper for adding a login box.
101 * @param string|null $return_path The path relative to the base the user should be sent back to after login completes.
102 * @param bool $register If $register == true provide a registration link.
103 * This will almost always depend on the value of config.register_policy.
105 * @return string Returns the complete html for inserting into the page
107 * @throws \Friendica\Network\HTTPException\InternalServerErrorException
108 * @throws \Friendica\Network\HTTPException\ServiceUnavailableException
109 * @hooks 'login_hook' string $o
111 public static function form(string $return_path = null, bool $register = false): string
113 $noid = DI::config()->get('system', 'no_openid');
116 DI::session()->remove('openid_identity');
117 DI::session()->remove('openid_attributes');
121 if ($register && intval(DI::config()->get('config', 'register_policy')) !== Register::CLOSED) {
123 'title' => DI::l10n()->t('Create a New Account'),
124 'desc' => DI::l10n()->t('Register'),
125 'url' => self::getRegisterURL()
129 if (DI::userSession()->getLocalUserId()) {
130 $tpl = Renderer::getMarkupTemplate('logout.tpl');
132 DI::page()['htmlhead'] .= Renderer::replaceMacros(
133 Renderer::getMarkupTemplate('login_head.tpl'),
135 '$baseurl' => DI::baseUrl()->get(true)
139 $tpl = Renderer::getMarkupTemplate('login.tpl');
142 if (!empty(DI::session()->get('openid_identity'))) {
143 $openid_title = DI::l10n()->t('Your OpenID: ');
144 $openid_readonly = true;
145 $identity = DI::session()->get('openid_identity');
146 $username_desc = DI::l10n()->t('Please enter your username and password to add the OpenID to your existing account.');
148 $openid_title = DI::l10n()->t('Or login using OpenID: ');
149 $openid_readonly = false;
154 $o = Renderer::replaceMacros(
157 '$dest_url' => DI::baseUrl()->get(true) . '/login',
158 '$logout' => DI::l10n()->t('Logout'),
159 '$login' => DI::l10n()->t('Login'),
161 '$lname' => ['username', DI::l10n()->t('Nickname or Email: '), '', $username_desc],
162 '$lpassword' => ['password', DI::l10n()->t('Password: '), '', ''],
163 '$lremember' => ['remember', DI::l10n()->t('Remember me'), 0, ''],
166 '$lopenid' => ['openid_url', $openid_title, $identity, '', $openid_readonly],
168 '$hiddens' => ['return_path' => $return_path ?? DI::args()->getQueryString()],
172 '$lostpass' => DI::l10n()->t('Forgot your password?'),
173 '$lostlink' => DI::l10n()->t('Password Reset'),
175 '$tostitle' => DI::l10n()->t('Website Terms of Service'),
176 '$toslink' => DI::l10n()->t('terms of service'),
178 '$privacytitle' => DI::l10n()->t('Website Privacy Policy'),
179 '$privacylink' => DI::l10n()->t('privacy policy'),
183 Hook::callAll('login_hook', $o);
189 * Get the URL to the register page and add OpenID parameters to it
191 private static function getRegisterURL(): string
193 if (empty(DI::session()->get('openid_identity'))) {
198 $attr = DI::session()->get('openid_attributes', []);
200 if (is_array($attr) && count($attr)) {
201 foreach ($attr as $k => $v) {
202 if ($k === 'namePerson/friendly') {
205 if ($k === 'namePerson/first') {
208 if ($k === 'namePerson') {
209 $args['username'] = trim($v);
211 if ($k === 'contact/email') {
212 $args['email'] = trim($v);
214 if ($k === 'media/image/aspect11') {
215 $photosq = bin2hex(trim($v));
217 if ($k === 'media/image/default') {
218 $photo = bin2hex(trim($v));
224 $args['nickname'] = $nick;
225 } elseif (!empty($first)) {
226 $args['nickname'] = $first;
229 if (!empty($photosq)) {
230 $args['photo'] = $photosq;
231 } elseif (!empty($photo)) {
232 $args['photo'] = $photo;
235 $args['openid_url'] = trim(DI::session()->get('openid_identity'));
237 return 'register?' . http_build_query($args);