Files
hold-slayer/tests/test_oauth_metadata.py
Robert Helewka 4a3c14d4af
All checks were successful
CVE Scan & Docker Build / security-scan (push) Successful in 45s
CVE Scan & Docker Build / build-and-push (push) Successful in 1m53s
docs: add Claude AI assistant rules and configuration
Add comprehensive rule documentation for AI-assisted development covering
authentication surfaces, outbound-call safety invariants, and other project
conventions to guide Claude's understanding of critical system behaviors.
2026-07-28 19:01:38 -04:00

78 lines
3.0 KiB
Python

"""
OAuth discovery metadata tests (RFC 9728 / RFC 8414 / RFC 7591).
MCP clients that get a 401 from /mcp perform OAuth discovery. These
endpoints are unauthenticated and served straight from main.app.
"""
import httpx
import pytest
import main
from config import get_settings
@pytest.fixture
async def client():
transport = httpx.ASGITransport(app=main.app)
async with httpx.AsyncClient(transport=transport, base_url="http://test") as c:
yield c
class TestProtectedResourceMetadata:
async def test_resource_advertises_mcp_path(self, client):
resp = await client.get("/.well-known/oauth-protected-resource")
assert resp.status_code == 200
body = resp.json()
# mcp-remote verifies this matches the URL it connected to.
assert body["resource"] == "http://test/mcp"
assert body["authorization_servers"] == ["http://test"]
async def test_mcp_suffixed_variant(self, client):
resp = await client.get("/.well-known/oauth-protected-resource/mcp")
assert resp.status_code == 200
assert resp.json()["resource"] == "http://test/mcp"
class TestAuthorizationServerMetadata:
async def test_advertises_casdoor_when_enabled(self, monkeypatch, client):
monkeypatch.setattr(get_settings().casdoor, "enabled", True)
monkeypatch.setattr(get_settings().casdoor, "endpoint", "https://id.example.test")
resp = await client.get("/.well-known/oauth-authorization-server")
assert resp.status_code == 200
body = resp.json()
assert body["issuer"] == "https://id.example.test"
assert body["jwks_uri"] == "https://id.example.test/.well-known/jwks"
assert body["registration_endpoint"] == "http://test/register"
async def test_dev_mode_advertises_local(self, monkeypatch, client):
monkeypatch.setattr(get_settings().casdoor, "enabled", False)
resp = await client.get("/.well-known/oauth-authorization-server")
assert resp.status_code == 200
body = resp.json()
assert body["issuer"] == "http://test"
assert body["authorization_endpoint"] == "http://test/auth/login"
class TestDynamicRegistration:
async def test_registers_client(self, client):
resp = await client.post(
"/register",
json={"redirect_uris": ["http://localhost/cb"], "client_name": "test"},
)
assert resp.status_code == 201
body = resp.json()
assert "client_id" in body
assert body["redirect_uris"] == ["http://localhost/cb"]
async def test_rejects_missing_redirect_uris(self, client):
resp = await client.post("/register", json={"client_name": "test"})
assert resp.status_code == 400
assert resp.json()["error"] == "invalid_redirect_uri"
async def test_rejects_non_json(self, client):
resp = await client.post(
"/register", content=b"not json", headers={"content-type": "application/json"}
)
assert resp.status_code == 400