"""Tests for MCP auth: bearer-token validation that reuses api_keys.""" from unittest.mock import AsyncMock, MagicMock, patch import pytest from fabledassistant.mcp.auth import resolve_bearer_to_user_id @pytest.mark.asyncio async def test_resolve_bearer_missing_header_returns_none(): assert await resolve_bearer_to_user_id(None) is None @pytest.mark.asyncio async def test_resolve_bearer_malformed_header_returns_none(): assert await resolve_bearer_to_user_id("Token abc") is None assert await resolve_bearer_to_user_id("Bearer") is None assert await resolve_bearer_to_user_id("Bearer ") is None assert await resolve_bearer_to_user_id("") is None @pytest.mark.asyncio async def test_resolve_bearer_unknown_token_returns_none(): with patch( "fabledassistant.mcp.auth.lookup_key", AsyncMock(return_value=None), ): assert await resolve_bearer_to_user_id("Bearer fmcp_doesnotexist") is None @pytest.mark.asyncio async def test_resolve_bearer_valid_token_returns_user_id(): fake_key = MagicMock() fake_key.user_id = 42 with patch( "fabledassistant.mcp.auth.lookup_key", AsyncMock(return_value=fake_key), ): uid = await resolve_bearer_to_user_id("Bearer fmcp_validkey") assert uid == 42 @pytest.mark.asyncio async def test_resolve_bearer_calls_lookup_with_stripped_token(): """The Bearer prefix and any trailing whitespace must be stripped before lookup.""" fake_key = MagicMock() fake_key.user_id = 1 mock_lookup = AsyncMock(return_value=fake_key) with patch("fabledassistant.mcp.auth.lookup_key", mock_lookup): await resolve_bearer_to_user_id("Bearer fmcp_abc123 ") mock_lookup.assert_awaited_once_with("fmcp_abc123")