Что такое OAuth 2.0 и зачем он нужен
OAuth 2.0 — это протокол не аутентификации, а авторизации. Он даёт другому сервису право действовать от имени пользователя, не запрашивая его пароль. Например, если пользователь входит на Sayt.uz через Google, Sayt.uz не знает его пароля от Google, а получает только email и данные профиля через выданный Google access token.
В протоколе четыре основных участника: resource owner (пользователь), client (приложение), authorization server (Google) и resource server (Google API). Это разделение обеспечивает безопасность: приложение никогда не видит пароль пользователя, а пользователь может в любой момент отозвать доступ.
Authorization code flow
Самый безопасный и стандартный flow — authorization code flow. Пользователя перенаправляют на страницу Google, где он входит. Google выдаёт специальный authorization code и возвращает пользователя в приложение. Приложение со своего сервера вместе с client_secret отправляет этот code в Google и в обмен получает access token.
Преимущество этого flow в том, что access token не проходит через браузер, а обменивается только между бэкендами. Это защищает от XSS и утечки токенов. На Sayt.uz все варианты social login работают через этот flow.
PKCE — защита для public client
Мобильные и SPA-приложения не могут безопасно хранить client_secret, потому что они работают на устройстве пользователя. Для решения этой проблемы существует стандарт PKCE (Proof Key for Code Exchange). Приложение создаёт случайный code_verifier и отправляет его SHA256-хеш (code_challenge) вместе с authorization-запросом.
При обмене токенов приложение повторно отправляет оригинальный code_verifier. Google хеширует его и сравнивает с исходным code_challenge. Если совпало — токен выдаётся. Даже если злоумышленник украдёт authorization code, без code_verifier он бесполезен.
Refresh token и длительность сессии
Access token короткоживущий (1 час), refresh token — долгоживущий (30-90 дней). Чтобы пользователь не входил заново каждый час, приложение через refresh token автоматически получает новый access token. Refresh token должен храниться только на бэкенде и никогда не передаваться в браузер открытым.
В практике Sayt.uz внедрена rotation refresh-токенов: при каждом refresh старый отзывается и выдаётся новый. Если отозванный токен используется повторно — это признак кражи, все сессии пользователя принудительно закрываются, и на email отправляется предупреждение.
Интеграция с Google и Facebook
У каждого провайдера свой authorization endpoint, token endpoint и userinfo endpoint. У Google это accounts.google.com и www.googleapis.com, у Facebook — graph.facebook.com. Различаются и scope-параметры: у Google стандарт openid profile email, у Facebook — public_profile email.
На Sayt.uz создан единый интерфейс для провайдеров: каждый провайдер реализует свой adapter с одинаковыми методами getAuthUrl, getAccessToken, getUserInfo. Это упрощает добавление новых провайдеров без изменения основной логики login.
Практика Sayt.uz
На Sayt.uz интеграция OAuth такая: authorization code flow для всех провайдеров, обязательный PKCE для public client, параметр state защищает от CSRF, nonce — от replay attack. Access token в Redis на 1 час, refresh token — в зашифрованном виде в PostgreSQL. Каждый login и refresh пишется в audit log.