%PDF- %PDF-
Mini Shell

Mini Shell

Direktori : /proc/11976/task/11976/root/home/bitrix/www/local/php_interface/include/
Upload File :
Create Path :
Current File : //proc/11976/task/11976/root/home/bitrix/www/local/php_interface/include/phoneauth.php

<?php

use Firebase\Auth\Token\Exception\InvalidToken;
use Kreait\Firebase\Factory;
use Kreait\Firebase\ServiceAccount;

define('SLACK2LOG_URL', 'https://hooks.slack.com/services/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');

class PhoneUserLoginExternal
{
    const UF_FIREBASE = 'UF_FIREBASE';

    public static function getUserByFirebaseUid($uid)
    {
        $dbUser = \CUser::GetList(
            ($by = 'XML_ID'), ($order = 'asc'),
            ['XML_ID' => $uid],
            [SELECT => ['ID', static::UF_FIREBASE]]
        );

        if ($arUser = $dbUser->Fetch()) {
            return $arUser;
        }

        return false;
    }

    /**
     * Авторизует пользователя по токену в хидере.
     */
    public static function OnBeforeProlog()
    {
        global $USER;

        if ($USER->IsAuthorized() || empty($_SERVER['REMOTE_USER'])) {
            return;
        }

        // static::log2slack('OnBeforeProlog', $_SERVER);

        $arToken = explode(' ', $_SERVER['REMOTE_USER']);

        if ('Bearer' !== $arToken[0]) {
            return;
        }

        $dbUser = \CUser::GetList(
            ($by = 'ID'), ($order = 'asc'),
            [static::UF_FIREBASE => $arToken['1']]
        );

        if ($arUser = $dbUser->Fetch()) {
            $USER->Authorize($arUser['ID'], false);
        }
    }

    /**
     * Код взят из компонента p4:user.registration.
     * Профилю будет присвоено временное имя "ID_соль" (например, 13456_cdjkncfkdvb).
     * И e-mail 'no-reply@port4lio.pro', письмо о регистрации уйдет в на no-reply@port4lio.pro.
     *
     * @param string $uid         Идентифкатор пользователя в Firebase
     * @param string $customTokem Внутренний токен авторизации в P4
     *
     * @return array|null user data
     */
    public static function registerUser($uid, $customToken)
    {
        $CUser = new \CUser();
        $passwd = uniqid();
        $result = $CUser->Register(
            "FIREBASE_{$uid}",
            "FIREBASE_{$uid}".uniqid().'_fake',
            '',
            $passwd,
            $passwd,
            "FIREBASE_{$uid}-no-reply@port4lio.pro"
        );

        if ('OK' == $result['TYPE']) {
            $userID = $result['ID'];
            $CUser->Update($userID, [
                'ACTIVE' => 'Y',
                'XML_ID' => $uid,
                static::UF_FIREBASE => $customToken,
            ]);

            $dbUser = \CUser::GetByID($userID);
            $arUser = $dbUser->Fetch();

            $section = 'models';

            if (!($profileID = P4UserRegisterHelper::createProfile($arUser, $el, $section))) {
                static::log('registerUser: '.$el->LAST_ERROR, 'ERROR');

                return false;
            }

            return $arUser;
        }
    }

