Files
core/docs/oauth-test-scenarios.md
Untone 05c188df62
Some checks failed
Deploy on push / deploy (push) Failing after 39s
[0.9.29] - 2025-09-26
### 🚨 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
2025-09-26 21:03:45 +03:00

5.9 KiB
Raw Blame History

OAuth Test Scenarios для testing.discours.io

🧪 Тестовые сценарии для проверки OAuth flow

1. Успешная авторизация GitHub

# Шаг 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. 🚨 Обработка ошибок провайдера

# 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)

# Неправильный 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. 🔍 Валидация провайдера

# Несуществующий провайдер
curl -v "https://v3.dscrs.site/oauth/invalid_provider"

# Ожидаемый результат:
# - JSON ответ с ошибкой {"error": "Invalid provider"}
# Проверка что 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 проверка

# 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 тест

#!/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

# Для тестирования нужны эти переменные:
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

🐛 Возможные проблемы и решения

Проблема: 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