Для централизованной авторизации пользователей Webasyst можно подключить внешнюю систему SSO. В этом примере используется Keycloak как провайдер, и библиотека jumbojett/openid-connect-php для реализации протокола OpenID Connect.

1. Установка библиотеки


composer require jumbojett/openid-connect-php

2. Настройка Keycloak

  • Создайте клиента в Keycloak.
  • Установите:
    • Client ID: webasyst
    • Access Type: confidential
    • Укажите Valid Redirect URIs: https://example.com/*

3. Изменение index.php Webasyst

В начало файла добавлен код авторизации:


session_start();
require_once __DIR__ . '/vendor/autoload.php';
use Jumbojett\OpenIDConnectClient;

Исключения из авторизации:


function isExcludedPath($path) {
    $patterns = [
        '#^/api/public#',
        '#^/favicon.ico$#',
        '#^/robots.txt$#'
    ];
    foreach ($patterns as $pattern) {
        if (preg_match($pattern, $path)) return true;
    }
    return false;
}

Обработка выхода:


if (!empty($_GET['logout']) && isset($_SESSION['id_token'])) {
    $id_token = $_SESSION['id_token'];
    session_destroy();
    setcookie(session_name(), '', time() - 3600);
    $logout_url = 'https://sso.example.com/realms/realm-name/protocol/openid-connect/logout?' . http_build_query([
        'id_token_hint' => $id_token,
        'post_logout_redirect_uri' => 'https://example.com'
    ]);
    header('Location: ' . $logout_url);
    exit;
}

Авторизация:


$current_path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
if (!isset($_SESSION['user']) && !isExcludedPath($current_path)) {
    $oidc = new OpenIDConnectClient(
        'https://sso.example.com/realms/realm-name',
        'webasyst',
        'your_client_secret'
    );
    $oidc->setRedirectURL('https://example.com');
    $oidc->addScope(['openid', 'email', 'profile']);
    $oidc->authenticate();

    $_SESSION['user'] = [
        'email' => $oidc->requestUserInfo('email'),
        'name'  => $oidc->requestUserInfo('preferred_username'),
    ];
    $_SESSION['id_token'] = $oidc->getIdToken();
}

5. Класс для выхода из SSO

Чтобы вынести логику выхода в отдельный класс, добавьте, например, waSSOAuthPlugin или используйте любой подходящий для вас плагин/контроллер:


class mySSOAuthActions extends waController
{
    const LOGOUT_URL = 'https://sso.example.com/realms/realm-name/protocol/openid-connect/logout?';
    const REDIRECT_URI = 'https://example.com';

    public function logoutAction()
    {
        $id_token = $_SESSION['id_token'] ?? null;

        session_destroy();
        setcookie(session_name(), '', time() - 3600);

        if ($id_token) {
            $logout_url = self::LOGOUT_URL . http_build_query([
                'id_token_hint' => $id_token,
                'post_logout_redirect_uri' => self::REDIRECT_URI
            ]);
            header('Location: ' . $logout_url);
        } else {
            header('Location: ' . self::REDIRECT_URI);
        }

        exit;
    }
}

Теперь для выхода достаточно перейти по ссылке:


/?module=ssoauth&action=logout 

6. Автоматическая авторизация Webasyst после входа через SSO

После успешной аутентификации через Keycloak можно сразу авторизовать пользователя в Webasyst. Ниже пример метода execute() в контроллере, который:

  1. Получает email из Keycloak;
  2. Ищет пользователя в Webasyst;
  3. Авторизует его;
  4. Перенаправляет в зависимости от группы.

public function execute()
{
    require_once wa()->getAppPath('lib/classes/vendor/autoload.php', 'booking');

    $email = $_SESSION['user']['email']; // email из Keycloak

    // Ищем пользователя по email
    $user_model = new waContactModel();
    $user = $user_model->getByEmail($email);

    if (!$user) {
        throw new waException('Пользователь не найден');
    }

    $user_id = (int) $user['id'];

    // Авторизация в Webasyst
    $auth = new waAuth();
    $auth->auth(['id' => $user_id]);

    // Проверка группы (например, админ — group_id = 1)
    $groupId = bookingHelper::getGroupId($this->getUser()->getId());
    if ($groupId === 1) {
        $this->redirect('/webasyst/');
    }

    // Обработка параметров запроса
    $uid = waRequest::param('uid');
    $confirmation_whatsapp = waRequest::get('w', 0, 'int');
    $confirmation_email = waRequest::get('e', 0, 'int');

    // Получаем заказ по UID
    $userModel = new bookingUsersModel();
    $orderModel = new bookingOrdersModel();
    $orderRecord = $orderModel->getByField(['uid' => $uid]);

    // Далее — логика обработки заказа...
}

Теперь при успешной аутентификации через Keycloak, Webasyst автоматически узнаёт пользователя и пускает в систему.