from pathlib import Path from httpx import ASGITransport, AsyncClient from porchlight.app import create_app from porchlight.config import Settings async def test_configured_clients_are_registered(tmp_path: Path) -> None: """Clients defined in config should be registered in the OIDC server.""" toml_content = """\ issuer = "https://test.example.com" [clients.test-rp] client_secret = "test-secret-0123456789abcdef" redirect_uris = ["https://app.example.com/callback"] scope = ["openid", "profile"] """ toml_file = tmp_path / "test.toml" toml_file.write_text(toml_content) settings = Settings(_toml_file=str(toml_file)) # type: ignore[call-arg] app = create_app(settings) async with AsyncClient(transport=ASGITransport(app=app), base_url="http://test") as client: # Trigger lifespan async with app.router.lifespan_context(app): response = await client.get("/health") assert response.status_code == 200 oidc_server = app.state.oidc_server assert "test-rp" in oidc_server.context.cdb cdb_entry = oidc_server.context.cdb["test-rp"] assert cdb_entry["client_id"] == "test-rp" assert cdb_entry["client_secret"] == "test-secret-0123456789abcdef" assert ("https://app.example.com/callback", {}) in cdb_entry["redirect_uris"] assert cdb_entry["scope"] == ["openid", "profile"] assert cdb_entry["allowed_scopes"] == ["openid", "profile"] async def test_manage_app_always_registered() -> None: """The internal manage-app client is always registered, even without config file clients.""" settings = Settings(issuer="https://test.example.com") app = create_app(settings) async with AsyncClient(transport=ASGITransport(app=app), base_url="http://test") as client: async with app.router.lifespan_context(app): response = await client.get("/health") assert response.status_code == 200 oidc_server = app.state.oidc_server assert "manage-app" in oidc_server.context.cdb