diff --git a/src/crewai/cli/authentication/constants.py b/src/crewai/cli/authentication/constants.py index 22a212822..a9457b36a 100644 --- a/src/crewai/cli/authentication/constants.py +++ b/src/crewai/cli/authentication/constants.py @@ -1,6 +1 @@ ALGORITHMS = ["RS256"] - -#TODO: The AUTH0 constants should be removed after WorkOS migration is completed -AUTH0_DOMAIN = "crewai.us.auth0.com" -AUTH0_CLIENT_ID = "DEVC5Fw6NlRoSzmDCcOhVq85EfLBjKa8" -AUTH0_AUDIENCE = "https://crewai.us.auth0.com/api/v2/" diff --git a/src/crewai/cli/authentication/main.py b/src/crewai/cli/authentication/main.py index 42dd6677b..09bc1fa1d 100644 --- a/src/crewai/cli/authentication/main.py +++ b/src/crewai/cli/authentication/main.py @@ -9,14 +9,7 @@ from pydantic import BaseModel, Field from .utils import validate_jwt_token from crewai.cli.shared.token_manager import TokenManager -from urllib.parse import quote -from crewai.cli.plus_api import PlusAPI from crewai.cli.config import Settings -from crewai.cli.authentication.constants import ( - AUTH0_AUDIENCE, - AUTH0_CLIENT_ID, - AUTH0_DOMAIN, -) console = Console() @@ -72,18 +65,6 @@ class AuthenticationCommand: """Sign up to CrewAI+""" console.print("Signing in to CrewAI Enterprise...\n", style="bold blue") - # TODO: WORKOS - Next line and conditional are temporary until migration to WorkOS is complete. - user_provider = self._determine_user_provider() - if user_provider == "auth0": - settings = Oauth2Settings( - provider="auth0", - client_id=AUTH0_CLIENT_ID, - domain=AUTH0_DOMAIN, - audience=AUTH0_AUDIENCE, - ) - self.oauth2_provider = ProviderFactory.from_settings(settings) - # End of temporary code. - device_code_data = self._get_device_code() self._display_auth_instructions(device_code_data) @@ -206,30 +187,3 @@ class AuthenticationCommand: "\nRun [bold]crewai login[/bold] to try logging in again.\n", style="yellow", ) - - # TODO: WORKOS - This method is temporary until migration to WorkOS is complete. - def _determine_user_provider(self) -> str: - """Determine which provider to use for authentication.""" - - console.print( - "Enter your CrewAI Enterprise account email: ", style="bold blue", end="" - ) - email = input() - email_encoded = quote(email) - - # It's not correct to call this method directly, but it's temporary until migration is complete. - response = PlusAPI("")._make_request( - "GET", f"/crewai_plus/api/v1/me/provider?email={email_encoded}" - ) - - if response.status_code == 200: - if response.json().get("provider") == "auth0": - return "auth0" - else: - return "workos" - else: - console.print( - "Error: Failed to authenticate with crewai enterprise. Ensure that you are using the latest crewai version and please try again. If the problem persists, contact support@crewai.com.", - style="red", - ) - raise SystemExit diff --git a/tests/cli/authentication/test_auth_main.py b/tests/cli/authentication/test_auth_main.py index d608c9ba4..ca8a0cf2b 100644 --- a/tests/cli/authentication/test_auth_main.py +++ b/tests/cli/authentication/test_auth_main.py @@ -3,11 +3,6 @@ from datetime import datetime, timedelta import requests from unittest.mock import MagicMock, patch, call from crewai.cli.authentication.main import AuthenticationCommand -from crewai.cli.authentication.constants import ( - AUTH0_AUDIENCE, - AUTH0_CLIENT_ID, - AUTH0_DOMAIN -) from crewai.cli.constants import ( CREWAI_ENTERPRISE_DEFAULT_OAUTH2_DOMAIN, CREWAI_ENTERPRISE_DEFAULT_OAUTH2_CLIENT_ID, @@ -22,16 +17,6 @@ class TestAuthenticationCommand: @pytest.mark.parametrize( "user_provider,expected_urls", [ - ( - "auth0", - { - "device_code_url": f"https://{AUTH0_DOMAIN}/oauth/device/code", - "token_url": f"https://{AUTH0_DOMAIN}/oauth/token", - "client_id": AUTH0_CLIENT_ID, - "audience": AUTH0_AUDIENCE, - "domain": AUTH0_DOMAIN, - }, - ), ( "workos", { @@ -44,9 +29,6 @@ class TestAuthenticationCommand: ), ], ) - @patch( - "crewai.cli.authentication.main.AuthenticationCommand._determine_user_provider" - ) @patch("crewai.cli.authentication.main.AuthenticationCommand._get_device_code") @patch( "crewai.cli.authentication.main.AuthenticationCommand._display_auth_instructions" @@ -59,11 +41,9 @@ class TestAuthenticationCommand: mock_poll, mock_display, mock_get_device, - mock_determine_provider, user_provider, expected_urls, ): - mock_determine_provider.return_value = user_provider mock_get_device.return_value = { "device_code": "test_code", "user_code": "123456", @@ -74,7 +54,6 @@ class TestAuthenticationCommand: mock_console_print.assert_called_once_with( "Signing in to CrewAI Enterprise...\n", style="bold blue" ) - mock_determine_provider.assert_called_once() mock_get_device.assert_called_once() mock_display.assert_called_once_with( {"device_code": "test_code", "user_code": "123456"} @@ -82,9 +61,17 @@ class TestAuthenticationCommand: mock_poll.assert_called_once_with( {"device_code": "test_code", "user_code": "123456"}, ) - assert self.auth_command.oauth2_provider.get_client_id() == expected_urls["client_id"] - assert self.auth_command.oauth2_provider.get_audience() == expected_urls["audience"] - assert self.auth_command.oauth2_provider._get_domain() == expected_urls["domain"] + assert ( + self.auth_command.oauth2_provider.get_client_id() + == expected_urls["client_id"] + ) + assert ( + self.auth_command.oauth2_provider.get_audience() + == expected_urls["audience"] + ) + assert ( + self.auth_command.oauth2_provider._get_domain() == expected_urls["domain"] + ) @patch("crewai.cli.authentication.main.webbrowser") @patch("crewai.cli.authentication.main.console.print") @@ -106,14 +93,6 @@ class TestAuthenticationCommand: @pytest.mark.parametrize( "user_provider,jwt_config", [ - ( - "auth0", - { - "jwks_url": f"https://{AUTH0_DOMAIN}/.well-known/jwks.json", - "issuer": f"https://{AUTH0_DOMAIN}/", - "audience": AUTH0_AUDIENCE, - }, - ), ( "workos", { @@ -135,14 +114,18 @@ class TestAuthenticationCommand: jwt_config, has_expiration, ): - from crewai.cli.authentication.providers.auth0 import Auth0Provider from crewai.cli.authentication.providers.workos import WorkosProvider from crewai.cli.authentication.main import Oauth2Settings - if user_provider == "auth0": - self.auth_command.oauth2_provider = Auth0Provider(settings=Oauth2Settings(provider=user_provider, client_id="test-client-id", domain=AUTH0_DOMAIN, audience=jwt_config["audience"])) - elif user_provider == "workos": - self.auth_command.oauth2_provider = WorkosProvider(settings=Oauth2Settings(provider=user_provider, client_id="test-client-id", domain=CREWAI_ENTERPRISE_DEFAULT_OAUTH2_DOMAIN, audience=jwt_config["audience"])) + if user_provider == "workos": + self.auth_command.oauth2_provider = WorkosProvider( + settings=Oauth2Settings( + provider=user_provider, + client_id="test-client-id", + domain=CREWAI_ENTERPRISE_DEFAULT_OAUTH2_DOMAIN, + audience=jwt_config["audience"], + ) + ) token_data = {"access_token": "test_access_token", "id_token": "test_id_token"} @@ -234,83 +217,6 @@ class TestAuthenticationCommand: ] mock_console_print.assert_has_calls(expected_calls) - @pytest.mark.parametrize( - "api_response,expected_provider", - [ - ({"provider": "auth0"}, "auth0"), - ({"provider": "workos"}, "workos"), - ({"provider": "none"}, "workos"), # Default to workos for any other value - ( - {}, - "workos", - ), # Default to workos if no provider key is sent in the response - ], - ) - @patch("crewai.cli.authentication.main.PlusAPI") - @patch("crewai.cli.authentication.main.console.print") - @patch("builtins.input", return_value="test@example.com") - def test_determine_user_provider_success( - self, - mock_input, - mock_console_print, - mock_plus_api, - api_response, - expected_provider, - ): - mock_api_instance = MagicMock() - mock_response = MagicMock() - mock_response.status_code = 200 - mock_response.json.return_value = api_response - mock_api_instance._make_request.return_value = mock_response - mock_plus_api.return_value = mock_api_instance - - result = self.auth_command._determine_user_provider() - - mock_input.assert_called_once() - - mock_plus_api.assert_called_once_with("") - mock_api_instance._make_request.assert_called_once_with( - "GET", "/crewai_plus/api/v1/me/provider?email=test%40example.com" - ) - - assert result == expected_provider - - @patch("crewai.cli.authentication.main.PlusAPI") - @patch("crewai.cli.authentication.main.console.print") - @patch("builtins.input", return_value="test@example.com") - def test_determine_user_provider_error( - self, mock_input, mock_console_print, mock_plus_api - ): - mock_api_instance = MagicMock() - mock_response = MagicMock() - mock_response.status_code = 500 - mock_api_instance._make_request.return_value = mock_response - mock_plus_api.return_value = mock_api_instance - - with pytest.raises(SystemExit): - self.auth_command._determine_user_provider() - - mock_input.assert_called_once() - - mock_plus_api.assert_called_once_with("") - mock_api_instance._make_request.assert_called_once_with( - "GET", "/crewai_plus/api/v1/me/provider?email=test%40example.com" - ) - - mock_console_print.assert_has_calls( - [ - call( - "Enter your CrewAI Enterprise account email: ", - style="bold blue", - end="", - ), - call( - "Error: Failed to authenticate with crewai enterprise. Ensure that you are using the latest crewai version and please try again. If the problem persists, contact support@crewai.com.", - style="red", - ), - ] - ) - @patch("requests.post") def test_get_device_code(self, mock_post): mock_response = MagicMock() @@ -323,7 +229,9 @@ class TestAuthenticationCommand: self.auth_command.oauth2_provider = MagicMock() self.auth_command.oauth2_provider.get_client_id.return_value = "test_client" - self.auth_command.oauth2_provider.get_authorize_url.return_value = "https://example.com/device" + self.auth_command.oauth2_provider.get_authorize_url.return_value = ( + "https://example.com/device" + ) self.auth_command.oauth2_provider.get_audience.return_value = "test_audience" result = self.auth_command._get_device_code() @@ -366,12 +274,12 @@ class TestAuthenticationCommand: ) as mock_tool_login, ): self.auth_command.oauth2_provider = MagicMock() - self.auth_command.oauth2_provider.get_token_url.return_value = "https://example.com/token" + self.auth_command.oauth2_provider.get_token_url.return_value = ( + "https://example.com/token" + ) self.auth_command.oauth2_provider.get_client_id.return_value = "test_client" - self.auth_command._poll_for_token( - device_code_data - ) + self.auth_command._poll_for_token(device_code_data) mock_post.assert_called_once_with( "https://example.com/token", @@ -406,9 +314,7 @@ class TestAuthenticationCommand: "interval": 0.1, # Short interval for testing } - self.auth_command._poll_for_token( - device_code_data - ) + self.auth_command._poll_for_token(device_code_data) mock_console_print.assert_any_call( "Timeout: Failed to get the token. Please try again.", style="bold red" @@ -429,15 +335,4 @@ class TestAuthenticationCommand: device_code_data = {"device_code": "test_device_code", "interval": 1} with pytest.raises(requests.HTTPError): - self.auth_command._poll_for_token( - device_code_data - ) - # @patch( - # "crewai.cli.authentication.main.AuthenticationCommand._determine_user_provider" - # ) - # def test_login_with_auth0(self, mock_determine_provider): - # from crewai.cli.authentication.providers.auth0 import Auth0Provider - # from crewai.cli.authentication.main import Oauth2Settings - - # self.auth_command.oauth2_provider = Auth0Provider(settings=Oauth2Settings(provider="auth0", client_id=AUTH0_CLIENT_ID, domain=AUTH0_DOMAIN, audience=AUTH0_AUDIENCE)) - # self.auth_command.login() + self.auth_command._poll_for_token(device_code_data)