Как подключить вход и регистрацию на сайт через Yandex ID
Вход через Яндекс — один из самых удобных способов авторизации для русскоязычной аудитории. В этой статье пошагово разберём, как подключить «Вход через Яндекс» к вашему сайту: от регистрации приложения в Яндекс OAuth до готового кода на примере Node.js/Express и чистого HTML.
Что такое OAuth 2.0 и как это работает
OAuth 2.0 — протокол авторизации, который позволяет пользователю дать вашему сайту ограниченный доступ к своим данным без передачи пароля.
Схема входа через Яндекс:
-
Пользователь нажимает «Войти через Яндекс».
-
Мы перенаправляем его на страницу Яндекса (
oauth.yandex.ru/authorize). -
Яндекс показывает окно согласия на передачу данных.
-
После подтверждения Яндекс редиректит пользователя обратно на наш сайт с кодом авторизации.
-
Сервер меняет этот код на access token.
-
С access token сервер запрашивает данные пользователя (email, имя, аватар).
-
Создаём/находим пользователя в БД и выдаём ему сессию.
Важно: обмен кода на токен и запрос данных выполняется на сервере, чтобы не раскрывать client_secret.
Шаг 1. Регистрация приложения в Яндексе
-
Перейдите на https://oauth.yandex.ru/ и войдите в свой аккаунт.
-
Нажмите «Создать приложение».
-
Выберите «Для доступа к API или отладки» (или «Веб-сервисы»).
-
Заполните форму:
-
Название — например, «Мой сайт».
-
Платформа — «Веб-сервисы».
-
Redirect URI — адрес, куда Яндекс вернёт пользователя, например:
texthttps://example.com/auth/yandex/callback
Для локальной разработки можно добавить
http://localhost:3000/auth/yandex/callback.
-
-
В разделе «Доступ к данным» отметьте нужные права. Для входа достаточно:
-
login:email— email пользователя; -
login:info— имя, фамилия, аватар; -
login:birthday,login:gender— опционально.
-
-
Сохраните приложение. Вы получите:
-
ClientID (публичный идентификатор);
-
Client secret (секретный ключ — не публикуйте его).
-
Официальная документация: https://yandex.ru/dev/id/doc/ru/
Шаг 2. Настройка проекта
Рассмотрим пример на Node.js + Express. Установите зависимости:
npm init -y npm install express axios express-session dotenv
Создайте файл .env:
YANDEX_CLIENT_ID=ваш_client_id YANDEX_CLIENT_SECRET=ваш_client_secret YANDEX_REDIRECT_URI=http://localhost:3000/auth/yandex/callback SESSION_SECRET=случайная_строка
Для продакшена добавьте
.envв.gitignoreи используйте менеджер секретов.
Шаг 3. Кнопка входа
На странице входа разместите ссылку на авторизацию Яндекса:
<a href="/auth/yandex" class="btn-yandex"> Войти через Яндекс </a>
Яндекс разрешает использовать свой логотип. Требования к оформлению: https://yandex.ru/dev/id/doc/ru/rules
Шаг 4. Редирект на Яндекс
Добавляем маршрут, который формирует URL авторизации:
// server.js const express = require('express'); const axios = require('axios'); const session = require('express-session'); require('dotenv').config(); const app = express(); app.use(session({ secret: process.env.SESSION_SECRET, resave: false, saveUninitialized: true, cookie: { secure: false } // true при HTTPS })); // 1. Начало авторизации app.get('/auth/yandex', (req, res) => { // Генерируем state для защиты от CSRF const state = Math.random().toString(36).substring(2); req.session.oauthState = state; const authUrl = 'https://oauth.yandex.ru/authorize?' + new URLSearchParams({ response_type: 'code', client_id: process.env.YANDEX_CLIENT_ID, redirect_uri: process.env.YANDEX_REDIRECT_URI, state }).toString(); res.redirect(authUrl); });
Параметр state — обязательная защита от CSRF-атак. Мы сохраняем его в сессии и проверяем на callback.
Шаг 5. Обработка callback
// 2. Callback: Яндекс вернул code app.get('/auth/yandex/callback', async (req, res) => { const { code, state, error } = req.query; // Проверка ошибки от Яндекса if (error) { return res.status(400).send('Авторизация отклонена пользователем'); } // Проверка state if (!state || state !== req.session.oauthState) { return res.status(400).send('Неверный state (возможна CSRF-атака)'); } delete req.session.oauthState; try { // 3. Меняем code на access_token const tokenResponse = await axios.post( 'https://oauth.yandex.ru/token', new URLSearchParams({ grant_type: 'authorization_code', code, client_id: process.env.YANDEX_CLIENT_ID, client_secret: process.env.YANDEX_CLIENT_SECRET, redirect_uri: process.env.YANDEX_REDIRECT_URI }), { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } } ); const { access_token } = tokenResponse.data; // 4. Получаем данные пользователя const userInfo = await axios.get( 'https://login.yandex.ru/info?format=json', { headers: { Authorization: `OAuth ${access_token}` } } ); const { id, default_email, real_name, first_name, last_name, default_avatar_id, is_avatar_empty } = userInfo.data; const user = { yandexId: id, email: default_email, name: real_name || `${first_name} ${last_name}`.trim(), avatar: is_avatar_empty ? null : `https://avatars.yandex.net/get-yapic/${default_avatar_id}/islands-200` }; // 5. TODO: найти или создать пользователя в БД // const dbUser = await findOrCreateUser(user); // Сохраняем в сессии req.session.user = user; req.session.save(() => res.redirect('/profile')); } catch (err) { console.error('OAuth error:', err.response?.data || err.message); res.status(500).send('Ошибка авторизации'); } }); // Страница профиля app.get('/profile', (req, res) => { if (!req.session.user) return res.redirect('/'); const u = req.session.user; res.send(` <h1>Привет, ${u.name}!</h1> <p>Email: ${u.email}</p> ${u.avatar ? `<img src="${u.avatar}" alt="avatar">` : ''} <a href="/logout">Выйти</a> `); }); app.get('/logout', (req, res) => { req.session.destroy(() => res.redirect('/')); }); app.listen(3000, () => console.log('Server: http://localhost:3000'));
Шаг 6. Сохранение пользователя в базе данных
Чтобы вход работал как полноценная регистрация, свяжите Яндекс-ID с записью в БД. Пример на Prisma (PostgreSQL):
model User {
id Int @id @default(autoincrement())
yandexId String @unique
email String? @unique
name String?
avatar String?
createdAt DateTime @default(now())
}
Логика «найти или создать»:
async function findOrCreateUser(yandexUser) { let user = await prisma.user.findUnique({ where: { yandexId: yandexUser.yandexId } }); if (!user) { user = await prisma.user.create({ data: { yandexId: yandexUser.yandexId, email: yandexUser.email, name: yandexUser.name, avatar: yandexUser.avatar } }); } return user; }
Совет: связывайте аккаунты по email осторожно. Если у вас есть обычная регистрация по email, сначала проверьте, нет ли уже пользователя с таким адресом, и предложите «привязать» Яндекс к существующему аккаунту.
Шаг 7. Хранение токена обновления (refresh token)
Access token Яндекса живёт ограниченное время. Если нужен долгий доступ к API (например, Яндекс.Диск, Метрика), запросите refresh_token:
// В запросе на authorize добавьте scope const authUrl = 'https://oauth.yandex.ru/authorize?' + new URLSearchParams({ response_type: 'code', client_id: process.env.YANDEX_CLIENT_ID, redirect_uri: process.env.YANDEX_REDIRECT_URI, scope: 'login:email login:info', state });
В ответе /token придёт refresh_token. Обновление токена:
const refreshed = await axios.post('https://oauth.yandex.ru/token', new URLSearchParams({ grant_type: 'refresh_token', refresh_token: storedRefreshToken, client_id: process.env.YANDEX_CLIENT_ID, client_secret: process.env.YANDEX_CLIENT_SECRET }), { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } } );
Храните refresh-токены в зашифрованном виде и никогда не отдавайте их на клиент.
Шаг 8. Безопасность: чек-лист
-
✅ Client secret — только на сервере. Не кладите его в фронтенд-код.
-
✅ Проверяйте
stateна каждом callback. -
✅ Используйте HTTPS в продакшене — Яндекс требует HTTPS для redirect URI (кроме localhost).
-
✅ Валидируйте redirect URI — Яндекс вернёт пользователя только на адрес из настроек приложения.
-
✅ Ограничивайте scope — запрашивайте только те права, которые реально нужны.
-
✅ Rate limiting — защитите эндпоинты
/auth/*от перебора. -
✅ Логируйте ошибки OAuth, но не пишите в логи токены и коды.
Частые ошибки и их решение
| Ошибка | Причина | Решение |
|---|---|---|
invalid_client |
Неверный client_id/client_secret |
Проверьте .env и настройки приложения |
redirect_uri_mismatch |
URI не совпадает с настройками | Добавьте точный URI в кабинете OAuth |
invalid_grant |
Код истёк (живёт ~10 мин) или использован повторно | Запрашивайте новый код |
403 Forbidden при /info |
Неверный формат заголовка | Используйте Authorization: OAuth <token>, не Bearer |
Альтернатива: готовые библиотеки
Если не хочется писать вручную, используйте Passport.js со стратегией passport-yandex:
npm install passport passport-yandex
const YandexStrategy = require('passport-yandex').Strategy; passport.use(new YandexStrategy({ clientID: process.env.YANDEX_CLIENT_ID, clientSecret: process.env.YANDEX_CLIENT_SECRET, callbackURL: process.env.YANDEX_REDIRECT_URI }, (accessToken, refreshToken, profile, done) => { // profile содержит данные пользователя Яндекса return done(null, profile); } ));
Документация: https://www.passportjs.org/packages/passport-yandex/
Полезные ссылки
-
Документация Яндекс ID для разработчиков: https://yandex.ru/dev/id/doc/ru/
-
Консоль приложений OAuth: https://oauth.yandex.ru/
-
Справочник API
login.yandex.ru/info: https://yandex.ru/dev/id/doc/ru/user-information -
Правила использования бренда Яндекса: https://yandex.ru/dev/id/doc/ru/rules
-
Спецификация OAuth 2.0 (RFC 6749): https://datatracker.ietf.org/doc/html/rfc6749
Итог
Подключение входа через Яндекс занимает около часа и состоит из пяти шагов: регистрация приложения → кнопка входа → редирект на Яндекс → обмен кода на токен → сохранение пользователя. Главное — держать client_secret на сервере, проверять state и использовать HTTPS. В результате вы получаете быструю регистрацию без пароля, подтверждённый email и доверие пользователей к знакомому бренду.




Комментарии 0
Комментариев пока нет. Будьте первым!