This is too much of a hassle for me. I do not have time for that. Sorry.
I have now analyzed the code. The Problem is the login function. They will be called in User-Class in \vendor\yiisoft\yii2\web folder:
public function login(IdentityInterface $identity, $duration = 0)
{
if ($this->beforeLogin($identity, false, $duration)) {
$this->switchIdentity($identity, $duration);
$id = $identity->getId();
$ip = Yii::$app->getRequest()->getUserIP();
if ($this->enableSession) {
$log = "User '$id' logged in from $ip with duration $duration.";
} else {
$log = "User '$id' logged in from $ip. Session not enabled.";
}
$this->regenerateCsrfToken();
Yii::info($log, __METHOD__);
$this->afterLogin($identity, false, $duration);
}
return !$this->getIsGuest();
}
In this function the beforeLogin function will be called:
protected function beforeLogin($identity, $cookieBased, $duration)
{
$event = new UserEvent([
'identity' => $identity,
'cookieBased' => $cookieBased,
'duration' => $duration,
]);
$this->trigger(self::EVENT_BEFORE_LOGIN, $event);
return $event->isValid;
}
Before the trigger function the field isValid from the Array $event has the value true.
After trigger function is called the field isValid has the value false.
Here is the trigger function (\vendor\yiisoft\yii2\base\Component.php):
public function trigger($name, Event $event = null)
{
$this->ensureBehaviors();
$eventHandlers = [];
foreach ($this->_eventWildcards as $wildcard => $handlers) {
if (StringHelper::matchWildcard($wildcard, $name)) {
$eventHandlers[] = $handlers;
}
}
if (!empty($this->_events[$name])) {
$eventHandlers[] = $this->_events[$name];
}
if (!empty($eventHandlers)) {
$eventHandlers = call_user_func_array('array_merge', $eventHandlers);
if ($event === null) {
$event = new Event();
}
if ($event->sender === null) {
$event->sender = $this;
}
$event->handled = false;
$event->name = $name;
foreach ($eventHandlers as $handler) {
$event->data = $handler[1];
call_user_func($handler[0], $event);
// stop further handling if the event is handled
if ($event->handled) {
return;
}
}
}
// invoke class-level attached handlers
Event::trigger($this, $name, $event);
}
So if the field isValid is false, the login will not done. This is only so if the field mfa_secret in the database is filled with a string. Otherwise if the mfa_secret field is empty, the login will done and the isValid field is true.
I can only imagine that it may be due to the rules for the fields used in the model user:
/**
* {@inheritdoc}
*/
public function rules()
{
return [
[['username', 'email', 'password', 'customer'], 'required', 'on' => self::SCENARIO_DEFAULT],
[['username', 'email', 'customer'], 'required', 'on' => self::SCENARIO_USER_UPDATE],
[['username', 'email'], 'unique'],
//[['email'], 'unique', 'message' => 'Es existiert bereits ein Benutzer mit dieser E-Mail-Adresse'],
[['email'], 'email', 'message' => 'Diese E-Mail-Adresse ist nicht korrekt'],
[['last_login', 'customer', 'active'], 'safe'],
[['username', 'fullname', 'email', 'mfa_secret'], 'string', 'max' => 255],
[['firstname', 'lastname'], 'string', 'max' => 100],
[['password'], 'string', 'max' => 64],
];
}
But I have defined the mfa_secret field only as a string with max 255 characters.