    /**
     * Авторизация пользователя по токену из Firabase Auth.
     *
     * @param array $arParams
     *
     * @return bool|int
     */
    public static function OnFirebaseAuth(&$arParams)
    {
        if (!empty($_REQUEST['LOGIN_BY_FIREBASE']) && 'Y' == $_REQUEST['LOGIN_BY_FIREBASE']) {
            $idTokenString = $_REQUEST['LOGIN'];

            $serviceAccount = ServiceAccount::fromJsonFile(
                __DIR__.
                '/keys/port4lio-8fb93-firebase-adminsdk-tcdmn-cbee5bad88.json'
            );

            $firebase = (new Factory())
                ->withServiceAccount($serviceAccount)
                ->create();

            try {
                $verifiedIdToken = $firebase->getAuth()->verifyIdToken($idTokenString);
            } catch (InvalidToken $e) {
                static::log('OnFirebaseAuth#InvalidToken: '.$e->getMessage(), 'ERROR');

                return false;
            }

            $uid = $verifiedIdToken->getClaim('sub');
            $arUser = static::getUserByFirebaseUid($uid);
            if (is_array($arUser) && !empty($arUser)) {
                if (!empty($arUser[static::UF_FIREBASE])) {
                    $customToken = $firebase->getAuth()->createCustomToken($uid);
                    $CUser = new \CUser();
                    $arUserFields = [static::UF_FIREBASE => $customToken];
                    if (!$CUser->Update($arUser['ID'], $arUserFields)) {
                        static::log('UpdateCustomToken: '.$CUser->LAST_ERROR, 'ERROR');
                    }
                }

                return $arUser['ID'];
            } else {
                $customToken = $firebase->getAuth()->createCustomToken($uid);
                $arFbUser = $firebase->getAuth()->getUser($uid);

                if (!empty($arFbUser->phoneNumber)) {
                    $phoneNumber = str_replace('+', '', $arFbUser->phoneNumber);

                    $by = 'id';
                    $order = 'desc';
                    $dbUsers = CUser::GetList($by, $order, array(
                        'UF_USER_PHONE' => $phoneNumber,
                        'ACTIVE' => 'Y',
                    ));
                    if ($arUser = $dbUsers->Fetch()) {
                        $CUser = new \CUser();
                        $arUserFields = [static::UF_FIREBASE => $customToken];
                        if (!$CUser->Update($arUser['ID'], $arUserFields)) {
                            static::log('UpdateCustomToken: '.$CUser->LAST_ERROR, 'ERROR');
                        }

                        return $arUser['ID'];
                    }
                }

                $arUser = static::registerUser($uid, $customToken);
                if (is_array($arUser) && !empty($arUser)) {
                    return $arUser['ID'];
                }
            }
        }
    }

    /**
     * Авторизация пользователя по номеру телефона.
     *
     * @param [type] $arParams
     */
    public static function OnUserLoginExternal(&$arParams)
    {
        if (isset($_REQUEST['LOGIN_BY_PHONE']) && 'Y' == $_REQUEST['LOGIN_BY_PHONE']) {
            $by = 'id';
            $order = 'desc';
            $dbUsers = CUser::GetList($by, $order, array(
                'UF_USER_PHONE' => $arParams['LOGIN'],
                'ACTIVE' => 'Y',
            ));
            if ($arUser = $dbUsers->Fetch()) {
                $arParams['PASSWORD'];

                if (strlen($arUser['PASSWORD']) > 32) {
                    $salt = substr($arUser['PASSWORD'], 0, strlen($arUser['PASSWORD']) - 32);
                    $db_password = substr($arUser['PASSWORD'], -32);
                } else {
                    $salt = '';
                    $db_password = $arUser['PASSWORD'];
                }

                if ('Y' == $arParams['PASSWORD_ORIGINAL']) {
                    $user_password = md5($salt.$arParams['PASSWORD']);
                } else {
                    if (strlen($arParams['PASSWORD']) > 32) {
                        $user_password = substr($arParams['PASSWORD'], -32);
                    } else {
                        $user_password = $arParams['PASSWORD'];
                    }
                }

                if ($db_password === $user_password) {
                    return $arUser['ID'];
                }
            }
        }
    }

    public static function log2slack($message, $context = null)
    {
        if (\defined('SLACK2LOG_URL') && function_exists(curl_init)) {
            $server = empty($_SERVER['SERVER_NAME'])
                ? $_SERVER['DOCUMENT_ROOT']
                : $_SERVER['SERVER_NAME'];

            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, SLACK2LOG_URL);
            curl_setopt($ch, CURLOPT_POST, 1);
            curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type:application/json']);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
                text => $server.': '.$message.
                    (null === $context ? '' : "\n\n".print_r($context, true)),
            ]));
            $result = curl_exec($ch);
            curl_close($ch);
        } else {
            \CEventLog::Log(
                'INFO',
                'INFO',
                'external.auth',
                'external.auth',
                null === $context
                    ? $message
                    : $message.'. '.print_r($context, true));
        }
    }

    public static function init()
    {
        AddEventHandler('main', 'OnUserLoginExternal', [__CLASS__, 'OnUserLoginExternal']);
        AddEventHandler('main', 'OnUserLoginExternal', [__CLASS__, 'OnFirebaseAuth']);
        AddEventHandler('main', 'OnBeforeProlog', [__CLASS__, 'OnBeforeProlog']);
    }

    private static function log($message, $severity = 'INFO', $context = null)
    {
        \CEventLog::Log(
            $severity,
            $severity,
            'external.auth',
            'external.auth',
            $message.(null != $context ? (': '.print_r($context, true)) : '')
        );
    }
}

Zerion Mini Shell 1.0