Что такое OAuth 2.0 с использованием Google или Яндекс?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
OAuth 2.0 - Безопасная аутентификация через внешних провайдеров
OAuth 2.0 - это стандартный протокол, который позволяет пользователям авторизоваться на твоем сайте, используя аккаунты Google, Яндекс или других сервисов. Это безопаснее, чем просить пароль, и удобнее для пользователя. Давайте разберёмся как это работает.
1. Основные концепции OAuth 2.0
OAuth 2.0 вводит несколько ключевых ролей:
const oauth2Roles = {
'Resource Owner': 'Пользователь (у которого есть аккаунт в Google)',
'Client (приложение)': 'Твой сайт / приложение',
'Authorization Server': 'Сервер Google (выдаёт токены)',
'Resource Server': 'API Google (хранит данные пользователя)'
};
// Процесс:
// 1. Пользователь нажимает "Войти через Google"
// 2. Твоё приложение перенаправляет на Google
// 3. Пользователь вводит пароль в Google (НЕ на твоём сайте)
// 4. Google выдаёт токен
// 5. Твоё приложение получает токен и создаёт сессию
2. Полный поток OAuth 2.0 с Google
Вот что происходит step-by-step:
// Шаг 1: Пользователь нажимает кнопку "Login with Google"
const step1 = {
action: 'Пользователь видит на странице кнопку',
code: '<button onClick="loginWithGoogle()">Login with Google</button>'
};
// Шаг 2: Фронтенд перенаправляет на Google
const step2 = {
action: 'Редирект на Google Auth URL',
url: 'https://accounts.google.com/o/oauth2/v2/auth',
params: {
client_id: 'YOUR_GOOGLE_CLIENT_ID',
redirect_uri: 'https://yourapp.com/callback', // Куда вернуться
scope: 'openid email profile', // Какие данные просим
response_type: 'code',
state: 'random_token_to_prevent_csrf' // Защита от атак
}
};
// Шаг 3: Пользователь авторизуется в Google
const step3 = {
action: 'Пользователь вводит пароль Google',
note: 'Это происходит на сервере Google, не на твоём сайте'
};
// Шаг 4: Google редирект с кодом авторизации
const step4 = {
action: 'Google редирект обратно на твой сайт',
url: 'https://yourapp.com/callback?code=AUTH_CODE&state=random_token',
code: 'Код авторизации (временный, действителен 10 минут)'
};
// Шаг 5: Backend обменивает код на токен
const step5 = {
action: 'Backend отправляет запрос на Google',
method: 'POST https://oauth2.googleapis.com/token',
body: {
code: 'AUTH_CODE_FROM_STEP4',
client_id: 'YOUR_GOOGLE_CLIENT_ID',
client_secret: 'YOUR_GOOGLE_CLIENT_SECRET', // НИКОГДА не в браузере!
redirect_uri: 'https://yourapp.com/callback',
grant_type: 'authorization_code'
},
response: {
access_token: 'TOKEN_FOR_API_REQUESTS',
id_token: 'JWT_TOKEN_WITH_USER_INFO',
refresh_token: 'TOKEN_TO_GET_NEW_ACCESS_TOKEN_LATER',
expires_in: 3600
}
};
// Шаг 6: Backend использует токен для получения данных пользователя
const step6 = {
action: 'Backend запрашивает данные пользователя',
url: 'https://www.googleapis.com/oauth2/v2/userinfo',
headers: {
'Authorization': 'Bearer ACCESS_TOKEN'
},
response: {
id: '123456789',
email: 'user@gmail.com',
name: 'John Doe',
picture: 'https://lh3.googleusercontent.com/...'
}
};
// Шаг 7: Backend создаёт пользователя и сессию
const step7 = {
action: 'Backend создаёт своего пользователя',
process: [
'Проверить, существует ли пользователь с email user@gmail.com',
'Если нет - создать нового пользователя',
'Создать сессию / JWT токен',
'Отправить сессию на фронтенд'
]
};
// Шаг 8: Пользователь авторизован
const step8 = {
action: 'Пользователь вошёл в приложение',
nextRequests: 'Все запросы отправляются с токеном сессии'
};
3. Практический пример - код на фронтенде (React)
import { GoogleOAuthProvider, GoogleLogin } from '@react-oauth/google';
function LoginPage() {
const handleSuccess = async (credentialResponse) => {
// credentialResponse.credential - JWT токен от Google
const token = credentialResponse.credential;
// Отправляем на backend
const response = await fetch('/api/v1/auth/google', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ token })
});
const data = await response.json();
// Сохраняем сессию
localStorage.setItem('session_token', data.session_token);
// Редирект на главную
window.location.href = '/';
};
const handleError = () => {
console.error('Login Failed');
};
return (
<GoogleOAuthProvider clientId="YOUR_GOOGLE_CLIENT_ID">
<GoogleLogin
onSuccess={handleSuccess}
onError={handleError}
/>
</GoogleOAuthProvider>
);
}
4. Практический пример - код на бэкенде (Python/FastAPI)
from google.auth.transport import requests
from google.oauth2 import id_token
from fastapi import APIRouter, HTTPException
from sqlalchemy.orm import Session
router = APIRouter(prefix="/api/v1/auth")
@router.post("/google")
async def google_login(payload: dict, db: Session):
# Шаг 1: Верифицировать JWT токен от Google
try:
idinfo = id_token.verify_oauth2_token(
payload['token'],
requests.Request(),
"YOUR_GOOGLE_CLIENT_ID"
)
except ValueError:
raise HTTPException(status_code=401, detail="Invalid token")
# Шаг 2: Извлечь информацию пользователя
email = idinfo.get('email')
name = idinfo.get('name')
google_id = idinfo.get('sub')
picture = idinfo.get('picture')
# Шаг 3: Найти или создать пользователя
user = db.query(User).filter(User.email == email).first()
if not user:
user = User(
email=email,
name=name,
google_id=google_id,
avatar_url=picture
)
db.add(user)
db.commit()
# Шаг 4: Создать сессию
session_token = generate_jwt_token(user.id)
return {
"session_token": session_token,
"user": {
"id": user.id,
"email": user.email,
"name": user.name
}
}
5. Отличие ID Token от Access Token
const tokens = {
idToken: {
purpose: 'Содержит информацию о пользователе',
format: 'JWT (можно декодировать и прочитать)',
content: {
sub: 'user_id',
email: 'user@gmail.com',
name: 'John',
iat: 1234567890,
exp: 1234571490
},
usage: 'Использовать для создания сессии на бэкенде',
security: 'Нужно верифицировать подпись!'
},
accessToken: {
purpose: 'Для доступа к Google API',
format: 'Непрозрачный токен',
usage: 'Отправлять в header Authorization при запросах к Google API',
example: 'GET /oauth2/v2/userinfo -H "Authorization: Bearer ACCESS_TOKEN"',
lifetime: '1 час (потом нужен refresh)'
},
refreshToken: {
purpose: 'Для получения новых access tokens',
lifetime: 'Долгоживущий (может быть до года)',
usage: 'Сохранять на бэкенде, не отправлять на фронтенд',
example: 'Если access_token истёк, используй refresh_token для получения нового'
}
};
6. OAuth 2.0 с Яндексом
Процесс примерно такой же, но некоторые детали отличаются:
const yandexOAuth = {
authUrl: 'https://oauth.yandex.ru/authorize',
tokenUrl: 'https://oauth.yandex.ru/token',
userinfoUrl: 'https://login.yandex.ru/info',
params: {
client_id: 'YOUR_YANDEX_CLIENT_ID',
redirect_uri: 'https://yourapp.com/callback',
response_type: 'code',
state: 'random_string'
},
differences: [
'Yandex не выдаёт ID token по умолчанию',
'Нужно использовать access_token для получения информации',
'Процесс немного отличается'
]
};
7. Безопасность OAuth 2.0
const security = {
clientSecret: {
rule: 'НИКОГДА не передавай client_secret на фронтенд',
reason: 'Его может видеть любой в DevTools',
correct: 'Используй только на защищённом бэкенде'
},
codeVerifier: {
name: 'PKCE (Proof Key for Public Clients)',
use: 'Для фронтенд-приложений без бэкенда',
process: 'Генерируешь code_verifier на клиенте, отправляешь хеш на сервер'
},
state: {
purpose: 'Защита от CSRF атак',
rule: 'Всегда генерируй уникальный state и проверяй при возврате'
},
redirectUri: {
rule: 'Регистри ровань в Google только те URI, на которые будешь редиректить',
security: 'Иначе злоумышленник может перехватить код'
}
};
8. Типичные ошибки
const mistakes = {
'Не проверил подпись ID token': 'Может быть поддельный токен',
'Передал client_secret на фронтенд': 'Уязвимость безопасности',
'Не проверил state при возврате': 'CSRF атака возможна',
'Сохранил refresh_token на фронтенде': 'Может быть украден из localStorage',
'Не обработал истечение access_token': 'Запросы начнут падать'
};
9. Когда использовать OAuth
const useOAuth = [
'Быстрая регистрация - пользователь не вводит пароль',
'Безопасность - пароль не передаётся твоему серверу',
'Удобство - один клик вместо заполнения формы',
'Многофакторная аутентификация - если Google/Yandex требуют',
'Универсальность - один аккаунт для всех сервисов'
];
const dontUseOAuth = [
'Если тебе нужна максимальная контроль над аутентификацией',
'Если требуется специальная логика (например, пригласительные коды)',
'Если нужна полная независимость от внешних сервисов'
];
10. Что происходит если пользователь удалит приложение
const removal = {
scenario: 'Пользователь отозвал доступ приложению в Google',
process: [
'1. Пользователь идёт в Google Account -> Security',
'2. Удаляет твоё приложение из подключённых приложений',
'3. Google аннулирует всё tokens (access и refresh)',
'4. Твоё приложение получит 401 Unauthorized при следующем запросе'
],
recovery: 'Отправь пользователя снова на авторизацию через Google'
};
Итог
OAuth 2.0 - это стандартный и безопасный способ аутентификации через Google, Яндекс и других провайдеров. Основной процесс: пользователь редиректится на Google -> авторизуется -> получает код -> бэкенд обменивает код на токен -> создаёт сессию. Это намного безопаснее, чем просить пароль, и удобнее для пользователя. Главное - не забывай о безопасности: никогда не передавай client_secret на фронтенд, проверяй state, верифицируй токены.