Руководство по интеграции
Добавьте «Вход через Tutu» в свой продукт за четыре шага с OAuth2 + PKCE.
Четыре шага для интеграции
Фронтенд запускает вход
Создайте экземпляр через createTutuId({ baseUrl, clientId }) из @tutu/id-sdk и вызовите idSdk.startLogin() по клику. SDK генерирует пару PKCE и перенаправляет на страницу авторизации TutuId.
Пользователь авторизуется в TutuId
На экране согласия /oauth/authorize пользователь нажимает «Разрешить» (пропускается, если уже авторизовал). Проверив client_id и белый список redirect_uri, TutuId возвращает на ваш /auth/callback с кодом авторизации.
Страница обратного вызова получает code
На /auth/callback вызовите idSdk.completeCallback(), чтобы получить { code, codeVerifier }. Передайте эти два значения своему бэкенду — никогда не обменивайте token прямо в браузере.
Бэкенд обменивает token → создаёт аккаунт
Ваш бэкенд обменивает code + codeVerifier на access_token, вызывает /userinfo для { sub, email, emailVerified, ... }, сопоставляет или создаёт локальный аккаунт по sub, затем выдаёт собственную сессию.
★ Защита от захвата аккаунта (обязательно)
Ваш бэкенд может связывать или создавать локальный аккаунт только по sub (уникальному ID аккаунта). Только когда emailVerified === true, можно связать существующий локальный аккаунт по email; иначе создайте отдельный аккаунт и оставьте email пустым.
Почему: злоумышленник может заранее зарегистрировать аккаунт Tutu на email жертвы; слияние по неподтверждённому email выдаст локальный аккаунт жертвы. Это красная линия уровня CVE.
Справочник по API SDK
@tutu/id-sdk · чисто клиентский, без зависимостей (нужны Web Crypto + sessionStorage).
createTutuId({ baseUrl, clientId, redirectUri? }) Создаёт экземпляр SDK. redirectUri по умолчанию ${location.origin}/auth/callback и адаптируется к dev/prod.
startLogin(scope?) Генерирует пару PKCE и перенаправляет на страницу авторизации, запуская «Вход через Tutu».
trySilentLogin(scope?) Тихий вход: при наличии центральной сессии и прежней авторизации бесшовно обменивает код; иначе сразу возвращает состояние «вышел» (не мешая пользователю).
completeCallback() Разбирает результат на странице обратного вызова: при успехе возвращает { code, codeVerifier }, при ошибке/отмене — { error }.
logoutEverywhere(returnTo?) Завершает центральную сессию, каскадно выходя из всех продуктов набора, затем возвращает на returnTo.
Хотите сначала посмотреть в действии?