Ansible даёт разработчикам сайтов и приложений бесплатную и открытую платформу — пользователь регистрируется и входит своей учётной записью Ansible, вместо того чтобы придумывать ещё один пароль.
Выше конверсия
Вход в два касания — меньше тех, кто закрыл форму регистрации и не вернулся.
Не нужно хранить пароли
Нечего хранить, нечего восстанавливать и нечему утекать: чужого секрета вы просто не видите.
Прямая связь
С пользователем можно связаться прямо в Ansible — с обычными пуш-уведомлениями.
Что дальше
Дальше — Bot API и мини-приложения: сервис целиком внутри мессенджера.
Заметка: Здесь описаны библиотека входа Ansible и новый — на базе OpenID Connect порядок входа.
У нас есть небольшой конструктор — он быстро соберёт кнопку входа для вашего интерфейса. Можно обратиться и напрямую к JS API библиотеки.
На мобильных используйте обычный OIDC-редирект через системный браузер: те же адреса, отдельный SDK не нужен.
Кроме того, Ansible поддерживает стандартный OpenID Connect , так что вход можно подключить любой совместимой библиотекой или брокером — Keycloak, Authentik, Auth0 и подобными.
Мы следуем обычному Authorization Code Flow с PKCE .
Если хочется разобраться в OIDC подробнее, начните с руководства OpenID Foundation.
@ansible_dev_bot, кнопка меню открывает https://id.ansible.su/app.client_id и
client_secret.https://id.ansible.su/widget.js на
страницу — или сходите по обычному OIDC.id_token на своём сервере, прежде
чем поверить тому, что прислал браузер.Что-то не сходится — напишите нам, пожалуйста, с описанием шага, на котором встали.
Приложению нужна карточка: имя и логотип, которые пользователь увидит
в окне подтверждения. Заводится она в кабинете разработчика — откройте бот
@ansible_dev_bot и нажмите кнопку меню.
Логотип стоит взять тот же, что у вас на сайте, а имя — такое же, как в адресной строке. Пользователь соглашается отдать свои данные ровно тому, кого узнал: незнакомое имя в этом окне — причина нажать «Отмена».
client_id у нас — не идентификатор бота, а строка вида
app_9f3ab21c, которую выдаёт кабинет. client_secret показывается там же и только владельцу приложения.
В карточке приложения два списка, и они про разное:
https://example.com. Без порта и без пути.https://example.com/auth/callback. Сверяются побайтово: лишний
слэш в конце — уже другой адрес.Важно: вход возможен только с заранее вписанных адресов. Это не формальность: без такой проверки чужой сайт мог бы провести пользователя через настоящее окно подтверждения и забрать результат себе.
Настройте кнопку и заберите готовый код для своей страницы.
Ту же библиотеку можно вызывать из кода:
Библиотека кладёт в страницу один объект — Ansible.
| Метод | Что делает |
|---|---|
Ansible.login(clientId, callback) | Открывает окно входа и вызывает callback с результатом. Оба аргумента необязательны: без них берутся значения из атрибутов тега <script>. |
Отдельного шага инициализации нет — библиотека готова к работе сразу после загрузки.
Настраивается атрибутами того же тега <script>.
| Атрибут | Тип | Что значит |
|---|---|---|
data-client | string | client_id из кабинета. Если он задан, библиотека сама вставит кнопку на место тега. |
data-onauth | string | Имя глобальной функции, которую позвать с результатом. Именно имя: data-onauth="onAnsibleAuth", а не onAnsibleAuth(data) — выражение не выполнится. |
data-label | string | Необязательно. Надпись на кнопке. |
<script async src="https://id.ansible.su/widget.js"
data-client="app_9f3ab21c"
data-label="Войти через Ansible"
data-onauth="onAnsibleAuth"></script>
<script>
function onAnsibleAuth(data) {
// data.jwt приходит только first-party клиентам.
// Всё остальное проверяйте на своём сервере.
fetch('/auth/ansible', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
});
}
</script>Функция из data-onauth получает один объект.
| Поле | Тип | Что значит |
|---|---|---|
status | string | confirmed при успехе. |
user | object | Идентификатор и имя вошедшего, плюс auth_date. |
hash | string | HMAC-SHA256 по полям auth_date, id, name, photo_url, ключ — SHA-256 от вашего client_secret. Проверяется на сервере. |
jwt | string | Только для доверенных приложений. Обычным клиентам не выдаётся. |
🚨 Подписью покрыты только перечисленные поля. Всё, что пришло рядом и в
hashне входит, — это данные из браузера: проверить их нечем, и решения по ним принимать нельзя.
Если вы настраиваете готовую библиотеку или брокера, вот значения для её конфигурации.
Адрес discovery-документа
https://id.ansible.su/.well-known/openid-configuration
Настройки клиента
| Параметр | Значение |
|---|---|
| Client ID | Client ID из кабинета разработчика |
| Client Secret | Client Secret из кабинета разработчика |
| Response Type | код |
| PKCE | Обязателен (S256) |
Мы объявляем два scope. openid обязателен.
| Scope | Что даёт | Claim’ы |
|---|---|---|
openid | Обязателен. Идентификатор пользователя и время входа. | sub, iss, aud, iat, exp, auth_time |
profile | Отображаемое имя. | name, picture |
Номера телефона и адреса почты вход через Ansible не отдаёт — такого scope у нас нет. Если вам нужен подтверждённый номер, спросите его у пользователя сами: молчаливая передача чужого телефона стороннему сайту — не та цена, которую стоит платить за удобный вход.
pictureсейчас приходит пустой строкой: фото профиля в токен пока не попадает. Поле объявлено и не исчезнет — рассчитывайте на ключ, но не на значение.
Все данные приходят прямо в ID-токене.
Раскодированный id_token выглядит так:
{
"iss": "https://id.ansible.su",
"aud": "app_9f3ab21c",
"sub": "1234567890",
"iat": 1753900000,
"exp": 1753903600,
"auth_time": 1753900000,
"name": "Мария",
"picture": "",
"nonce": "n-0S6_WzA2Mj"
}
sub— строка, даже когда внутри число. Складывайте её в текстовое поле: разбор в целое переживёт не каждый идентификатор.
Эндпоинт /userinfo есть и отдаёт sub,
name и picture по Bearer-токену, но ничего сверх
того, что уже лежит в id_token. Библиотеке OIDC его можно не
дёргать.
Если делаете OIDC руками, вот адреса и порядок шагов.
https://id.ansible.su/.well-known/openid-configurationhttps://id.ansible.su/authorizehttps://id.ansible.su/tokenhttps://id.ansible.su/userinfohttps://id.ansible.su/.well-known/jwks.jsonНастраиваете готовую библиотеку или брокера (Keycloak, Authentik, Auth0) — хватит одного адреса discovery, остальное он заберёт сам.
Отправьте пользователя в браузере на адрес авторизации.
GET https://id.ansible.su/authorize?
client_id=<YOUR_CLIENT_ID>&
redirect_uri=<YOUR_CALLBACK_URL>&
response_type=code&
scope=openid%20profile&
state=<RANDOM_STRING>&
code_challenge=<PKCE_CHALLENGE>&
code_challenge_method=S256
app_… из кабинета.base64url(sha256(verifier)).PKCE обязателен. В discovery объявлены и
S256, иplain, но обмен кода безcode_verifierсейчас заканчивается ошибкойinvalid_grant. ИспользуйтеS256— это и работает, и правильно.
После подтверждения пользователь вернётся на ваш
redirect_uri с параметром code. Обменяйте его —
запросом со своего сервера, не из браузера.
POST https://id.ansible.su/token
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code&
code=<AUTHORIZATION_CODE>&
redirect_uri=<YOUR_CALLBACK_URL>&
client_id=<YOUR_CLIENT_ID>&
client_secret=<YOUR_CLIENT_SECRET>&
code_verifier=<PKCE_VERIFIER>
Аутентификация клиента —
client_secret_post: секрет идёт в теле запроса. HTTP Basic наш сервер не читает, и заголовокAuthorizationздесь ничего не даст.
Ответ:
{
"access_token": "...",
"token_type": "Bearer",
"expires_in": 3600,
"id_token": "eyJhbGciOiJSUzI1NiIs...",
"scope": "openid profile"
}
Код одноразовый и живёт 10 минут. refresh_token не
выдаётся: срок жизни access_token — час, дальше нужен новый вход.
id_token — это подписанный JWT. Прежде чем поверить
тому, что внутри, проверьте подпись:
https://id.ansible.su/.well-known/jwks.json —
по kid из заголовка токена.RS256.iss равен
https://id.ansible.su, aud — вашему client_id,
exp не в прошлом, а nonce совпадает с тем, что вы
отправляли.Ключ сейчас один и не ротируется, но
kidв заголовке уже есть. Выбирайте ключ по нему, а не берите первый из списка — иначе первая же ротация сломает вход, и уже у всех сразу.
Токены подписываются RS256 — ключом RSA-2048.
Других алгоритмов сейчас нет.
| Алгоритм | Состояние |
|---|---|
RS256 | Единственный. Работает со всеми библиотеками OIDC без настройки. |
В JWKS всегда ровно один активный ключ. Выбор алгоритма на стороне приложения не предусмотрен.