diff --git a/homeassistant/auth/providers/insecure_example.py b/homeassistant/auth/providers/insecure_example.py index 9ad6da27ce3..dc003c3e6f3 100644 --- a/homeassistant/auth/providers/insecure_example.py +++ b/homeassistant/auth/providers/insecure_example.py @@ -102,7 +102,7 @@ class ExampleLoginFlow(LoginFlow): self, user_input: dict[str, str] | None = None ) -> FlowResult: """Handle the step of the form.""" - errors = {} + errors = None if user_input is not None: try: @@ -110,7 +110,7 @@ class ExampleLoginFlow(LoginFlow): user_input["username"], user_input["password"] ) except InvalidAuthError: - errors["base"] = "invalid_auth" + errors = {"base": "invalid_auth"} if not errors: user_input.pop("password") diff --git a/homeassistant/components/auth/login_flow.py b/homeassistant/components/auth/login_flow.py index ef2bb793662..a21854b7770 100644 --- a/homeassistant/components/auth/login_flow.py +++ b/homeassistant/components/auth/login_flow.py @@ -154,14 +154,18 @@ class LoginFlowBaseView(HomeAssistantView): async def _async_flow_result_to_response(self, request, client_id, result): """Convert the flow result to a response.""" if result["type"] != data_entry_flow.RESULT_TYPE_CREATE_ENTRY: - if result["type"] == data_entry_flow.RESULT_TYPE_FORM: - # @log_invalid_auth does not work here since it returns HTTP 200 - # need manually log failed login attempts - if result.get("errors", {}).get("base") in ( + # @log_invalid_auth does not work here since it returns HTTP 200. + # We need to manually log failed login attempts. + if ( + result["type"] == data_entry_flow.RESULT_TYPE_FORM + and (errors := result.get("errors")) + and errors.get("base") + in ( "invalid_auth", "invalid_code", - ): - await process_wrong_login(request) + ) + ): + await process_wrong_login(request) return self.json(_prepare_result_json(result)) result.pop("data") diff --git a/tests/components/auth/test_login_flow.py b/tests/components/auth/test_login_flow.py index fd0157c235e..1fa06045de6 100644 --- a/tests/components/auth/test_login_flow.py +++ b/tests/components/auth/test_login_flow.py @@ -54,33 +54,41 @@ async def test_invalid_username_password(hass, aiohttp_client): step = await resp.json() # Incorrect username - resp = await client.post( - f"/auth/login_flow/{step['flow_id']}", - json={ - "client_id": CLIENT_ID, - "username": "wrong-user", - "password": "test-pass", - }, - ) + with patch( + "homeassistant.components.auth.login_flow.process_wrong_login" + ) as mock_process_wrong_login: + resp = await client.post( + f"/auth/login_flow/{step['flow_id']}", + json={ + "client_id": CLIENT_ID, + "username": "wrong-user", + "password": "test-pass", + }, + ) assert resp.status == HTTPStatus.OK step = await resp.json() + assert len(mock_process_wrong_login.mock_calls) == 1 assert step["step_id"] == "init" assert step["errors"]["base"] == "invalid_auth" # Incorrect password - resp = await client.post( - f"/auth/login_flow/{step['flow_id']}", - json={ - "client_id": CLIENT_ID, - "username": "test-user", - "password": "wrong-pass", - }, - ) + with patch( + "homeassistant.components.auth.login_flow.process_wrong_login" + ) as mock_process_wrong_login: + resp = await client.post( + f"/auth/login_flow/{step['flow_id']}", + json={ + "client_id": CLIENT_ID, + "username": "test-user", + "password": "wrong-pass", + }, + ) assert resp.status == HTTPStatus.OK step = await resp.json() + assert len(mock_process_wrong_login.mock_calls) == 1 assert step["step_id"] == "init" assert step["errors"]["base"] == "invalid_auth" @@ -105,15 +113,23 @@ async def test_login_exist_user(hass, aiohttp_client): assert resp.status == HTTPStatus.OK step = await resp.json() - resp = await client.post( - f"/auth/login_flow/{step['flow_id']}", - json={"client_id": CLIENT_ID, "username": "test-user", "password": "test-pass"}, - ) + with patch( + "homeassistant.components.auth.login_flow.process_success_login" + ) as mock_process_success_login: + resp = await client.post( + f"/auth/login_flow/{step['flow_id']}", + json={ + "client_id": CLIENT_ID, + "username": "test-user", + "password": "test-pass", + }, + ) assert resp.status == HTTPStatus.OK step = await resp.json() assert step["type"] == "create_entry" assert len(step["result"]) > 1 + assert len(mock_process_success_login.mock_calls) == 1 async def test_login_local_only_user(hass, aiohttp_client):