Вход через Google добавляется на сайт или в приложение с помощью OAuth 2.0 и его слоя идентификации OpenID Connect (OIDC). Коротко: пользователь перенаправляется в Google, Google проверяет личность и отправляет вашему сайту подписанный ID-токен; ваш сервер проверяет подпись и получателя токена, сопоставляет пользователя со своими записями и открывает собственную сессию. Ваш сайт никогда не видит и не хранит пароль от Google. Техническая настройка занимает немного времени; проект растягивают связывание аккаунтов, управление сессиями и требования корпоративных клиентов к единому входу (SSO). В этой статье описана схема, которую мы применяем в корпоративных веб-проектах; это часть нашей услуги разработки сайтов, отвечающая за аутентификацию.
OAuth, OpenID Connect и SSO: что есть что
В обиходе эти три термина используют как синонимы, но они отвечают на три разных вопроса. OAuth 2.0 протокол делегирования прав: он говорит «это приложение может читать мой календарь от моего имени», но не говорит, кто вы. OpenID Connect слой идентификации поверх OAuth: подписанный ID-токен сообщает «этот пользователь имеет такую-то идентичность, его почта подтверждена». Вход через Google на практике и есть OpenID Connect. SSO (single sign-on) архитектурная цель: пользователь входит один раз и получает доступ к нескольким приложениям без повторного ввода пароля. Потребности бывают двух видов:
- Социальный вход (B2C): ваши клиенты регистрируются и входят через аккаунт Google, Apple или Microsoft. Цель снизить трение и не брать на себя управление паролями.
- Корпоративный SSO (B2B / внутренние приложения): сотрудники входят через провайдера идентификации компании (Google Workspace, Microsoft Entra ID, Keycloak). Цель централизованное управление доступом: при увольнении доступ отключается в одном месте.
Оба варианта используют один протокол, но продуктовые решения различаются. При социальном входе провайдера выбирает пользователь; при корпоративном SSO провайдера задаёт компания-клиент и обычно хочет подключить собственного арендатора через SAML или OIDC.
Схема входа через Google по шагам
Рекомендуемая схема «authorization code с PKCE». Старый implicit flow, выдававший токены в браузере, больше не рекомендуется; токены всегда получает сервер, а браузеру достаётся только ваш собственный cookie сессии.
- В Google Cloud Console создаётся OAuth-клиент; разрешённые адреса возврата (redirect URI) регистрируются с точным совпадением, без масок.
- Когда пользователь нажимает «Войти через Google», сервер генерирует случайный state и PKCE code_verifier, сохраняет их в короткоживущем cookie и перенаправляет пользователя на адрес авторизации Google.
- Google проверяет личность, показывает пользователю, какие данные будут переданы, и запрашивает согласие; браузер возвращается на ваш callback-адрес с параметром code.
- Сервер сверяет state с cookie и обменивает code на ID-токен на token-эндпоинте Google (с client_secret и code_verifier).
- Подпись ID-токена проверяется по опубликованным ключам Google вместе с полями iss, aud и сроком действия; почта должна быть отмечена как подтверждённая.
- Пользователь находится или создаётся в базе, ваш cookie сессии завершает вход. Токен Google в браузер не передаётся.
Пример: callback как route handler в Next.js
// app/api/auth/google/callback/route.ts
import { createRemoteJWKSet, jwtVerify } from 'jose';
const GOOGLE_JWKS = createRemoteJWKSet(
new URL('https://www.googleapis.com/oauth2/v3/certs'),
);
export async function GET(req: Request) {
const url = new URL(req.url);
const code = url.searchParams.get('code');
const state = url.searchParams.get('state');
// state записан в cookie при старте входа: защита от CSRF
if (!code || !state || state !== await readStateCookie()) {
return new Response('Недопустимый запрос', { status: 400 });
}
// обмен code -> токен всегда выполняется на сервере
const tokenRes = await fetch('https://oauth2.googleapis.com/token', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({
code,
grant_type: 'authorization_code',
client_id: process.env.GOOGLE_CLIENT_ID!,
client_secret: process.env.GOOGLE_CLIENT_SECRET!,
redirect_uri: process.env.GOOGLE_REDIRECT_URI!,
code_verifier: await readVerifierCookie(),
}),
});
const { id_token } = (await tokenRes.json()) as { id_token: string };
// проверка подписи, издателя, получателя и срока
const { payload } = await jwtVerify(id_token, GOOGLE_JWKS, {
issuer: ['https://accounts.google.com', 'accounts.google.com'],
audience: process.env.GOOGLE_CLIENT_ID,
});
if (payload.email_verified !== true) {
return new Response('Почта не подтверждена', { status: 403 });
}
// идентичность это постоянный "sub" от Google, а не адрес почты
const user = await findOrLinkUser({
provider: 'google',
subject: payload.sub!,
email: String(payload.email),
});
return createSessionAndRedirect(user.id, '/dashboard');
}Связывание аккаунтов: где проекты застревают
На большинстве сайтов, добавляющих вход через Google, уже есть пользователи с почтой и паролем. Если заранее не решить, что произойдёт, когда тот же человек войдёт через Google, появятся либо два отдельных аккаунта, либо будут объединены не те. Проблему решают три правила. Первое: идентичность пользователя не адрес почты, а постоянное значение sub, которое присылает Google; почта меняется, sub нет. Второе: автоматическое объединение с существующим аккаунтом выполняется только если Google подтвердил почту; иначе войти сможет аккаунт, выдающий чужой адрес за свой. Третье: пользователь должен иметь возможность привязать несколько провайдеров, поэтому данные провайдера хранятся в отдельной таблице «идентичности» (пользователь, провайдер, sub), а не в колонках таблицы пользователей.
Ключ пользователя не почта, а постоянный идентификатор, выданный провайдером. Система, где ключом служит почта, путает аккаунты, как только адрес меняется или другой провайдер присылает тот же адрес без подтверждения.
Корпоративный SSO: Google Workspace и Microsoft Entra
Когда SSO нужен для B2B-продукта или внутренней панели, задача вырастает на несколько шагов. Нужно ограничить, какие домены могут входить: поле hd в ID-токене Google содержит домен Workspace пользователя, но это только проверка, а не замена авторизации. Если пользователи создаются автоматически при первом входе (just-in-time provisioning), должна быть определена стартовая роль; проектирование ролей мы описали в статье о ролях пользователей и авторизации. Если подключается Microsoft Entra или другой арендатор, клиент обычно регистрирует ваше приложение на своей стороне через SAML или OIDC, а вы храните отдельного издателя и набор ключей для каждого клиента. Чаще всего забывают о выходе: когда сотрудник увольняется, его аккаунт у провайдера закрывается, но ваша открытая сессия живёт до собственного истечения. Делайте сессии короткими или обрабатывайте уведомление провайдера о выходе.
Чек-лист безопасности
- state и PKCE обязательны в каждом запросе; state одноразовый и сверяется с cookie при callback.
- Redirect URI зарегистрированы с точным совпадением; для теста и продакшена используются отдельные клиенты, а client_secret никогда не попадает в браузер или мобильную сборку.
- ID-токен используется только для идентификации; вызовы API авторизует ваша собственная сессия или выданный вами токен. Отправлять ID-токен другим сервисам как ключ доступа распространённая ошибка.
- Scope минимальны: openid, email и profile достаточно для большинства сайтов. Доступ к календарю или Drive при необходимости запрашивается отдельно и позже.
- Путь восстановления для пользователя, потерявшего аккаунт Google, проектируется заранее: одноразовая ссылка на почту или второй провайдер. Аккаунты, привязанные к одному провайдеру, самый частый источник обращений в поддержку.
- На эндпоинты входа ставится ограничение частоты, неудачные попытки логируются; остальные поверхности атаки разобраны в статье о безопасности сайта.
Для рискованных действий (подтверждение платежа, изменение прав) одного входа через Google недостаточно; запрашивайте второе подтверждение в момент действия. Эту сторону мы разобрали в статье о SMS OTP-верификации.
Готовый сервис идентификации или своя реализация?
Облачные сервисы вроде Auth0, Firebase Authentication и Clerk, а также самостоятельно размещаемые продукты вроде Keycloak дают всю эту схему, сброс пароля и многофакторную аутентификацию из коробки. Для одного провайдера и простой модели пользователей достаточно собственной реализации с библиотекой вроде Auth.js, и данные пользователей остаются в вашей базе. Если одновременно нужны мультиарендный SSO, поддержка SAML, многофакторная аутентификация и журналы аудита, готовый сервис или Keycloak сокращают проект на недели. Решают два вопроса: где будут храниться данные пользователей и можно ли при уходе из сервиса экспортировать пользователей вместе с хешами паролей? Если таблица пользователей в вашей базе, второй вопрос решается сам собой; этот подход согласуется и с мультиарендной моделью из статьи о разработке SaaS-продукта.
Замечание о персональных данных
При входе через Google вам передаются имя, почта и фото профиля; это персональные данные, и в политике конфиденциальности должны быть указаны их источник (провайдер идентификации) и цель обработки. Запрашивайте только то, что нужно для входа, и не храните фото профиля, если оно не используется. Турецкий правовой контекст описан в статье о сайте, соответствующем KVKK; этот текст не является юридической консультацией.
Вывод
При правильной реализации вход через Google даёт пользователям регистрацию без трения, а вашему сайту избавление от хранения паролей. Техническая схема стандартна; проект определяют правила связывания аккаунтов, срок жизни сессии и ожидания корпоративных клиентов по SSO. Если вы хотите добавить социальный вход или корпоративный SSO на существующий сайт, отправьте требования через форму запроса, и мы спланируем схему вместе с вашей текущей таблицей пользователей.