Twitter OAuth authentication

Good day, dear forum users. I have a problem with authorization. Namely, with authorization via Twitter. Since I don’t have much experience, I used examples from the Internet and implemented them, but it doesn’t work out. Can someone help me figure it out or point me in the right direction? There are no problems with routing and data from .env, all permissions are made, but I get this error: 2024-09-13 23:05:42 error: Error obtaining user information from Twitter: null
2024-09-13 23:05:42 error: Error during Twitter authentication: Failed to get user information from Twitter.

I will attach entire code from AuthController

<?php
declare(strict_types=1);

namespace App\Controller;

use Abraham\TwitterOAuth\TwitterOAuth;
use App\Model\UserModel;
use App\Pkg\Db\Maria;
use Cake\Controller\Controller;
use Cake\Http\Exception\NotFoundException;
use Cake\Log\Log;
use Exception;
use Google_Client;
use Google_Service_Oauth2 as GoogleOauth2;
use PDO;

class AuthController extends Controller
{
    public $googleClient;

    private UserModel $userModel;

    public PDO $conn;

    public $twitterClient;

    public function initialize(): void
    {
        parent::initialize();
        $this->loadComponent('Flash');

        $env = getenv('APP_ENV') === 'prod' ? $_ENV : parse_ini_file(ROOT . '/config/.env');

        // Google API settings
        $clientId     = $env['GOOGLE_CLIENT_ID'] ?? '';
        $clientSecret = $env['GOOGLE_CLIENT_SECRET'] ?? '';
        $redirectUri  = $env['GOOGLE_REDIRECT_URI'] ?? '';

        $this->googleClient = new Google_Client();
        $this->googleClient->setClientId($clientId);
        $this->googleClient->setClientSecret($clientSecret);
        $this->googleClient->setRedirectUri($redirectUri);
        $this->googleClient->addScope(GoogleOauth2::USERINFO_EMAIL);
        $this->googleClient->addScope(GoogleOauth2::USERINFO_PROFILE);

        // Twitter API settings
        $twitterKey    = $env['TWITTER_API_KEY'] ?? '';
        $twitterSecret = $env['TWITTER_API_SECRET_KEY'] ?? '';

        $this->twitterClient = new TwitterOAuth($twitterKey, $twitterSecret);

        $db              = new Maria();
        $this->conn      = $db->instanceConnection();
        $this->userModel = new UserModel($this->conn);
    }

    // Google authentication

    public function login(): void
    {
        $authUrl = $this->googleClient->createAuthUrl();
        $this->redirect($authUrl);
    }

    public function callback(): void
    {
        try {
            $code = $this->request->getQuery('code');
            if (!$code) {
                throw new NotFoundException('Authorization code not found.');
            }

            $accessToken = $this->googleClient->fetchAccessTokenWithAuthCode($code);
            if (isset($accessToken['error'])) {
                throw new Exception('Error obtaining token: ' . $accessToken['error']);
            }
            $this->googleClient->setAccessToken($accessToken);

            $oauth2 = new GoogleOauth2($this->googleClient);
            $userInfo = $oauth2->userinfo->get();

            if (empty($userInfo->id) || empty($userInfo->email)) {
                throw new NotFoundException('Failed to get user information.');
            }

            $this->processGoogleUser($userInfo);
        } catch (Exception $e) {
            Log::error('Error during Google authentication: ' . $e->getMessage());
            $this->Flash->error('Error during Google authentication. Please try again.');
            $this->redirect(['action' => 'login']);
        }
    }

    private function processGoogleUser($userInfo): void
    {
        $userData = (object)[
            'name'  => $userInfo->name,
            'email' => $userInfo->email,
            'id'    => $userInfo->id,
        ];
        $res = $this->userModel->createOrUpdateGoogleUser($userData, $this->googleClient->getAccessToken()['access_token']);
        if ($res['success'] != 1) {
            throw new NotFoundException('Failed to save user.');
        }

        $this->Flash->success('Welcome, ' . $userInfo->name . '!');
        $this->redirect(['controller' => 'User', 'action' => 'index']);
    }

    // Twitter authentication

    public function twitterLogin(): void
    {
        try {
            $requestToken = $this->twitterClient->oauth('oauth/request_token', [
                'oauth_callback' => getenv('TWITTER_CALLBACK_URL') ?? '',
            ]);

            if ($this->twitterClient->getLastHttpCode() === 200) {
                $url = $this->twitterClient->url('oauth/authorize', [
                    'oauth_token' => $requestToken['oauth_token'],
                ]);
                $this->redirect($url);
            } else {
                $error = $this->twitterClient->getLastBody();
                Log::error('Error obtaining request token from Twitter: ' . json_encode($error));
                $this->Flash->error('Failed to get Twitter authorization URL.');
                $this->redirect(['action' => 'twitterLogin']);
            }
        } catch (Exception $e) {
            Log::error('Error requesting request token: ' . $e->getMessage());
            $this->Flash->error('Error during Twitter authentication. Please try again.');
            $this->redirect(['action' => 'twitterLogin']);
        }
    }

    public function twitterCallback(): void
    {
        try {
            $oauthToken    = $this->request->getQuery('oauth_token');
            $oauthVerifier = $this->request->getQuery('oauth_verifier');

            if (!$oauthToken || !$oauthVerifier) {
                throw new NotFoundException('Missing parameters for Twitter authentication.');
            }

            $accessToken = $this->twitterClient->oauth('oauth/access_token', [
                'oauth_token'    => $oauthToken,
                'oauth_verifier' => $oauthVerifier,
            ]);

            if ($this->twitterClient->getLastHttpCode() !== 200) {
                $error = $this->twitterClient->getLastBody();
                Log::error('Error obtaining access token from Twitter: ' . json_encode($error));
                throw new NotFoundException('Failed to obtain access token from Twitter.');
            }

            $this->twitterClient->setOauthToken($accessToken['oauth_token'], $accessToken['oauth_token_secret']);
            $userInfo = $this->twitterClient->get('account/verify_credentials', [
                'skip_status' => 'true',
                'include_email' => 'true',
                'include_entities' => 'false',
            ]);

            Log::info('Full response from Twitter: ' . json_encode($userInfo));

            if ($this->twitterClient->getLastHttpCode() !== 200) {
                $error = $this->twitterClient->getLastBody();
                Log::error('Error obtaining user information from Twitter: ' . json_encode($error));
                throw new NotFoundException('Failed to get user information from Twitter.');
            }
            if (empty($userInfo->id_str) || empty($userInfo->email)) {
                throw new NotFoundException('Failed to get user information from Twitter.');
            }

            $this->processTwitterUser($userInfo);
        } catch (Exception $e) {
            Log::error('Error during Twitter authentication: ' . $e->getMessage());
            $this->Flash->error('Error during Twitter authentication. Please try again.');
            $this->redirect(['action' => 'twitterLogin']);
        }
    }

    private function processTwitterUser($userInfo): void
    {
        $userData = (object)[
            'name'  => $userInfo->name,
            'email' => $userInfo->email,
            'id'    => $userInfo->id_str,
        ];
        $res = $this->userModel->createOrUpdateTwitterUser($userData, $this->twitterClient->getOauthToken()['oauth_token']);
        if ($res['success'] != 1) {
            throw new NotFoundException('Failed to save user.');
        }

        $this->Flash->success('Welcome, ' . $userInfo->name . '!');
        $this->redirect(['controller' => 'User', 'action' => 'index']);
    }
}