| """ |
| Unit tests for Supabase key validation functionality. |
| Tests the JWT-based validation of anon vs service keys. |
| """ |
|
|
| from unittest.mock import patch |
|
|
| import pytest |
| from jose import jwt |
|
|
| from src.server.config.config import ( |
| ConfigurationError, |
| load_environment_config, |
| validate_supabase_key, |
| ) |
|
|
|
|
| def test_validate_anon_key(): |
| """Test validation detects anon key correctly.""" |
| |
| anon_payload = {"role": "anon", "iss": "supabase"} |
| anon_token = jwt.encode(anon_payload, "secret", algorithm="HS256") |
|
|
| is_valid, msg = validate_supabase_key(anon_token) |
|
|
| assert not is_valid |
| assert msg == "ANON_KEY_DETECTED" |
|
|
|
|
| def test_validate_service_key(): |
| """Test validation detects service key correctly.""" |
| |
| service_payload = {"role": "service_role", "iss": "supabase"} |
| service_token = jwt.encode(service_payload, "secret", algorithm="HS256") |
|
|
| is_valid, msg = validate_supabase_key(service_token) |
|
|
| assert is_valid |
| assert msg == "VALID_SERVICE_KEY" |
|
|
|
|
| def test_validate_unknown_key(): |
| """Test validation handles unknown key roles.""" |
| |
| unknown_payload = {"role": "custom", "iss": "supabase"} |
| unknown_token = jwt.encode(unknown_payload, "secret", algorithm="HS256") |
|
|
| is_valid, msg = validate_supabase_key(unknown_token) |
|
|
| assert not is_valid |
| assert "UNKNOWN_KEY_TYPE" in msg |
| assert "custom" in msg |
|
|
|
|
| def test_validate_invalid_jwt(): |
| """Test validation handles invalid JWT format gracefully.""" |
| is_valid, msg = validate_supabase_key("not-a-jwt") |
|
|
| |
| assert is_valid |
| assert msg == "UNABLE_TO_VALIDATE" |
|
|
|
|
| def test_validate_empty_key(): |
| """Test validation handles empty key.""" |
| is_valid, msg = validate_supabase_key("") |
|
|
| assert not is_valid |
| assert msg == "EMPTY_KEY" |
|
|
|
|
| def test_config_raises_on_anon_key(): |
| """Test that configuration loading raises error when anon key detected.""" |
| |
| anon_payload = {"role": "anon", "iss": "supabase"} |
| mock_anon_key = jwt.encode(anon_payload, "secret", algorithm="HS256") |
|
|
| with patch.dict( |
| "os.environ", |
| { |
| "SUPABASE_URL": "https://test.supabase.co", |
| "SUPABASE_SERVICE_KEY": mock_anon_key, |
| "OPENAI_API_KEY": "", |
| }, |
| ): |
| with pytest.raises(ConfigurationError) as exc_info: |
| load_environment_config() |
|
|
| error_message = str(exc_info.value) |
| assert "CRITICAL: You are using a Supabase ANON key" in error_message |
| assert "service_role" in error_message |
| assert "permission denied" in error_message |
|
|
|
|
| def test_config_accepts_service_key(): |
| """Test that configuration loading accepts service key.""" |
| |
| service_payload = {"role": "service_role", "iss": "supabase"} |
| mock_service_key = jwt.encode(service_payload, "secret", algorithm="HS256") |
|
|
| with patch.dict( |
| "os.environ", |
| { |
| "SUPABASE_URL": "https://test.supabase.co", |
| "SUPABASE_SERVICE_KEY": mock_service_key, |
| "PORT": "8051", |
| "OPENAI_API_KEY": "", |
| }, |
| ): |
| |
| config = load_environment_config() |
| assert config.supabase_service_key == mock_service_key |
|
|
|
|
| def test_config_handles_invalid_jwt(): |
| """Test that configuration loading handles invalid JWT gracefully.""" |
| with patch.dict( |
| "os.environ", |
| { |
| "SUPABASE_URL": "https://test.supabase.co", |
| "SUPABASE_SERVICE_KEY": "invalid-jwt-key", |
| "PORT": "8051", |
| "OPENAI_API_KEY": "", |
| }, |
| ): |
| |
| config = load_environment_config() |
| assert config.supabase_service_key == "invalid-jwt-key" |
|
|
|
|
| def test_config_fails_on_unknown_role(): |
| """Test that configuration loading fails fast for unknown roles.""" |
| |
| unknown_payload = {"role": "custom_role", "iss": "supabase"} |
| mock_unknown_key = jwt.encode(unknown_payload, "secret", algorithm="HS256") |
|
|
| with patch.dict( |
| "os.environ", |
| { |
| "SUPABASE_URL": "https://test.supabase.co", |
| "SUPABASE_SERVICE_KEY": mock_unknown_key, |
| "PORT": "8051", |
| "OPENAI_API_KEY": "", |
| }, |
| ): |
| |
| with pytest.raises(ConfigurationError) as exc_info: |
| load_environment_config() |
|
|
| error_message = str(exc_info.value) |
| assert "Unknown Supabase key role 'custom_role'" in error_message |
| assert "Expected 'service_role'" in error_message |
|
|
|
|
| def test_config_raises_on_anon_key_with_port(): |
| """Test that anon key detection works properly with all required env vars.""" |
| |
| anon_payload = {"role": "anon", "iss": "supabase"} |
| mock_anon_key = jwt.encode(anon_payload, "secret", algorithm="HS256") |
|
|
| with patch.dict( |
| "os.environ", |
| { |
| "SUPABASE_URL": "https://test.supabase.co", |
| "SUPABASE_SERVICE_KEY": mock_anon_key, |
| "PORT": "8051", |
| "OPENAI_API_KEY": "sk-test123", |
| }, |
| ): |
| |
| with pytest.raises(ConfigurationError) as exc_info: |
| load_environment_config() |
|
|
| error_message = str(exc_info.value) |
| assert "CRITICAL: You are using a Supabase ANON key" in error_message |
|
|
|
|
| def test_jwt_decoding_with_real_structure(): |
| """Test JWT decoding with realistic Supabase JWT structure.""" |
| |
| realistic_anon_payload = { |
| "aud": "authenticated", |
| "exp": 1999999999, |
| "iat": 1234567890, |
| "iss": "supabase", |
| "ref": "abcdefghij", |
| "role": "anon", |
| } |
|
|
| realistic_service_payload = { |
| "aud": "authenticated", |
| "exp": 1999999999, |
| "iat": 1234567890, |
| "iss": "supabase", |
| "ref": "abcdefghij", |
| "role": "service_role", |
| } |
|
|
| anon_token = jwt.encode(realistic_anon_payload, "secret", algorithm="HS256") |
| service_token = jwt.encode(realistic_service_payload, "secret", algorithm="HS256") |
|
|
| |
| is_valid_anon, msg_anon = validate_supabase_key(anon_token) |
| assert not is_valid_anon |
| assert msg_anon == "ANON_KEY_DETECTED" |
|
|
| |
| is_valid_service, msg_service = validate_supabase_key(service_token) |
| assert is_valid_service |
| assert msg_service == "VALID_SERVICE_KEY" |
|
|