TYPO3 Tipps und Tricks: Manueller/Programmatischer Login in Controller-Action (TYPO3 9)

Manchmal gibt es bei Web-Projekten die Notwendigkeit einen Login programmatisch (manuell, im PHP-Code) durchzuführen. Ein Kunde hat vor kurzem folgende Anforderung gestellt: Nach erfolgreicher Benutzeraccount-Aktivierung (Klick auf Link in E-Mail) soll der Benutzer automatisch angemeldet (eingeloggt) sein (ohne Eingabe von Benutzernamen/Passwort). Hier zeige ich einen Lösungsvorschlag für TYPO3 Version 9.

Bei TYPO3 Version 9 erfolgt der Login automatisch über die übermittelten POST-Felder (logintype, user, pass) mittels des Authentication-Services. Wenn man nun im Controller einen Login durchführen will, muss man eine eigene Instanz des Services „FrontendUserAuthentication“ erstellen und diesen ausführen/starten. Der Trick dabei ist, vorher einfach die benötigten POST-Daten manuell zu setzen. 

public static function loginUser($user){    $_POST['logintype'] = 'login';    $_POST['user'] = $user->getEmail();    $_POST['pass'] = $user->getPassword();    $authService = GeneralUtility::makeInstance(FrontendUserAuthentication::class);    $authService->start();}

In diesem Fall würde die Authentifizierung natürlich fehlschlagen, da wir das Passwort nicht als Klartext, sondern gehasht und verschlüsselt übertragen. Dafür müssen wir nun noch einen eigenen Authentication Service erstellen und diesen erweitern. Dazu in der ext_localconf.php:

ExtensionManagementUtility::addService($_EXTKEY, 'auth', FeBasedAuthenticationService::class, array(    'title' => 'Authentication Service for fe_users',    'description' => 'Authentication Service for fe_users',    'subtype' => 'authUserFE',    'available' => true,    'priority' => 90,    'quality' => 90,    'os' => '',    'exec' => '',    'className' => FeMailBasedAuthenticationService::class));

In diesem müssen wir nun die authUser-Methode überschreiben:

class FeBasedAuthenticationService extends AuthenticationService{  public function authUser(array $user): int  {      ...         if (!$isValidPassword) {          // Failed login attempt - wrong password          $this->writeLogMessage(TYPO3_MODE . ' Authentication failed - wrong password for username \'%s\'', $submittedUsername);          $message = 'Login-attempt from ###IP###, username \'%s\', password not accepted!';          $this->writelog(255, 3, 3, 1, $message, [$submittedUsername]);          $this->logger->info(sprintf($message, $submittedUsername));          // Responsible, authentication failed, do NOT check other services          //check submitted hashed password (login for activation)          if($submittedPassword == $passwordHashInDatabase) {              return 200;          }          return 0;      }         ...  }}

Die Methode ist mit dem Core (TYPO3\CMS\Core\Authentication\ AuthenticationService) bis auf diese Änderung ident:

if($submittedPassword == $passwordHashInDatabase) {    return 200;}

Nun kann ein login auch per PHP-Code in einer Action oder sonst wo innerhalb von TYPO3 leicht durchgeführt werden, aus Sicherheitsgründen sollte danach ein Redirect durchgeführt werden.

//login UserLoginUtility::loginUser($user);$this->redirect('successviewactivated', 'User');