‪TYPO3CMS  ‪main
ResetPasswordController.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
19 
20 use Psr\Http\Message\ResponseInterface;
21 use Psr\Http\Message\ServerRequestInterface;
43 
49 #[AsController]
51 {
53 
54  protected string ‪$loginProvider = '';
55  protected ‪ViewInterface ‪$view;
56 
57  public function ‪__construct(
58  protected readonly ‪Context $context,
59  protected readonly ‪Locales $locales,
60  protected readonly ‪Features $features,
61  protected readonly ‪UriBuilder $uriBuilder,
62  protected readonly ‪PageRenderer $pageRenderer,
63  protected readonly ‪PasswordReset $passwordReset,
64  protected readonly ‪Typo3Information $typo3Information,
65  protected readonly ‪AuthenticationStyleInformation $authenticationStyleInformation,
66  protected readonly ‪ExtensionConfiguration $extensionConfiguration,
67  protected readonly ‪BackendViewFactory $backendViewFactory,
68  ) {}
69 
73  public function ‪forgetPasswordFormAction(ServerRequestInterface $request): ResponseInterface
74  {
75  $this->‪initialize($request);
76  $this->‪initializeForgetPasswordView($request);
77  $this->pageRenderer->setBodyContent('<body>' . $this->view->render('Login/ForgetPasswordForm'));
78  return $this->pageRenderer->renderResponse();
79  }
80 
88  public function ‪initiatePasswordResetAction(ServerRequestInterface $request): ResponseInterface
89  {
90  $this->‪initialize($request);
91  $this->‪initializeForgetPasswordView($request);
92  $emailAddress = $request->getParsedBody()['email'] ?? '';
93  $this->view->assign('email', $emailAddress);
94  if (!GeneralUtility::validEmail($emailAddress)) {
95  $this->view->assign('invalidEmail', true);
96  } else {
97  $this->passwordReset->initiateReset($request, $this->context, $emailAddress);
98  $this->view->assign('resetInitiated', true);
99  }
100  $this->pageRenderer->setBodyContent('<body>' . $this->view->render('Login/ForgetPasswordForm'));
101  // Prevent time based information disclosure by waiting a random time
102  // before sending a response. This prevents that the response time
103  // can be an indicator if the used email exists or not. Wait a random
104  // time between 200 milliseconds and 3 seconds.
105  usleep(random_int(200000, 3000000));
106  return $this->pageRenderer->renderResponse();
107  }
108 
112  public function ‪passwordResetAction(ServerRequestInterface $request): ResponseInterface
113  {
114  $this->‪initialize($request);
115  $this->‪initializeResetPasswordView($request);
116  if (!$this->passwordReset->isValidResetTokenFromRequest($request)) {
117  $this->view->assign('invalidToken', true);
118  }
119  $this->pageRenderer->setBodyContent('<body>' . $this->view->render('Login/ResetPasswordForm'));
120  return $this->pageRenderer->renderResponse();
121  }
122 
130  public function ‪passwordResetFinishAction(ServerRequestInterface $request): ResponseInterface
131  {
132  // Token is invalid
133  if (!$this->passwordReset->isValidResetTokenFromRequest($request)) {
134  return $this->‪passwordResetAction($request);
135  }
136  $this->‪initialize($request);
137  $this->‪initializeResetPasswordView($request);
138  if ($this->passwordReset->resetPassword($request, $this->context)) {
139  $this->view->assign('resetExecuted', true);
140  } else {
141  $this->view->assign('error', true);
142  }
143  $this->pageRenderer->setBodyContent('<body>' . $this->view->render('Login/ResetPasswordForm'));
144  return $this->pageRenderer->renderResponse();
145  }
146 
147  protected function ‪initializeForgetPasswordView(ServerRequestInterface $request): void
148  {
149  $parameters = array_filter(['loginProvider' => $this->loginProvider]);
150  $this->view->assignMultiple([
151  'formUrl' => $this->uriBuilder->buildUriWithRedirect('password_forget_initiate_reset', $parameters, ‪RouteRedirect::createFromRequest($request)),
152  'returnUrl' => $this->uriBuilder->buildUriWithRedirect('login', $parameters, ‪RouteRedirect::createFromRequest($request)),
153  ]);
154  }
155 
156  protected function ‪initializeResetPasswordView(ServerRequestInterface $request): void
157  {
158  $token = $request->getQueryParams()['t'] ?? '';
159  $identity = $request->getQueryParams()['i'] ?? '';
160  $expirationDate = $request->getQueryParams()['e'] ?? '';
161  $parameters = array_filter(['loginProvider' => $this->loginProvider]);
162  $formUrl = $this->uriBuilder->buildUriWithRedirect(
163  'password_reset_finish',
164  array_filter(array_merge($parameters, [
165  't' => $token,
166  'i' => $identity,
167  'e' => $expirationDate,
168  ])),
170  );
171  $this->view->assignMultiple([
172  'token' => $token,
173  'identity' => $identity,
174  'expirationDate' => $expirationDate,
175  'formUrl' => $formUrl,
176  'restartUrl' => $this->uriBuilder->buildUriWithRedirect('password_forget', $parameters, ‪RouteRedirect::createFromRequest($request)),
177  'passwordRequirements' => $this->getPasswordRequirements(),
178  ]);
179  }
180 
181  protected function ‪initialize(ServerRequestInterface $request): void
182  {
183  $languageService = $this->‪getLanguageService();
184 
185  // Only allow to execute this if not logged in as a user right now
186  if ($this->context->getAspect('backend.user')->isLoggedIn()) {
188  new ‪RedirectResponse($this->uriBuilder->buildUriFromRoute('login'), 303),
189  1618342858
190  );
191  }
192 
193  // Fetch login provider from the request
194  $this->loginProvider = $request->getQueryParams()['loginProvider'] ?? '';
195 
196  // Try to get the preferred browser language
197  $httpAcceptLanguage = $request->getServerParams()['HTTP_ACCEPT_LANGUAGE'] ?? '';
198  $preferredBrowserLanguage = $this->locales->getPreferredClientLanguage($httpAcceptLanguage);
199 
200  // If we found a $preferredBrowserLanguage, which is not the default language
201  // initialize $this->getLanguageService() again with $preferredBrowserLanguage.
202  // Additionally, set the language to the backend user object, so labels in fluid views are translated
203  if ($preferredBrowserLanguage !== 'default') {
204  $languageService->init($preferredBrowserLanguage);
205  $this->‪getBackendUserAuthentication()->user['lang'] = $preferredBrowserLanguage;
206  }
207 
208  $this->‪setUpBasicPageRendererForBackend($this->pageRenderer, $this->extensionConfiguration, $request, $languageService);
209  $this->pageRenderer->setTitle('TYPO3 CMS Login: ' . (‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'] ?? ''));
210  $this->pageRenderer->loadJavaScriptModule('bootstrap');
211  $this->pageRenderer->loadJavaScriptModule('@typo3/backend/login.js');
212 
213  $this->view = $this->backendViewFactory->create($request);
214  $this->view->assignMultiple([
215  'enablePasswordReset' => $this->passwordReset->isEnabled(),
216  'referrerCheckEnabled' => $this->features->isFeatureEnabled('security.backend.enforceReferrer'),
217  'loginUrl' => (string)$request->getUri(),
218  ]);
219 
221  }
222 
223  protected function ‪provideCustomLoginStyling(): void
224  {
225  $languageService = $this->‪getLanguageService();
226  if (($backgroundImageStyles = $this->authenticationStyleInformation->getBackgroundImageStyles()) !== '') {
227  $this->pageRenderer->addCssInlineBlock('loginBackgroundImage', $backgroundImageStyles, useNonce: true);
228  }
229  if (($footerNote = $this->authenticationStyleInformation->getFooterNote()) !== '') {
230  $this->view->assign('loginFootnote', $footerNote);
231  }
232  if (($highlightColorStyles = $this->authenticationStyleInformation->getHighlightColorStyles()) !== '') {
233  $this->pageRenderer->addCssInlineBlock('loginHighlightColor', $highlightColorStyles, useNonce: true);
234  }
235  if (($logo = $this->authenticationStyleInformation->getLogo()) !== '') {
236  $logoAlt = $this->authenticationStyleInformation->getLogoAlt()
237  ?: $languageService->sL('LLL:EXT:backend/Resources/Private/Language/locallang_login.xlf:typo3.altText');
238  } else {
239  $logo = $this->authenticationStyleInformation->getDefaultLogo();
240  $logoAlt = $languageService->sL('LLL:EXT:backend/Resources/Private/Language/locallang_login.xlf:typo3.altText');
241  $this->pageRenderer->addCssInlineBlock('loginLogo', $this->authenticationStyleInformation->getDefaultLogoStyles(), useNonce: true);
242  }
243  $this->view->assignMultiple([
244  'logo' => $logo,
245  'logoAlt' => $logoAlt,
246  'images' => $this->authenticationStyleInformation->getSupportingImages(),
247  'copyright' => $this->typo3Information->getCopyrightNotice(),
248  ]);
249  }
250 
251  protected function ‪getPasswordRequirements(): array
252  {
253  $passwordPolicy = ‪$GLOBALS['TYPO3_CONF_VARS']['BE']['passwordPolicy'] ?? 'default';
254  $passwordPolicyValidator = GeneralUtility::makeInstance(
255  PasswordPolicyValidator::class,
256  PasswordPolicyAction::UPDATE_USER_PASSWORD,
257  is_string($passwordPolicy) ? $passwordPolicy : ''
258  );
259  return $passwordPolicyValidator->getRequirements();
260  }
261 
262  protected function ‪getLanguageService(): ‪LanguageService
263  {
264  return ‪$GLOBALS['LANG'];
265  }
266 
268  {
269  return ‪$GLOBALS['BE_USER'];
270  }
271 }
‪TYPO3\CMS\Backend\View\AuthenticationStyleInformation
Definition: AuthenticationStyleInformation.php:32
‪TYPO3\CMS\Backend\Controller\ResetPasswordController\initiatePasswordResetAction
‪initiatePasswordResetAction(ServerRequestInterface $request)
Definition: ResetPasswordController.php:87
‪TYPO3\CMS\Core\Information\Typo3Information
Definition: Typo3Information.php:28
‪TYPO3\CMS\Backend\Controller\ResetPasswordController\passwordResetAction
‪passwordResetAction(ServerRequestInterface $request)
Definition: ResetPasswordController.php:111
‪TYPO3\CMS\Core\View\ViewInterface
Definition: ViewInterface.php:24
‪TYPO3\CMS\Backend\View\BackendViewFactory
Definition: BackendViewFactory.php:35
‪TYPO3\CMS\Core\Configuration\ExtensionConfiguration
Definition: ExtensionConfiguration.php:47
‪TYPO3\CMS\Backend\Authentication\PasswordReset
Definition: PasswordReset.php:65
‪TYPO3\CMS\Backend\Template\PageRendererBackendSetupTrait
Definition: PageRendererBackendSetupTrait.php:45
‪TYPO3\CMS\Backend\Controller\ResetPasswordController\getBackendUserAuthentication
‪getBackendUserAuthentication()
Definition: ResetPasswordController.php:266
‪TYPO3\CMS\Core\Localization\Locales
Definition: Locales.php:36
‪TYPO3\CMS\Core\Context\Context
Definition: Context.php:54
‪TYPO3\CMS\Backend\Controller\ResetPasswordController\getLanguageService
‪getLanguageService()
Definition: ResetPasswordController.php:261
‪TYPO3\CMS\Core\Page\PageRenderer
Definition: PageRenderer.php:44
‪TYPO3\CMS\Backend\Controller\ResetPasswordController\__construct
‪__construct(protected readonly Context $context, protected readonly Locales $locales, protected readonly Features $features, protected readonly UriBuilder $uriBuilder, protected readonly PageRenderer $pageRenderer, protected readonly PasswordReset $passwordReset, protected readonly Typo3Information $typo3Information, protected readonly AuthenticationStyleInformation $authenticationStyleInformation, protected readonly ExtensionConfiguration $extensionConfiguration, protected readonly BackendViewFactory $backendViewFactory,)
Definition: ResetPasswordController.php:56
‪TYPO3\CMS\Backend\Controller\ResetPasswordController\provideCustomLoginStyling
‪provideCustomLoginStyling()
Definition: ResetPasswordController.php:222
‪TYPO3\CMS\Backend\Controller\ResetPasswordController\initializeResetPasswordView
‪initializeResetPasswordView(ServerRequestInterface $request)
Definition: ResetPasswordController.php:155
‪TYPO3\CMS\Backend\Controller\ResetPasswordController\initialize
‪initialize(ServerRequestInterface $request)
Definition: ResetPasswordController.php:180
‪TYPO3\CMS\Backend\Routing\RouteRedirect
Definition: RouteRedirect.php:30
‪TYPO3\CMS\Backend\Routing\UriBuilder
Definition: UriBuilder.php:44
‪TYPO3\CMS\Core\PasswordPolicy\PasswordPolicyValidator
Definition: PasswordPolicyValidator.php:27
‪TYPO3\CMS\Core\Configuration\Features
Definition: Features.php:56
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication
Definition: BackendUserAuthentication.php:62
‪TYPO3\CMS\Core\Http\PropagateResponseException
Definition: PropagateResponseException.php:47
‪TYPO3\CMS\Core\Http\RedirectResponse
Definition: RedirectResponse.php:30
‪TYPO3\CMS\Backend\Controller\ResetPasswordController\$view
‪ViewInterface $view
Definition: ResetPasswordController.php:54
‪TYPO3\CMS\Backend\Controller\ResetPasswordController\$loginProvider
‪string $loginProvider
Definition: ResetPasswordController.php:53
‪TYPO3\CMS\Backend\Controller\ResetPasswordController\initializeForgetPasswordView
‪initializeForgetPasswordView(ServerRequestInterface $request)
Definition: ResetPasswordController.php:146
‪TYPO3\CMS\Backend\Controller\ResetPasswordController\passwordResetFinishAction
‪passwordResetFinishAction(ServerRequestInterface $request)
Definition: ResetPasswordController.php:129
‪TYPO3\CMS\Backend\Controller\ResetPasswordController
Definition: ResetPasswordController.php:51
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Backend\Template\PageRendererBackendSetupTrait\setUpBasicPageRendererForBackend
‪setUpBasicPageRendererForBackend(PageRenderer $pageRenderer, ExtensionConfiguration $extensionConfiguration, ServerRequestInterface $request, LanguageService $languageService,)
Definition: PageRendererBackendSetupTrait.php:49
‪TYPO3\CMS\Backend\Attribute\AsController
Definition: AsController.php:25
‪TYPO3\CMS\Core\PasswordPolicy\PasswordPolicyAction
‪PasswordPolicyAction
Definition: PasswordPolicyAction.php:24
‪TYPO3\CMS\Core\Localization\LanguageService
Definition: LanguageService.php:46
‪TYPO3\CMS\Backend\Routing\RouteRedirect\createFromRequest
‪static createFromRequest(ServerRequestInterface $request)
Definition: RouteRedirect.php:58
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:52
‪TYPO3\CMS\Backend\Controller\ResetPasswordController\forgetPasswordFormAction
‪forgetPasswordFormAction(ServerRequestInterface $request)
Definition: ResetPasswordController.php:72
‪TYPO3\CMS\Backend\Controller
Definition: AboutController.php:18
‪TYPO3\CMS\Backend\Controller\ResetPasswordController\getPasswordRequirements
‪getPasswordRequirements()
Definition: ResetPasswordController.php:250