Сегодня мы погрузимся в процесс аутентификации с использованием OAuth2, который является основным методом обеспечения безопасности при доступе к Google API. Изучим, как настроить FastAPI для работы с аутентификацией OAuth2, и выполним практическое взаимодействие с Google API через полученные токены доступа.
Прежде чем нырнуть в дебри кода, давайте разберёмся, зачем вообще нужен OAuth2 и как он работает.
Представьте, что вы заходите в кофейню и хотите получить доступ к её Wi-Fi. Вместо того, чтобы попросить владельца об учётных данных от маршрутизатора, вы используете QR-код для авторизации на временный доступ. OAuth2 работает примерно так же, только вместо кофе и Wi-Fi вы получаете доступ к таким "сервисам", как Google Sheets, Gmail или Google Maps.
OAuth2 — это протокол авторизации, который позволяет вашему приложению получить ограниченный доступ к ресурсам от имени пользователя. Ключевые преимущества:
- Безопасность: мы используете токены вместо того, чтобы хранить данные логина и пароля.
- Гибкость: можно получить разные уровни доступа (например, только чтение или полный доступ).
- Асинхронность: отлично интегрируется в API.
Типичная "история OAuth2" состоит из следующих шагов:
- Пользователь заходит в ваше приложение и нажимает кнопку "Авторизоваться через Google".
- Ваш сервер перенаправляет пользователя на страницу авторизации Google, где он логинится и подтверждает доступ.
- Google возвращает вашему серверу временный код авторизации.
- Сервер обменивает этот код на долгоживущий токен доступа (access token).
- Вы используете токен для запросов к Google API.
Итак, теории хватит (хотя если не хватит, вот вам официальная документация: OAuth2 Overview)
На а теперь — к настройкам!
Настройка OAuth2 в Google Cloud Console
Чтобы воспользоваться OAuth2, нужно подготовить нашу площадку в Google Cloud Console.
Создадим учётные данные для OAuth
- Зайдите в Google Cloud Console.
- Откройте ваш проект или создайте новый.
- Перейдите в раздел APIs & Services → Credentials.
- Нажмите Create Credentials → OAuth 2.0 Client IDs.
- Выберите Web application в качестве Application Type.
- Укажите имя клиента. Например, "FastAPI Google Auth".
- Добавьте в поле Authorized redirect URIs URL, куда будет возвращён пользователь после авторизации. Например:
http://localhost:8000/auth/callback - Сохраните настройки и скачайте файл с учётными данными (JSON формат).
создайте файл client_secret.json и сохраните в корне вашего проекта. Никогда не публикуйте этот файл в открытом доступе (например, на GitHub).
Интеграция OAuth2 с FastAPI
Теперь, когда у нас есть учётные данные, пришло время интегрировать их в наше приложение на FastAPI.
Теперь установим зависимости. OAuth2 взаимодействует с Google через HTTP-запросы. Для этого нам понадобится несколько библиотек:
pip install httpx google-auth google-auth-oauthlib
Начнём с настройки базового приложения FastAPI. Создадим эндпоинты для перенаправления на Google для авторизации и получения токенов.
from fastapi import FastAPI, HTTPException
from fastapi.responses import RedirectResponse
import httpx
import os
import json
from urllib.parse import urlencode
app = FastAPI()
# Загрузка клиентских данных из файла
with open("client_secret.json", "r") as f:
client_config = json.load(f)
CLIENT_ID = client_config["web"]["client_id"]
CLIENT_SECRET = client_config["web"]["client_secret"]
REDIRECT_URI = "http://localhost:8000/auth/callback"
AUTHORIZATION_URL = "https://accounts.google.com/o/oauth2/v2/auth"
TOKEN_URL = "https://oauth2.googleapis.com/token"
SCOPES = ["https://www.googleapis.com/auth/drive.readonly"]
user_tokens = {} # Простая структура для хранения токенов пользователей (не используется в продакшене)
Создадим эндпоинт для авторизации.
Этот эндпоинт перенаправляет пользователя на страницу Google для получения кода авторизации:
@app.get("/auth")
def auth_request():
# Формируем URL для авторизации
params = {
"client_id": CLIENT_ID,
"response_type": "code",
"redirect_uri": REDIRECT_URI,
"scope": " ".join(SCOPES),
"access_type": "offline",
"prompt": "consent",
}
url = f"{AUTHORIZATION_URL}?{urlencode(params)}"
return RedirectResponse(url)
Теперь нам нужен эндпоинт для получения токена. После успешной авторизации Google перенаправит пользователя с кодом авторизации на указанный нами URI. Обрабатываем этот код, чтобы получить токен:
@app.get("/auth/callback")
async def auth_callback(code: str):
# Формируем запрос для обмена кода на токен
payload = {
"code": code,
"client_id": CLIENT_ID,
"client_secret": CLIENT_SECRET,
"redirect_uri": REDIRECT_URI,
"grant_type": "authorization_code",
}
async with httpx.AsyncClient() as client:
token_response = await client.post(TOKEN_URL, data=payload)
if token_response.status_code != 200:
raise HTTPException(status_code=token_response.status_code, detail="Ошибка получения токена")
# Сохраняем токен для текущего сеанса
token_data = token_response.json()
user_tokens["access_token"] = token_data["access_token"]
user_tokens["refresh_token"] = token_data.get("refresh_token")
return {"access_token": token_data["access_token"]}
Как использовать токены для запросов к API?
Поздравляю! Теперь у нас есть токены доступа. Давайте использовать их для взаимодействия с Google API. Например, мы попробуем получить список файлов на Google Диске.
Эндпоинт для доступа к Google Drive API
DRIVE_API_URL = "https://www.googleapis.com/drive/v3/files"
@app.get("/drive/files")
async def get_drive_files():
access_token = user_tokens.get("access_token")
if not access_token:
raise HTTPException(status_code=401, detail="Необходима авторизация")
# Запрос к Google Drive API
headers = {"Authorization": f"Bearer {access_token}"}
async with httpx.AsyncClient() as client:
response = await client.get(DRIVE_API_URL, headers=headers)
if response.status_code != 200:
raise HTTPException(status_code=response.status_code, detail="Ошибка Google API")
return response.json()
Попробуйте открыть браузер, перейти по пути /auth, успешно авторизоваться, а затем вызвать /drive/files.
Типичные ошибки и как их избежать
Работа с OAuth2 может быть немного сложной из-за множества нюансов. Вот несколько распространённых подводных камней:
- Не забывайте обновлять токены: токены доступа обычно имеют срок действия (около часа). Используйте
refresh_tokenдля получения нового. - Настройки редиректа: URL, указанный в Google Cloud Console, должен точно совпадать с указанным в коде. Даже лишний
/может вызвать ошибки. - Разграничение прав доступа: убедитесь, что ваш токен имеет соответствующие разрешения (scopes) для действий, которые вы пытаетесь выполнить.
Теперь у нас есть основа для интеграции FastAPI с Google API через OAuth2. На следующих лекциях мы будем углубляться в практическое использование Google Sheets и Drive API. Готовьтесь к ещё большему количеству кода и возможностей!
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