Some checks failed
Deploy on push / deploy (push) Failing after 39s
### 🚨 CRITICAL Security Fixes - **🔒 Open Redirect Protection**: Добавлена строгая валидация redirect_uri против whitelist доменов - **🔒 Rate Limiting**: Защита OAuth endpoints от брутфорса (10 попыток за 5 минут на IP) - **🔒 Logout Endpoint**: Критически важный endpoint для безопасного отзыва httpOnly cookies - **🔒 Provider Validation**: Усиленная валидация OAuth провайдеров с логированием атак - **🚨 GlitchTip Alerts**: Автоматические алерты безопасности в GlitchTip при критических событиях ### 🛡️ Security Modules - **auth/oauth_security.py**: Модуль безопасности OAuth с валидацией и rate limiting + GlitchTip алерты - **auth/logout.py**: Безопасный logout с поддержкой JSON API и browser redirect - **tests/test_oauth_security.py**: Комплексные тесты безопасности (11 тестов) - **tests/test_oauth_glitchtip_alerts.py**: Тесты интеграции с GlitchTip (8 тестов) ### 🔧 OAuth Improvements - **Minimal Flow**: Упрощен до минимума - только httpOnly cookie, нет JWT в URL - **Simple Logic**: Нет error параметра = успех, максимальная простота - **DRY Refactoring**: Устранено дублирование кода в logout и валидации ### 🎯 OAuth Endpoints - **Старт**: `v3.dscrs.site/oauth/{provider}` - с rate limiting и валидацией - **Callback**: `v3.dscrs.site/oauth/{provider}/callback` - безопасный redirect_uri - **Logout**: `v3.dscrs.site/auth/logout` - отзыв httpOnly cookies - **Финализация**: `testing.discours.io/oauth?redirect_url=...` - минимальная схема ### 📊 Security Test Coverage - ✅ Open redirect attack prevention - ✅ Rate limiting protection - ✅ Provider validation - ✅ Safe fallback mechanisms - ✅ Cookie security (httpOnly + Secure + SameSite) - ✅ GlitchTip integration (8 тестов алертов) ### 📝 Documentation - Создан `docs/oauth-minimal-flow.md` - полное описание минимального flow - Обновлена документация OAuth в `docs/auth/oauth.md` - Добавлены security best practices
175 lines
5.9 KiB
Markdown
175 lines
5.9 KiB
Markdown
# OAuth Test Scenarios для testing.discours.io
|
||
|
||
## 🧪 Тестовые сценарии для проверки OAuth flow
|
||
|
||
### 1. ✅ Успешная авторизация GitHub
|
||
```bash
|
||
# Шаг 1: Инициация OAuth
|
||
curl -v "https://v3.dscrs.site/oauth/github" \
|
||
-H "Referer: https://testing.discours.io/some-page" \
|
||
-H "User-Agent: Mozilla/5.0"
|
||
|
||
# Ожидаемый результат:
|
||
# - Редирект 302 на GitHub с правильными параметрами
|
||
# - state сохранен в Redis с TTL 10 минут
|
||
# - redirect_uri взят из Referer header
|
||
|
||
# Шаг 2: Callback от GitHub (симуляция)
|
||
curl -v "https://v3.dscrs.site/oauth/github/callback?code=test_code&state=valid_state" \
|
||
-H "User-Agent: Mozilla/5.0"
|
||
|
||
# Ожидаемый результат:
|
||
# - Обмен code на access_token
|
||
# - Получение профиля пользователя
|
||
# - Создание JWT токена
|
||
# - Установка httpOnly cookie с domain=".discours.io"
|
||
# - Редирект на https://testing.discours.io/oauth?success=true
|
||
```
|
||
|
||
### 2. 🚨 Обработка ошибок провайдера
|
||
```bash
|
||
# GitHub отклонил доступ
|
||
curl -v "https://v3.dscrs.site/oauth/github/callback?error=access_denied&state=valid_state"
|
||
|
||
# Ожидаемый результат:
|
||
# - Редирект на https://testing.discours.io/oauth?error=access_denied
|
||
```
|
||
|
||
### 3. 🛡️ CSRF защита (state validation)
|
||
```bash
|
||
# Неправильный state
|
||
curl -v "https://v3.dscrs.site/oauth/github/callback?code=test_code&state=invalid_state"
|
||
|
||
# Ожидаемый результат:
|
||
# - Редирект на https://testing.discours.io/oauth?error=oauth_state_expired
|
||
```
|
||
|
||
### 4. 🔍 Валидация провайдера
|
||
```bash
|
||
# Несуществующий провайдер
|
||
curl -v "https://v3.dscrs.site/oauth/invalid_provider"
|
||
|
||
# Ожидаемый результат:
|
||
# - JSON ответ с ошибкой {"error": "Invalid provider"}
|
||
```
|
||
|
||
### 5. 🍪 Проверка cookie установки
|
||
```bash
|
||
# Проверка что cookie устанавливается правильно
|
||
curl -v "https://v3.dscrs.site/oauth/github/callback?code=valid_code&state=valid_state" \
|
||
-c cookies.txt
|
||
|
||
# Проверить в cookies.txt:
|
||
# - session_token cookie
|
||
# - HttpOnly=true
|
||
# - Secure=true
|
||
# - SameSite=Lax
|
||
# - Domain=.discours.io
|
||
```
|
||
|
||
### 6. 🌐 CORS проверка
|
||
```bash
|
||
# Preflight запрос
|
||
curl -v "https://v3.dscrs.site/oauth/github" \
|
||
-X OPTIONS \
|
||
-H "Origin: https://testing.discours.io" \
|
||
-H "Access-Control-Request-Method: GET"
|
||
|
||
# Ожидаемый результат:
|
||
# - Access-Control-Allow-Origin: https://testing.discours.io
|
||
# - Access-Control-Allow-Credentials: true
|
||
```
|
||
|
||
### 7. 🔄 Полный E2E тест
|
||
```bash
|
||
#!/bin/bash
|
||
# Полный тест OAuth flow
|
||
|
||
echo "🔄 Тестируем полный OAuth flow..."
|
||
|
||
# 1. Инициация
|
||
INIT_RESPONSE=$(curl -s -D headers1.txt "https://v3.dscrs.site/oauth/github" \
|
||
-H "Referer: https://testing.discours.io/test-page")
|
||
|
||
# Извлекаем Location header для получения state
|
||
GITHUB_URL=$(grep -i "location:" headers1.txt | cut -d' ' -f2 | tr -d '\r')
|
||
STATE=$(echo "$GITHUB_URL" | grep -o 'state=[^&]*' | cut -d'=' -f2)
|
||
|
||
echo "✅ State получен: $STATE"
|
||
|
||
# 2. Симуляция callback
|
||
CALLBACK_RESPONSE=$(curl -s -D headers2.txt \
|
||
"https://v3.dscrs.site/oauth/github/callback?code=test_code&state=$STATE")
|
||
|
||
# Проверяем редирект
|
||
REDIRECT_URL=$(grep -i "location:" headers2.txt | cut -d' ' -f2 | tr -d '\r')
|
||
echo "✅ Redirect URL: $REDIRECT_URL"
|
||
|
||
# Проверяем cookie
|
||
COOKIE=$(grep -i "set-cookie:" headers2.txt | grep "session_token")
|
||
echo "✅ Cookie установлен: $COOKIE"
|
||
|
||
if [[ "$REDIRECT_URL" == *"testing.discours.io/oauth?success=true"* ]]; then
|
||
echo "🎉 OAuth flow работает корректно!"
|
||
else
|
||
echo "❌ OAuth flow не работает"
|
||
exit 1
|
||
fi
|
||
```
|
||
|
||
## 🔧 Настройки провайдеров для тестирования
|
||
|
||
### GitHub OAuth App
|
||
```
|
||
Application name: Discours Testing
|
||
Homepage URL: https://testing.discours.io
|
||
Authorization callback URL: https://v3.dscrs.site/oauth/github/callback
|
||
```
|
||
|
||
### Google OAuth Client
|
||
```
|
||
Authorized JavaScript origins: https://testing.discours.io
|
||
Authorized redirect URIs: https://v3.dscrs.site/oauth/google/callback
|
||
```
|
||
|
||
### Environment Variables
|
||
```bash
|
||
# Для тестирования нужны эти переменные:
|
||
GITHUB_CLIENT_ID=your_github_client_id
|
||
GITHUB_CLIENT_SECRET=your_github_client_secret
|
||
GOOGLE_CLIENT_ID=your_google_client_id
|
||
GOOGLE_CLIENT_SECRET=your_google_client_secret
|
||
|
||
# Redis для state storage
|
||
REDIS_URL=redis://localhost:6379
|
||
|
||
# Frontend URL
|
||
FRONTEND_URL=https://testing.discours.io
|
||
```
|
||
|
||
## 🐛 Возможные проблемы и решения
|
||
|
||
### 1. Cookie не устанавливается
|
||
**Проблема**: Domain mismatch между v3.dscrs.site и testing.discours.io
|
||
**Решение**: Используется domain=".discours.io" для поддержки поддоменов
|
||
|
||
### 2. CORS ошибки
|
||
**Проблема**: Браузер блокирует запросы между доменами
|
||
**Решение**: allow_credentials=True в CORS настройках
|
||
|
||
### 3. State expired
|
||
**Проблема**: Redis state истекает через 10 минут
|
||
**Решение**: Увеличить TTL или оптимизировать flow
|
||
|
||
### 4. Provider not configured
|
||
**Проблема**: Отсутствуют CLIENT_ID/CLIENT_SECRET
|
||
**Решение**: Проверить environment variables
|
||
|
||
## 📊 Метрики успешности
|
||
|
||
- ✅ Успешная авторизация: > 95%
|
||
- ✅ CSRF защита: 100% блокировка invalid state
|
||
- ✅ Cookie безопасность: HttpOnly + Secure + SameSite
|
||
- ✅ Error handling: Все ошибки редиректят на фронт
|
||
- ✅ Performance: < 2 секунд на полный flow
|