validate(); Authserver::info("Trying to authenticate user by login = '{$this->username}'."); $password = (string)$this->password; $totp = null; if (preg_match('/.{8,}:(\d{6})$/', $password, $matches) === 1) { $totp = $matches[1]; $password = mb_substr($password, 0, -7); // :123456 - 7 chars } login: $credentials = new Credentials( login: (string)$this->username, password: $password, totp: $totp, ); try { $result = $this->loginService->loginByCredentials($credentials); } catch (Exceptions\InvalidPasswordException $e) { if ($totp !== null) { $password = $this->password; goto login; } $this->convertAuthenticationException($e); } catch (AuthenticationException $e) { $this->convertAuthenticationException($e); } $account = $result->account; if ($account->status === Account::STATUS_DELETED) { throw new ForbiddenOperationException('Invalid credentials. Invalid username or password.'); } $clientToken = $this->clientToken ?: Uuid::uuid4()->toString(); $token = $this->tokensFactory->createForMinecraftAccount($account, $clientToken); $dataModel = new AuthenticateData($account, $token->toString(), $clientToken, (bool)$this->requestUser); /** @var OauthSession|null $minecraftOauthSession */ $minecraftOauthSession = $account->getOauthSessions() ->andWhere(['client_id' => OauthClient::UNAUTHORIZED_MINECRAFT_GAME_LAUNCHER]) ->one(); if ($minecraftOauthSession === null) { $minecraftOauthSession = new OauthSession(); $minecraftOauthSession->account_id = $account->id; $minecraftOauthSession->client_id = OauthClient::UNAUTHORIZED_MINECRAFT_GAME_LAUNCHER; $minecraftOauthSession->scopes = [P::MINECRAFT_SERVER_SESSION]; } $minecraftOauthSession->last_used_at = time(); Assert::true($minecraftOauthSession->save()); Authserver::info("User with id = {$account->id}, username = '{$account->username}' and email = '{$account->email}' successfully logged in."); return $dataModel; } /** * @throws \api\modules\authserver\exceptions\ForbiddenOperationException */ private function convertAuthenticationException(AuthenticationException $e): never { throw match ($e::class) { Exceptions\AccountBannedException::class => new ForbiddenOperationException('This account has been suspended.'), Exceptions\TotpRequiredException::class => new ForbiddenOperationException('Account protected with two factor auth.'), default => new ForbiddenOperationException('Invalid credentials. Invalid username or password.'), }; } }