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>
138 lines
5.2 KiB
Python
138 lines
5.2 KiB
Python
"""
|
|
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)
|