Skip to content

Instantly share code, notes, and snippets.

@xTCry
Created May 2, 2023 01:25
Show Gist options
  • Save xTCry/6fe4296427f25649862994961fe6e219 to your computer and use it in GitHub Desktop.
Save xTCry/6fe4296427f25649862994961fe6e219 to your computer and use it in GitHub Desktop.
[Bitrix] Own authorization distribution (instead of `spread.php`)

[Bitrix] Own authorization distribution (instead of spread.php)

Need to disable standart cookies spread - /bitrix/admin/settings.php?mid=main&tabControl_active_tab=edit1#opt_ALLOW_SPREAD_COOKIE

Add to php_interface/init.php

// Path to `reauth.class.php` file
include_once __DIR__ . '/../../x-dev/reauth/reauth.class.php';

if (true) {
    \XTT\ReAuth\ReAuth::init();
}
<?php
// Should work only on HTTPS requests
use Bitrix\Main;
use Bitrix\Main\Web;
header("P3P: policyref=\"/bitrix/p3p.xml\", CP=\"NON DSP COR CUR ADM DEV PSA PSD OUR UNR BUS UNI COM NAV INT DEM STA\"");
header("Content-type: image/png");
if (!isset($_GET['k'], $_GET['s']) || !is_string($_GET['k']) || !is_string($_GET['s']) || empty($_GET['k'])) {
return;
}
// "SameSite: None" requires "secure"
ini_set('session.cookie_secure', 1);
ini_set('session.cookie_samesite', 'None');
// require_once(__DIR__.'/include.php');
require_once($_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include.php');
$cookieString = base64_decode($_GET['s']);
$arr = explode(chr(2), $cookieString);
$salt = $_SERVER['REMOTE_ADDR'] . '|' . @filemtime($_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/classes/general/version.php') . '|' . LICENSE_KEY;
if (!is_array($arr) || md5($cookieString . $salt) !== $_GET['k']) {
return;
}
$application = Main\Application::getInstance();
$context = Main\Context::getCurrent();
$request = $context->getRequest();
$response = $context->getResponse();
$host = $request->getHttpHost();
foreach ($arr as $str) {
if (empty($str)) {
continue;
}
$params = explode(chr(1), $str);
// "SameSite: None" requires "secure"
$cookie = (new Web\Cookie($params[0], $params[1], $params[2], false))
->setPath($params[3])
->setDomain($host)
->setSecure(true)
->setHttpOnly($params[6])
->setSameSite(Web\Cookie::SAME_SITE_NONE);
$response->addCookie($cookie);
// logout
if (substr($params[0], -5) == '_UIDH' && $params[1] == '') {
$kernelSession = $application->getKernelSession();
$kernelSession["SESS_AUTH"] = [];
unset($kernelSession["SESS_AUTH"]);
unset($kernelSession["SESS_OPERATIONS"]);
unset($kernelSession["MODULE_PERMISSIONS"]);
unset($kernelSession["SESS_PWD_HASH_TESTED"]);
}
}
$application->end();
<?
namespace XTT\ReAuth;
use Bitrix\Main;
use Bitrix\Main\Page;
/*
Disable standart spread
\COption::SetOptionString("main", "ALLOW_SPREAD_COOKIE", "N");
*/
class ReAuth
{
const SESSION_COOKIE_NAME = 'PIXELIZER_SPREAD_COOKIE';
protected static /* string */ $PIXEL_PATH = '/x-dev/reauth/pixel.php';
public static function init()
{
AddEventHandler("main", "OnBeforeLocalRedirect", ['XTT\ReAuth\ReAuth', 'OnBeforeLocalRedirect']);
AddEventHandler("main", "OnBeforeEndBufferContent", ['XTT\ReAuth\ReAuth', 'OnBeforeEndBufferContent']);
AddEventHandler("main", "OnAfterUserAuthorize", ['XTT\ReAuth\ReAuth', 'OnAfterUserAuthorize']);
// \COption::SetOptionString("main", "ALLOW_SPREAD_COOKIE", "N");
}
// ! Event (main)
public function OnBeforeEndBufferContent()
{
$reAuth = new ReAuth();
$asset = Page\Asset::getInstance();
$asset->addString($reAuth->GetSpreadCookieHTML(), false, Page\AssetLocation::AFTER_JS, Page\AssetMode::STANDARD);
}
// ! Event (main)
public function OnBeforeLocalRedirect()
{
// Store cookies for next hit (see \XTT\ReAuth\ReAuth::GetSpreadCookieHTML())
$reAuth = new ReAuth();
$reAuth->StoreCookies();
}
// ! Event (main)
public function OnAfterUserAuthorize($arParams)
{
if (!defined('ADMIN_SECTION') || ADMIN_SECTION !== true) {
return;
}
// Store cookies for next hit (see \XTT\ReAuth\ReAuth::GetSpreadCookieHTML())
$reAuth = new ReAuth();
$reAuth->StoreCookies();
}
public function isActive()
{
return true;
}
/**
* Вызывается после успешной авторизации (юзера или редиректе)
*/
public function StoreCookies()
{
$application = Main\Application::getInstance();
$response = Main\Context::getCurrent()->getResponse();
// Установка прошлых кук из сохраненной сессиии
if (is_array($application->getSession()[self::SESSION_COOKIE_NAME])) {
foreach ($application->getSession()[self::SESSION_COOKIE_NAME] as $cookie) {
if ($cookie instanceof Main\Web\Cookie) {
$response->addCookie($cookie, false);
}
}
}
$application->getSession()[self::SESSION_COOKIE_NAME] = $response->getCookies();
$this->HoldSpreadCookieHTML(true);
}
/**
* Если передано значение `$set`, то устанавливает это состояние и возвращает прошлое.\
* Иначе просто возвращает состояние держателя печенек (был ли показ "пикселя").
*/
public function HoldSpreadCookieHTML(bool $set = false)
{
static $showed_already = false;
$result = $showed_already;
if ($set) {
$showed_already = true;
}
return $result;
}
/**
* Возвращает строку с "пикселями" для распространения печенек
*/
public function GetSpreadCookieHTML()
{
$res = '';
$request = Main\Context::getCurrent()->getRequest();
if (
$request->isHttps()
// Если распространения еще не было
&& !$this->HoldSpreadCookieHTML()
&& $this->isActive()
// && \COption::GetOptionString("main", "ALLOW_SPREAD_COOKIE", "Y") == "Y"
) {
foreach ($this->GetSpreadCookieUrls() as $url) {
$res .= "new Image().src='" . \CUtil::JSEscape($url) . "';\n";
$this->HoldSpreadCookieHTML(true);
}
}
if ($res) {
return '<script>' . $res . '</script>';
}
return '';
}
/**
* Возвращает массив URL-адресов, содержащих подписанные междоменные печеньки
*
* @return array
*/
public function GetSpreadCookieUrls()
{
if (!$this->isActive()/* \COption::GetOptionString("main", "ALLOW_SPREAD_COOKIE", "Y") !== "Y" */) {
return [];
}
$application = Main\Application::getInstance();
$response = Main\Context::getCurrent()->getResponse();
$request = Main\Context::getCurrent()->getRequest();
if (
isset($application->getSession()[self::SESSION_COOKIE_NAME])
&& is_array($application->getSession()[self::SESSION_COOKIE_NAME])
) {
foreach ($application->getSession()[self::SESSION_COOKIE_NAME] as $cookie) {
if ($cookie instanceof Main\Web\Cookie) {
$response->addCookie($cookie, false);
}
}
// ! Очищаем, т.к. будем считать, что печеньем уже поделилсь
unset($application->getSession()[self::SESSION_COOKIE_NAME]);
}
$cookies = $response->getCookies();
if (empty($cookies)) {
return [];
}
$params = "";
foreach ($cookies as $cookie) {
if ($cookie->getSpread() & Main\Web\Cookie::SPREAD_SITES) {
$params .= join(chr(1), [
$cookie->getName(),
$cookie->getValue(),
$cookie->getExpires(),
$cookie->getPath(),
'', //domain is empty
$cookie->getSecure(),
$cookie->getHttpOnly(),
chr(2),
]);
}
}
$salt = $_SERVER["REMOTE_ADDR"] . "|" . @filemtime($_SERVER["DOCUMENT_ROOT"] . "/bitrix/modules/main/classes/general/version.php") . "|" . LICENSE_KEY;
$params = "s=" . urlencode(base64_encode($params)) . "&k=" . urlencode(md5($params . $salt));
$arrDomain = [];
$arrDomain[] = $request->getHttpHost();
$rs = \CSite::GetList('', '', ["ACTIVE" => "Y"]);
while ($ar = $rs->Fetch()) {
$arD = explode("\n", str_replace("\r", "\n", $ar["DOMAINS"]));
if (is_array($arD) && count($arD) > 0) {
foreach ($arD as $d) {
if (trim($d) <> '') {
$arrDomain[] = $d;
}
}
}
}
if (empty($arrDomain)) {
return [];
}
$arUniqDomains = [];
$arrDomain = array_unique($arrDomain);
$arrDomain2 = array_unique($arrDomain);
// Уникализация по поддоменам
foreach ($arrDomain as $domain1) {
$bGood = true;
foreach ($arrDomain2 as $domain2) {
if (
mb_strlen($domain1) > mb_strlen($domain2)
&& mb_substr($domain1, - (mb_strlen($domain2) + 1)) == "." . $domain2
) {
$bGood = false;
break;
}
}
if ($bGood) {
$arUniqDomains[] = $domain1;
}
}
$arUrl = [];
$protocol = ($request->isHttps() ? "https://" : "http://");
$arrCurUrl = parse_url($protocol . $request->getHttpHost() . "/");
foreach ($arUniqDomains as $domain) {
if (trim($domain) <> '') {
$url = $protocol . $domain . self::$PIXEL_PATH . "?" . $params;
$arrUrl = parse_url($url);
if ($arrUrl["host"] != $arrCurUrl["host"]) {
$arUrl[] = $url;
}
}
}
return $arUrl;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment