feat(test): add Phase 5b integration and E2E tests
Add comprehensive integration and end-to-end test suites: - Integration tests for API flows (authorization, token, verification) - Integration tests for middleware chain and security headers - Integration tests for domain verification services - E2E tests for complete authentication flows - E2E tests for error scenarios and edge cases - Shared test fixtures and utilities in conftest.py - Rename Dockerfile to Containerfile for Podman compatibility 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
137
tests/integration/api/test_metadata.py
Normal file
137
tests/integration/api/test_metadata.py
Normal file
@@ -0,0 +1,137 @@
|
||||
"""
|
||||
Integration tests for OAuth 2.0 metadata endpoint.
|
||||
|
||||
Tests the /.well-known/oauth-authorization-server endpoint per RFC 8414.
|
||||
"""
|
||||
|
||||
import json
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def metadata_app(monkeypatch, tmp_path):
|
||||
"""Create app for metadata testing."""
|
||||
db_path = tmp_path / "test.db"
|
||||
|
||||
monkeypatch.setenv("GONDULF_SECRET_KEY", "a" * 32)
|
||||
monkeypatch.setenv("GONDULF_BASE_URL", "https://auth.example.com")
|
||||
monkeypatch.setenv("GONDULF_DATABASE_URL", f"sqlite:///{db_path}")
|
||||
monkeypatch.setenv("GONDULF_DEBUG", "true")
|
||||
|
||||
from gondulf.main import app
|
||||
return app
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def metadata_client(metadata_app):
|
||||
"""Create test client for metadata tests."""
|
||||
with TestClient(metadata_app) as client:
|
||||
yield client
|
||||
|
||||
|
||||
class TestMetadataEndpoint:
|
||||
"""Tests for OAuth 2.0 Authorization Server Metadata endpoint."""
|
||||
|
||||
def test_metadata_returns_json(self, metadata_client):
|
||||
"""Test metadata endpoint returns JSON response."""
|
||||
response = metadata_client.get("/.well-known/oauth-authorization-server")
|
||||
|
||||
assert response.status_code == 200
|
||||
assert "application/json" in response.headers["content-type"]
|
||||
|
||||
def test_metadata_includes_issuer(self, metadata_client):
|
||||
"""Test metadata includes issuer field."""
|
||||
response = metadata_client.get("/.well-known/oauth-authorization-server")
|
||||
|
||||
data = response.json()
|
||||
assert "issuer" in data
|
||||
assert data["issuer"] == "https://auth.example.com"
|
||||
|
||||
def test_metadata_includes_authorization_endpoint(self, metadata_client):
|
||||
"""Test metadata includes authorization endpoint."""
|
||||
response = metadata_client.get("/.well-known/oauth-authorization-server")
|
||||
|
||||
data = response.json()
|
||||
assert "authorization_endpoint" in data
|
||||
assert data["authorization_endpoint"] == "https://auth.example.com/authorize"
|
||||
|
||||
def test_metadata_includes_token_endpoint(self, metadata_client):
|
||||
"""Test metadata includes token endpoint."""
|
||||
response = metadata_client.get("/.well-known/oauth-authorization-server")
|
||||
|
||||
data = response.json()
|
||||
assert "token_endpoint" in data
|
||||
assert data["token_endpoint"] == "https://auth.example.com/token"
|
||||
|
||||
def test_metadata_includes_response_types(self, metadata_client):
|
||||
"""Test metadata includes supported response types."""
|
||||
response = metadata_client.get("/.well-known/oauth-authorization-server")
|
||||
|
||||
data = response.json()
|
||||
assert "response_types_supported" in data
|
||||
assert "code" in data["response_types_supported"]
|
||||
|
||||
def test_metadata_includes_grant_types(self, metadata_client):
|
||||
"""Test metadata includes supported grant types."""
|
||||
response = metadata_client.get("/.well-known/oauth-authorization-server")
|
||||
|
||||
data = response.json()
|
||||
assert "grant_types_supported" in data
|
||||
assert "authorization_code" in data["grant_types_supported"]
|
||||
|
||||
def test_metadata_includes_token_auth_methods(self, metadata_client):
|
||||
"""Test metadata includes token endpoint auth methods."""
|
||||
response = metadata_client.get("/.well-known/oauth-authorization-server")
|
||||
|
||||
data = response.json()
|
||||
assert "token_endpoint_auth_methods_supported" in data
|
||||
assert "none" in data["token_endpoint_auth_methods_supported"]
|
||||
|
||||
|
||||
class TestMetadataCaching:
|
||||
"""Tests for metadata endpoint caching behavior."""
|
||||
|
||||
def test_metadata_includes_cache_header(self, metadata_client):
|
||||
"""Test metadata endpoint includes Cache-Control header."""
|
||||
response = metadata_client.get("/.well-known/oauth-authorization-server")
|
||||
|
||||
assert "Cache-Control" in response.headers
|
||||
# Should allow caching
|
||||
assert "public" in response.headers["Cache-Control"]
|
||||
assert "max-age" in response.headers["Cache-Control"]
|
||||
|
||||
def test_metadata_is_cacheable(self, metadata_client):
|
||||
"""Test metadata endpoint allows public caching."""
|
||||
response = metadata_client.get("/.well-known/oauth-authorization-server")
|
||||
|
||||
cache_control = response.headers["Cache-Control"]
|
||||
# Should be cacheable for a reasonable time
|
||||
assert "public" in cache_control
|
||||
|
||||
|
||||
class TestMetadataSecurity:
|
||||
"""Security tests for metadata endpoint."""
|
||||
|
||||
def test_metadata_includes_security_headers(self, metadata_client):
|
||||
"""Test metadata endpoint includes security headers."""
|
||||
response = metadata_client.get("/.well-known/oauth-authorization-server")
|
||||
|
||||
assert "X-Frame-Options" in response.headers
|
||||
assert "X-Content-Type-Options" in response.headers
|
||||
|
||||
def test_metadata_requires_no_authentication(self, metadata_client):
|
||||
"""Test metadata endpoint is publicly accessible."""
|
||||
response = metadata_client.get("/.well-known/oauth-authorization-server")
|
||||
|
||||
# Should work without any authentication
|
||||
assert response.status_code == 200
|
||||
|
||||
def test_metadata_returns_valid_json(self, metadata_client):
|
||||
"""Test metadata returns valid parseable JSON."""
|
||||
response = metadata_client.get("/.well-known/oauth-authorization-server")
|
||||
|
||||
# Should not raise
|
||||
data = json.loads(response.content)
|
||||
assert isinstance(data, dict)
|
||||
Reference in New Issue
Block a user