Wir hatten einen ähnlichen Fall (Contao 4.13), dass wir einen QR-Code per Post verschickt haben und die Nutzer beim Scan (oder manueller Eingabe) direkt angemeldet werden sollten. Der entscheidende Hinweis war tatsächlich in dem Posting des OP hier. Es ist nur ein minimaler Unterschied, durch den es letztendlich funktioniert hat. Beim UsernamePasswordToken wird kein Password angegeben. Den Password Parameter gibt es nämlich im c'tor von UsernamePasswordToken in symfony 6 nicht:
https://github.com/symfony/symfony/b...dToken.php#L25
Der Code sieht dann so aus:
PHP-Code:
// create the user session
$token = new UsernamePasswordToken($user, 'contao_frontend', $user->getRoles());
$authenticatedToken = $this->authenticationManager->authenticate($token);
$this->tokenStorage->setToken($authenticatedToken);
Die Authentifizierung läuft vorher ab, indem der Nutzer mit dem Code aus der DB geladen wird. Der Code ist eine praktisch nicht erratbare Buchstaben/Zahlen Kombination, die einen eindeutigen index in der DB darstellt. Hier die komplette Login Methode:
PHP-Code:
public function loginWithCode(string $code): ?FrontendUser
{
// try to load the usr via the secret unique personal code, e.g. in QR as https://site.com/code-login?webCode=123456
$memberModel = MemberModel::findBy('webCode', $code);
if (!$memberModel) {
// user not found, code is invalid
return null;
}
// code is valid, load the user by its username
$user = FrontendUser::loadUserByIdentifier($memberModel->username);
if (!$user) {
// something bad happened, no login
return null;
}
try {
// check pre and post auth hooks
$this->userChecker->checkPreAuth($user);
$this->userChecker->checkPostAuth($user);
} catch (Exception $ex) {
return null;
}
// update the lastLogin and currentLogin field
$user->lastLogin = $user->currentLogin;
$user->currentLogin = time();
$user->save();
// create the user session
$token = new UsernamePasswordToken($user, 'contao_frontend', $user->getRoles());
$authenticatedToken = $this->authenticationManager->authenticate($token);
$this->tokenStorage->setToken($authenticatedToken);
// log the login event
static::getContainer()->get('monolog.logger.contao')->log(
LogLevel::INFO,
sprintf('User "%s" has logged in with code', $user->username),
['contao' => new ContaoContext(__METHOD__, TL_ACCESS)]
);
return $user;
}
Der Vollständigkeit halber hier der c'tor der Klasse:
PHP-Code:
class CodeAuthenticator extends System
{
private AuthenticationManagerInterface $authenticationManager;
private TokenStorageInterface $tokenStorage;
private UserChecker $userChecker;
public function __construct(
AuthenticationManagerInterface $authenticationManager,
TokenStorageInterface $tokenStorage,
UserChecker $userChecker
)
{
$this->authenticationManager = $authenticationManager;
$this->tokenStorage = $tokenStorage;
$this->userChecker = $userChecker;
}
public function loginWithCode(string $code): ?FrontendUser{...}
}
Bei einer User/Password Authentifizierung muss natürlich die User/Password Kombi vorher selbst geprüft werden, vermutlich gibt es hier schon was Passendes in Symfony selbst. Das habe ich jetzt nicht recherchiert...
Lesezeichen