import pytest from unittest.mock import MagicMock, patch from ea_chatbot.auth import OIDCClient @pytest.fixture def oidc_config(): return { "client_id": "test_id", "client_secret": "test_secret", "server_metadata_url": "https://example.com/.well-known/openid-configuration", "redirect_uri": "http://localhost:5173/auth/callback" } @pytest.fixture def mock_metadata(): return { "authorization_endpoint": "https://example.com/auth", "token_endpoint": "https://example.com/token", "userinfo_endpoint": "https://example.com/userinfo", "jwks_uri": "https://example.com/jwks" } def test_oidc_generate_pkce(oidc_config): client = OIDCClient(**oidc_config) code_verifier, code_challenge = client.generate_pkce() assert len(code_verifier) >= 43 assert len(code_challenge) > 0 # Verifier should be high entropy assert code_verifier != client.generate_pkce()[0] def test_oidc_get_auth_data(oidc_config, mock_metadata): client = OIDCClient(**oidc_config) client.metadata = mock_metadata auth_data = client.get_auth_data() assert "url" in auth_data assert "state" in auth_data assert "nonce" in auth_data assert "code_verifier" in auth_data url = auth_data["url"] assert "code_challenge=" in url assert "code_challenge_method=S256" in url assert f"state={auth_data['state']}" in url assert f"nonce={auth_data['nonce']}" in url def test_oidc_exchange_code_with_pkce(oidc_config, mock_metadata): client = OIDCClient(**oidc_config) client.metadata = mock_metadata with patch.object(client.oauth_session, "fetch_token") as mock_fetch: mock_fetch.return_value = {"access_token": "token"} token = client.exchange_code_for_token("code", code_verifier="verifier") assert token == {"access_token": "token"} mock_fetch.assert_called_once_with( mock_metadata["token_endpoint"], code="code", client_secret=oidc_config["client_secret"], code_verifier="verifier" )