Единая аутентификация (SSO)

Настройте единую аутентификацию с вашим сайтом

Вводная


Технология единого входа (англ. Single Sign-On) — подход, при котором аутентификация пользователя происходит на вашем сайте. При этом аутентифицированный пользователь получает доступ к сервисам платформы Aplaut без повторной аутентификации.

Aplaut использует JSON Web Token (JWT) для безопасного обмена данными пользователя.


Логин пользователя


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

  • Добавьте в DNS запись CNAME:

CNAME aplaut-platform.yoursite.ru sso.aplaut.io
  • Зарегистрируйте JS обработчик для обработки действия пользователя «Логин».

  • В ЛК включите SSO и укажите секретный ключ подписи JWT.

Обмен данными при логине

После включения SSO в личном кабинете, процесс отправления отзыва из формы выглядит так:

  1. Неаутентифицированный в Aplaut пользователь нажимает на вашем сайте кнопку «Оставить отзыв».

  2. Бэкенд Aplaut отвечает 401 Unauthorized.

  3. Скрипт Aplaut вызывает предоставленный JS-обработчик, позволяющий пользователю войти на сайт (например, открывающий форму логина).

  4. Ваш сайт аутентифицирует пользователя.

  5. Ваш сайт создает JWT токен, содержащий информацию о пользователе.

  6. И делает фоновый браузерный запрос на https://aplaut-platform.yoursite.ru/auth/sso/jwt/login?token=TOKEN&store_id=APLAUT_STORE_ID. В ответе приходят аутентификационные куки.

  7. Ваш JS-обработчик сообщает скрипту Aplaut об успешном логине.

  8. Форма отзыва повторно отправляет отзыв, уже с аутентификационными куками.

☝️Все процессы происходят в браузере, прямого взаимодействия вашего бэкенда с бэкендом Aplaut нет. Как сформировать JWT токен читайте ниже.


Регистрация JS-обработчика

Обработчик — функция без аргументов, возвращающая Promise (then-able object).

В примере ниже минималистичный обработчик, который логинит пользователя по заранее сгенерированному JWT токену, используя Fetch API.


☝️ Fetch API не поддерживается старыми версиями браузеров, например, IE 11. Для поддержки старых браузеров используйте XMLHttpRequest.

const TOKEN = 'JWT';
const STORE_ID = 'APLAUT_STORE_ID';
const BASE_SSO_URL = 'https://aplaut-platform.yoursite.ru/auth/sso/jwt';

function aplautSendSSORequest(action /* login or logout */) {
  return fetch(
    `${BASE_SSO_URL}/${action}?token=${TOKEN}&store_id=${STORE_ID}`,
    {
      mode: 'cors',
      credentials: 'include'
    }
  );
}

// Обработчик
function aplautSSOHandler() {
  return new Promise(function (resolve, reject) {
    let Omnibox = Shoppilot.require('omnibox');
    Omnibox.hide();

    login() // Логин на вашем сайте; имплементируйте эту функцию
      .then(() => {
        aplautSendSSORequest('login') // Логин в Aplaut
          .then(() => {
            Omnibox.show();
            resolve(); // Сообщаем форме отзыва что пользователь залогинен
          });
      });
  });
}


(function () {
  window._shoppilot = window._shoppilot || [];

  _shoppilot.push([
    '_setOnReady',
    function (Shoppilot) {
      // Регистрация обработчика
      Shoppilot.require('user_config').set('sso_handler', aplautSSOHandler);
    }
  ]);

  // Другие команды загрузчика

  // Загрузчик скрипта
  var store_id = '<?= APLAUT_STORE_ID ?>';
  var theme_id = 'default';
  var script = document.createElement('script');
  script.type = 'text/javascript';
  script.async = true;
  script.src = '//get.aplaut.io/f/v1/' + store_id + '/' + theme_id + '/app.js';
  var s = document.getElementsByTagName('script')[0];
  s.parentNode.insertBefore(script, s);
})();


Логаут пользователя


Чтобы разлогинить пользователя, нужно сформировать JWT токен аналогичным образом, но отправить его на https://aplaut-platform.yoursite.ru/auth/sso/jwt/logout?token=TOKEN&store_id=APLAUT_STORE_ID.


Чтобы очистить форму отзыва и заставить скрипт Aplaut «забыть» об уже загруженной сессии пользователя, нужно закрыть Омнибокс:

var Omnibox = Shoppilot.require('omnibox'); Omnibox.close({force: true});


При следующем взаимодействии с формами Aplaut устаревшей сессии уже не будет (пользователь будет анонимен).


Включение SSO


  1. Перейти в раздел Настройки компании -> Омнибокс -> Аутентификация.

  2. Разрешить запрашивать аутентификацию при написании отзыва.

  3. Выбрать способ аутентификации Single Sign-On (SSO).

  4. Заполнить секретный ключ для подписи JWT токена.


Настройки SSO в личном кабинете

JWT Токен


Токен состоит из трех частей, разделенных точкой (.):

  1. Заголовок

  2. Полезные данные

  3. Подпись

Заголовок

Заголовок состоит из двух полей: тип токена и алгоритм формирования подписи:

{ "alg": "HS256", "typ": "JWT" }


Полезные данные

Полезные данные содержат обязательные и необязательные поля.

Параметр

Обязательный

Описание

jti

да

Уникальный идентификатор токена

iss

да

Store Id

iat

да

Время выпуска токена (Unix epoch)

email

нет*

Email

phone

нет*

Телефон

name

да

Полное имя

location_name

нет

Название локации (например, город)

exp

нет

Время экспирации токена (Unix epoch)

picture

нет

URL аватара

external_id

нет

Уникальный идентификатор пользователя

custom_attributes

нет

Произвольные атрибуты

*Обязателен email или phone. Можно передать и то и другое.


Пример:

{
  "jti": "b219a441cfc9e6419fe87d1ed55eae7a",
  "iss": "57a1dd0955b4a36599000003",
  "iat": "1471512369",
  "exp": "1471512400",
  "email": "grushenka@yandex.ru",
  "name": "Аграфена Петрова",
  "phone": "+79651755423",
  "external_id": "12345",
  "custom_attributes": {"eye_colour": "racing green"}
}


Подпись

Чтобы создать подпись, необходимо иметь закодированные с помощью алгоритма Base64 заголовок и полезные данные, а также секретный ключ.

Пример формирования токена (псевдокод):

header      = {...}
header64    = base64UrlEncode(header)
payload     = {...}
payload64   = base64UrlEncode(payload)
signature   = HMACSHA256(header64 + "." + payload64, <YOUR SECRET CODE>)
signature64 = base64UrlEncode(signature)
token       = header64 + "." + payload64 + "." + signature64


Секретный код (YOUR SECRET CODE) указывается в личном кабинете.


Полезные ресурсы:

👆 На этом пока всё