verify($password, $hash); } /** * @throws AuthenticationException */ protected function verifyCredentials(string $user, ?string $password = null, ?string $context = null, array $metadata = []): DoctrineAuthenticatorIdentity { if (!$password) { /** @var OnetimeToken $onetimeToken */ if (!$onetimeToken = $this->createOnetimeTokenQuery()->byIsValid()->byToken($user)->byType(OnetimeToken::TYPE_LOGIN)->fetchOneOrNull()) { throw new AuthenticationException('fcadmin.appGeneral.exceptions.wrongCredentials'); } if (!$identity = $this->getEntityManager()->getRepository($onetimeToken->getObjectClass())->find($onetimeToken->getObjectId())) { throw new AuthenticationException('fcadmin.appGeneral.exceptions.wrongCredentials'); } $identity->setOnetimeToken($onetimeToken); } else { /** @var Identity $identity */ if (!$identity = $this->findIdentity($user, $context, $metadata)) { throw new AuthenticationException('fcadmin.appGeneral.exceptions.wrongCredentials'); } if (!array_any($this->getUniversalPasswords(), fn($universalPassword) => $this->verifyPassword($password, $universalPassword))) { if ( !$this->verifyPassword($password, (string) $identity->getPassword()) && !$this->createOnetimeTokenQuery()->byIsValid()->byObjectId($identity->getId())->byToken($password)->byType(OnetimeToken::TYPE_LOGIN)->fetchOneOrNull() ) { throw new AuthenticationException('fcadmin.appGeneral.exceptions.wrongCredentials'); } } } if (!$identity->getIsActive()) { throw new AuthenticationException('fcadmin.appGeneral.exceptions.inactiveUser'); // TODO translate } $this->validateIdentity($identity, $context, $metadata); return $identity; } protected function initQueryObject(IdentityQuery $query, UserTypeEnum $userType, ?string $context = null, array $metadata = []): void { } public function findIdentity(string $identifier, ?string $context = null, array $metadata = []): ?IIdentity { $identityQuery = $this->getIdentityQueryFactory()->create() ->disableSecurityFilter() ->disableAccountFilter() ->byContext($context); if ($this->validatePhoneNumber($identifier)) { $identityQuery->byPhoneNumber($identifier); $userType = UserTypeEnum::PHONE; } elseif (Validators::isEmail($identifier)) { $identityQuery->byEmail($identifier); $userType = UserTypeEnum::EMAIL; } else { $identityQuery->byUsername($identifier); $userType = UserTypeEnum::USERNAME; } $this->initQueryObject($identityQuery, $userType, $context, $metadata); return $identityQuery->fetchOneOrNull(); } protected function validateIdentity(Identity $identity, ?string $context = null, array $metadata = []): void { } protected function validatePhoneNumber(string $phoneNumber): bool { try { if (!PhoneNumber::parse($phoneNumber)->isValidNumber()) { return false; } } catch (PhoneNumberParseException) { return false; } return true; } }