Вход через OAuth2
Отправляйте людей в Hivesigner, чтобы они вошли в ваше приложение. Там они смотрят ваш запрос и одобряют его. Затем Hivesigner возвращает их на ваш адрес возврата с токеном (поток с токеном) или с кодом, который ваш сервер обменивает на токены (поток с кодом). На этой странице разобраны оба потока, все параметры и области доступа.
Прежде чем начать
- Зарегистрируйте приложение: аккаунт Hive для него, с перечисленными адресами возврата. Смотрите Зарегистрируйте приложение.
- Чтобы отправлять операции через API, аккаунт вашего приложения должен ещё и дать постинг-полномочия @hivesigner.
- Для потока с кодом задайте секрет клиента.
Адрес авторизации
Отправьте человека по этому адресу:
https://hivesigner.com/oauth2/authorize?client_id=CLIENT_ID&redirect_uri=REDIRECT_URI&scope=SCOPE&state=STATE
Закодируйте каждое значение для адреса. URLSearchParams сделает это за вас:
import { randomBytes } from 'node:crypto';
const state = randomBytes(16).toString('hex');
// Store `state` in the user's session before you redirect (see "Protect the request with state").
const params = new URLSearchParams({
client_id: 'myapp',
redirect_uri: 'https://myapp.example/auth/callback',
scope: 'posting',
state,
});
const authorizeUrl = `https://hivesigner.com/oauth2/authorize?${params}`;
Параметры
| Параметр | Обязателен | Что делает |
|---|---|---|
client_id |
Да, для приложения | Имя аккаунта вашего приложения. Читается и clientId. Без него запрос становится запросом только на вход с сайта без аккаунта приложения: смотрите Вход без доступа к публикации. |
redirect_uri |
Да | Куда Hivesigner вернёт человека. Должен быть ровно одним из адресов перенаправления вашего приложения. Смотрите Адреса возврата. |
scope |
Нет | login, posting или offline. Смотрите Области доступа. Без него запрос просит доступ к публикации. |
response_type |
Нет | code начинает поток с кодом. Любое другое значение или его отсутствие означает поток с токеном. |
state |
Рекомендуется | Случайное значение, которое Hivesigner возвращает без изменений. Смотрите Защитите запрос через state. |
account |
Нет | Имя пользователя Hive. Если этот аккаунт есть на устройстве человека, Hivesigner выберет его. Иначе он не учитывается. Читается и select_account. |
Человек всё равно может переключиться на другой аккаунт на экране согласия. Всегда берите аккаунт из токена или из обмена кода, но не из того, что вы запросили.
Области доступа
В Hive одно постинг-полномочие. Поэтому у Hivesigner два уровня доступа — только вход и публикация, и ничего более тонкого между ними.
scope |
Что одобряет человек | Поток | type токена доступа |
|---|---|---|---|
login |
«Просмотр имени пользователя вашего аккаунта». Ничего не предоставляется. | Поток с токеном (не добавляйте response_type=code) |
login |
posting |
Доступ к публикации. В первый раз это добавляет аккаунт вашего приложения в постинг-полномочия человека. | Поток с токеном или поток с кодом при response_type=code |
posting |
offline |
Доступ к публикации, как выше | Поток с кодом | posting, вместе с токеном refresh |
В потоке с кодом адрес возврата сначала получает код (токен с type, равным code), который ваш сервер обменивает на токен доступа.
- Отсутствие области означает
posting. - Значение, где где-либо есть
offline, означаетoffline, например староеoffline,vote,comment. - Любое другое значение означает
posting. Сюда относятся и старые названия операций вродеvote,comment,vote,comment,comment_optionsилиcustom_json. Они не ограничивают токен: любой постинг-токен разрешает одни и те же операции. Смотрите Что принимает broadcast.
Просите login, когда вашему приложению нужно лишь знать, кто этот человек. Смотрите Вход без доступа к публикации.
Поток с токеном
Браузер человека получает токен доступа напрямую. Вашему приложению не нужен никакой секрет.
-
Отправьте человека на адрес авторизации:
https://hivesigner.com/oauth2/authorize?client_id=CLIENT_ID&redirect_uri=REDIRECT_URI&scope=posting&state=STATE -
Человек одобряет. Hivesigner перенаправляет на ваш адрес возврата:
REDIRECT_URI?state=STATE&access_token=ACCESS_TOKEN&expires_in=604800&username=USERNAMEHivesigner добавляет свои параметры через
?, когда у вашего адреса нет строки запроса, и через&, когда она есть.stateпоявляется только тогда, когда вы отправили непустое значение. -
На своём адресе возврата сначала сверьте
state. Затем проверьте токен на своём сервере. Аккаунт, которому он принадлежит, находится внутри токена: не полагайтесь только на параметрusername, ведь адрес может изменить кто угодно. -
Держите токен на своём сервере или в cookie с httpOnly. Перенаправьте на чистый адрес, чтобы токен исчез из адресной строки.
-
Используйте токен с API, пока он не истечёт через
expires_inсекунд (7 дней). Затем снова отправьте человека на адрес авторизации. Тот, кто уже дал доступ к публикации, видит «Вход в APP» и «Вы уже авторизовали @myapp. Новые права не предоставляются.».
Поток с кодом
Ваш сервер получает код и обменивает его на токен доступа и токен обновления. Затем он может обновлять их без участия человека. Используйте это, когда ваш сервер действует за людей долгое время.
-
Отправьте человека на адрес авторизации с
scope=offline:https://hivesigner.com/oauth2/authorize?client_id=CLIENT_ID&redirect_uri=REDIRECT_URI&scope=offline&state=STATEscope=posting&response_type=codeделает то же самое. -
Человек одобряет доступ к публикации. Hivesigner перенаправляет на ваш адрес возврата:
REDIRECT_URI?code=CODE&state=STATE&username=USERNAME -
Сверьте
state. Затем сразу обменяйте код со своего сервера.
Обменяйте код
Отправьте код и свой секрет клиента на /api/oauth2/token в теле запроса POST:
curl -X POST https://hivesigner.com/api/oauth2/token \
-H 'Content-Type: application/json' \
-d '{"code": "CODE", "client_secret": "CLIENT_SECRET"}'
Ответ:
{
"access_token": "ACCESS_TOKEN",
"refresh_token": "REFRESH_TOKEN",
"expires_in": 604800,
"username": "alice"
}
Тот же вызов в Node.js 18 или новее:
const TOKEN_URL = 'https://hivesigner.com/api/oauth2/token';
export async function hivesignerTokens(grant) {
const res = await fetch(TOKEN_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
...grant,
client_secret: process.env.HIVESIGNER_CLIENT_SECRET,
}),
});
const data = await res.json();
if (!res.ok || data.error) {
throw new Error(`${data.error}: ${data.error_description}`);
}
return data; // { access_token, refresh_token, expires_in, username }
}
// On your callback, after checking state:
const tokens = await hivesignerTokens({ code: req.query.code });
- Помещайте код и секрет в тело запроса, а не в адрес.
- Не отправляйте с этим запросом заголовок
Authorization. - Используйте
usernameиз этого ответа. Он берётся из кода, который подписал человек. - Храните токен доступа и токен обновления на своём сервере.
Обновление
Когда токен доступа истекает, отправьте токен обновления вместе со своим секретом клиента на тот же адрес:
curl -X POST https://hivesigner.com/api/oauth2/token \
-H 'Content-Type: application/json' \
-d '{"refresh_token": "REFRESH_TOKEN", "client_secret": "CLIENT_SECRET"}'
const renewed = await hivesignerTokens({ refresh_token: stored.refresh_token });
Ответ имеет ту же форму, с новым токеном доступа и новым токеном обновления. Сохраните оба вместо прежних.
Защитите запрос через state
Без state другой сайт мог бы отправить вашего пользователя на ваш адрес возврата с токеном или кодом по своему выбору. Тогда ваше приложение выполнило бы вход в чужой аккаунт. state связывает каждое возвращение с тем браузером, где вход начался.
- Создавайте случайное значение на каждый вход, не меньше 16 случайных байтов. Шестнадцатеричная запись избавляет его от символов, требующих кодирования.
- Храните его там, где предъявить его снова может только этот браузер: сессия вашего сервера или недолговечная cookie с httpOnly, Secure и
SameSite=Lax. - Отправьте его как
stateв адресе авторизации. - На своём адресе возврата сверьте параметр
stateс сохранённым значением. Если он отсутствует или отличается, остановитесь: не используйте ни токен, ни код. - Удалите сохранённое значение, чтобы каждое срабатывало один раз.
app.get('/auth/callback', async (req, res) => {
const expected = req.session.hivesignerState;
delete req.session.hivesignerState;
if (!expected || req.query.state !== expected) {
return res.status(400).send('This sign-in has expired. Please try again.');
}
// Token flow: req.query.access_token. Code flow: req.query.code.
});
Hivesigner возвращает то же значение state, которое получил. Пустое он опускает.
Что видит человек
Экран согласия показывает изображение и название вашего приложения, «Аккаунт Hive @myapp» и «Перенаправит вас на HOST», где HOST берётся из вашего адреса возврата. Затем:
- Первый запрос на публикацию. Заголовок гласит «APP запрашивает доступ к вашему аккаунту.». Карточка Область доступа перечисляет, что сможет делать ваше приложение. Уведомление гласит «Первая авторизация: аккаунт @myapp будет добавлен в ваши постинг-полномочия в блокчейне, для чего один раз потребуется ваш активный ключ. Этот аккаунт сможет публиковать от вашего имени, пока вы не отзовёте доступ.». Кнопка гласит Авторизовать. Если на устройстве человека нет активного ключа для этого аккаунта, экран просит его здесь же.
- Вход. При
scope=loginили при уже выданном ранее доступе к публикации заголовок гласит «Вход в APP», а кнопка — Войти. - Аккаунт. «Авторизация от имени» или «Вход от имени», а следом выбранный аккаунт. Здесь человек может сменить аккаунт.
- Заблокированный аккаунт. Над кнопкой появляется поле кода доступа. Один щелчок снимает блокировку и продолжает.
- На устройстве нет аккаунтов. Кнопка гласит Продолжить. Она открывает форму добавления аккаунта, а затем возвращает к запросу.
После первого запроса на публикацию Hivesigner ждёт, пока новое разрешение станет видно в блокчейне, и только потом перенаправляет. Это может занять несколько секунд. Весь экран со стороны человека описан в Вход в приложения.
Отмена и отклонённые запросы
- Отмена. Человек переходит к своему списку аккаунтов в Hivesigner. На ваш адрес возврата ничего не отправляется: параметра ошибки нет. Оставьте кнопку входа доступной, чтобы человек мог начать заново. Не ждите возвращения.
- Отклонённые запросы. Незарегистрированный адрес возврата, неизвестный
client_idили отсутствующийredirect_uriпоказывают в Hivesigner ошибку с кнопкой Сообщить о проблеме. На ваш адрес возврата ничего не отправляется. Смотрите Что видят люди, когда что-то не так.
Старый адрес запроса входа
Hivesigner всё ещё принимает более старый адрес входа, оставленный для прежних интеграций. Для новых используйте /oauth2/authorize.
https://hivesigner.com/login-request/CLIENT_ID?redirect_uri=REDIRECT_URI&scope=posting&state=STATE
Он открывает тот же экран согласия, с теми же проверками адреса возврата и тем же перенаправлением. Но свои параметры он читает иначе:
scope— этоloginилиposting. Любое другое значение или его отсутствие означаетlogin.offlineне читается. Для потока с кодом добавьтеresponse_type=code.accountне читается.
https://hivesigner.com/login?client_id=CLIENT_ID&redirect_uri=REDIRECT_URI подчиняется тем же правилам.