Увійти через AniHub
Вхід на ваш сайт акаунтом AniHub. Звичайний OpenID Connect — бібліотека підключається одним URL. Застосунок реєструєте самі.
Зареєструвати застосунокЗа хвилину
Auth.js, Passport, Authlib, Spring Security, Keycloak — усі вміють OpenID Connect. Дайте бібліотеці одну адресу:
https://anihub.in.ua/.well-known/openid-configurationРешту вона вичитає звідти сама. Конфіг, Auth.js / NextAuth:
providers: [
{
id: "anihub",
name: "AniHub",
type: "oidc",
issuer: "https://anihub.in.ua",
clientId: process.env.ANIHUB_CLIENT_ID,
clientSecret: process.env.ANIHUB_CLIENT_SECRET,
authorization: {
params: { scope: "openid profile email" },
},
},
]clientId і clientSecret — з картки застосунку в Налаштування → Розробникам.
Зберігайте sub: нікнейм і пошту користувач може змінити.
Адресу повернення бібліотеки (в Auth.js це /api/auth/callback/anihub) додайте до застосунку — збіг побайтовий.
Два типи застосунків
Питання одне: чи є у вас сервер, де може лежати секрет. Тип не змінюється після реєстрації.
Є серверна частина
Next.js з API-роутами, Django, Laravel, Express. Отримуєте client_secret і обмінюєте код зі свого сервера через Authorization: Basic.
Тільки браузер або телефон
SPA, мобільний чи десктопний застосунок. Секрету немає — у коді, що їде до користувача, він не сховається. Замість Basic надсилаєте client_id у тілі, захищає PKCE.
Якщо робите вручну
PKCE-пара
ваш серверcode_verifier тримайте в сесії. В URL іде тільки його хеш.
code_verifier=$(openssl rand -base64 60 | tr -d '=+/' | cut -c1-64)
code_challenge=$(printf '%s' "$code_verifier" \
| openssl dgst -binary -sha256 | openssl base64 -A \
| tr '+/' '-_' | tr -d '=')Екран згоди
браузерРедирект, не запит із коду.
https://anihub.in.ua/api/oauth/authorize
?response_type=code
&client_id=YOUR_CLIENT_ID
&redirect_uri=https%3A%2F%2Fexample.com%2Fauth%2Fcallback
&scope=openid%20profile%20email
&state=xyzABC123
&nonce=n-0S6_WzA2Mj
&code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM
&code_challenge_method=S256Параметри
response_typestringобовʼязковийЗавжди code.
client_idstringобовʼязковийЗ картки застосунку.
redirect_uriurlобовʼязковийПобайтовий збіг із зареєстрованою.
scopestringобовʼязковийЧерез пробіл, з openid.
statestringобовʼязковийПовернемо як є. Звірте.
code_challengestringобовʼязковийbase64url(SHA-256(code_verifier)).
code_challenge_methodstringобовʼязковийТільки S256.
noncestringПовернемо в id_token. Звірте.
promptstringconsent — питати згоду знову. none — без UI, інакше помилка.
Код на вашій адресі
ваш серверhttps://example.com/auth/callback?code=SplxlOBeZQQYbYS6WxSbIA&state=xyzABC123Звірте state. Не збігається — припиняйте. Відмова користувача приходить як error=access_denied.
Обмін коду на токени
ваш серверФорма, не JSON. Тільки з сервера — тут секрет.
curl -X POST https://anihub.in.ua/api/oauth/token \
-u "$CLIENT_ID:$CLIENT_SECRET" \
-d grant_type=authorization_code \
-d code="$CODE" \
-d redirect_uri=https://example.com/auth/callback \
-d code_verifier="$CODE_VERIFIER"Тіло запиту
grant_typestringобовʼязковийauthorization_code
codestringобовʼязковийОдноразовий, 60 секунд.
redirect_uriurlобовʼязковийТой самий рядок, що в кроці 2.
code_verifierstringобовʼязковийОригінал, не хеш.
client_idstringТільки публічні застосунки, замість Basic.
{
"access_token": "ahb_at_qkT9v2Nb…",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "email openid profile",
"id_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6…"
}Відповідь
access_tokenstringНепрозорий рядок, не JWT.
token_typestringBearer
expires_inintСекунди.
scopestringЩо дозволили. Може бути вужче за запит.
id_tokenJWTЯкщо просили openid. RS256.
refresh_tokenstringЯкщо просили offline_access. Ротується.
id_token і профіль
ваш серверПідпис — ключем із /.well-known/jwks.json. Звірте iss, aud, exp, nonce. Профіль — із claims або запитом:
curl https://anihub.in.ua/api/oauth/userinfo \
-H "Authorization: Bearer $ACCESS_TOKEN"{
"sub": "12345",
"preferred_username": "gluko",
"name": "gluko",
"picture": "https://anihub.in.ua/media/avatars/u12345_….webp",
"profile": "https://anihub.in.ua/profile/gluko",
"email": "[email protected]",
"email_verified": true
}Усі ендпоінти
| GET | /.well-known/openid-configuration | Discovery — з цього починає будь-яка бібліотека |
| GET | /.well-known/jwks.json | Публічні ключі для перевірки id_token |
| GET | /api/oauth/authorize | Початок входу (браузер користувача) |
| POST | /api/oauth/token | Обмін коду на токени; оновлення (ваш сервер) |
| GET | /api/oauth/userinfo | Профіль за access-токеном |
| GET | /api/oauth/library | Список аніме користувача (library:read) |
| PUT | /api/oauth/library/{id} | Створити або оновити запис (library:write) |
| GET | /api/oauth/logout | Вихід із вашого застосунку (RP-initiated logout) |
| POST | /api/oauth/revoke | Відкликати конкретний токен |
| POST | /api/oauth/introspect | Перевірка токена (конфіденційні клієнти) |
Дозволи
Кожен дозвіл — окремий рядок на екрані згоди. Просіть мінімум.
openidОбовʼязковий
Ідентифікатор користувача (sub) та id_token.
profileПрофіль
Нікнейм, аватар і посилання на профіль.
emailПошта
Адреса електронної пошти та ознака підтвердження.
library:readСписок аніме
GET /api/oauth/library — статуси, прогрес, оцінки.
library:writeКерування списком
PUT / DELETE /api/oauth/library/{anime_id} — додати, змінити, прибрати запис.
offline_accessПостійний доступ
refresh_token, щоб не просити вхід щогодини.
Refresh-токен ротується при кожному використанні, повторне пред'явлення гасить увесь ланцюжок — не запускайте два паралельні оновлення.
Вихід
Коли користувач тисне «вийти» у вас, надішліть його на:
GET https://anihub.in.ua/api/oauth/logout
?id_token_hint=<id_token, який ви отримали при вході>
&post_logout_redirect_uri=https://example.com/
&state=<ваш state>Відкликаємо всі токени вашого застосунку для цього користувача.
post_logout_redirect_uriмає бути зареєстрована — незареєстровану ігноруємо й показуємо власну сторінку.id_token_hintможе бути протермінований. Перевіряємо підпис, не строк.- З акаунта AniHub користувач не виходить, і згода лишається.
Перевірка застосунку
Новий застосунок працює одразу. До перевірки — застереження на екрані згоди й ліміт у 10 користувачів; ліміт лише на нових, наявні працюють далі. Заявку подаєте в налаштуваннях.
Інше
- Адреси повернення — побайтово.
/cbі/cb/різні. https://— усім. Публічним ще йhttp://127.0.0.1:портта власна схемаcom.example.app:/cb.localhostне приймається — лише IP.- Домен належить тому, хто зареєстрував першим. Чужий і домен AniHub не приймаються; loopback спільний.
- Назва й опис не можуть містити «AniHub» чи натякати на офіційність.
- Секрет показується один раз — далі лише перевипуск.
- Доступ відкликається будь-коли. Обробляйте
invalid_grantяк «треба увійти знову».
Готові почати?
Потрібна лише підтверджена пошта на акаунті.