diff --git a/homeassistant/auth/__init__.py b/homeassistant/auth/__init__.py index ee0d6c08441..64391debc10 100644 --- a/homeassistant/auth/__init__.py +++ b/homeassistant/auth/__init__.py @@ -86,18 +86,6 @@ class AuthManager: hass, self._async_create_login_flow, self._async_finish_login_flow ) - @property - def support_legacy(self) -> bool: - """ - Return if legacy_api_password auth providers are registered. - - Should be removed when we removed legacy_api_password auth providers. - """ - for provider_type, _ in self._providers: - if provider_type == "legacy_api_password": - return True - return False - @property def auth_providers(self) -> List[AuthProvider]: """Return a list of available auth providers.""" diff --git a/homeassistant/bootstrap.py b/homeassistant/bootstrap.py index ef294491141..422eab8ed4a 100644 --- a/homeassistant/bootstrap.py +++ b/homeassistant/bootstrap.py @@ -64,13 +64,9 @@ async def async_from_config_dict( ) core_config = config.get(core.DOMAIN, {}) - api_password = config.get("http", {}).get("api_password") - trusted_networks = config.get("http", {}).get("trusted_networks") try: - await conf_util.async_process_ha_core_config( - hass, core_config, api_password, trusted_networks - ) + await conf_util.async_process_ha_core_config(hass, core_config) except vol.Invalid as config_err: conf_util.async_log_exception(config_err, "homeassistant", core_config, hass) return None diff --git a/homeassistant/components/auth/login_flow.py b/homeassistant/components/auth/login_flow.py index 4fa0f866124..d6844396ce7 100644 --- a/homeassistant/components/auth/login_flow.py +++ b/homeassistant/components/auth/login_flow.py @@ -72,7 +72,11 @@ import voluptuous_serialize from homeassistant import data_entry_flow from homeassistant.components.http import KEY_REAL_IP -from homeassistant.components.http.ban import process_wrong_login, log_invalid_auth +from homeassistant.components.http.ban import ( + process_wrong_login, + process_success_login, + log_invalid_auth, +) from homeassistant.components.http.data_validator import RequestDataValidator from homeassistant.components.http.view import HomeAssistantView from . import indieauth @@ -185,6 +189,7 @@ class LoginFlowIndexView(HomeAssistantView): return self.json_message("Handler does not support init", 400) if result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY: + await process_success_login(request) result.pop("data") result["result"] = self._store_result(data["client_id"], result["result"]) return self.json(result) diff --git a/homeassistant/components/http/__init__.py b/homeassistant/components/http/__init__.py index 1b61e74769f..4df606a3c1b 100644 --- a/homeassistant/components/http/__init__.py +++ b/homeassistant/components/http/__init__.py @@ -17,7 +17,6 @@ from homeassistant.const import ( import homeassistant.helpers.config_validation as cv import homeassistant.util as hass_util from homeassistant.util import ssl as ssl_util -from homeassistant.util.logging import HideSensitiveDataFilter from .auth import setup_auth from .ban import setup_bans @@ -32,7 +31,6 @@ from .view import HomeAssistantView # noqa DOMAIN = "http" -CONF_API_PASSWORD = "api_password" CONF_SERVER_HOST = "server_host" CONF_SERVER_PORT = "server_port" CONF_BASE_URL = "base_url" @@ -42,7 +40,6 @@ CONF_SSL_KEY = "ssl_key" CONF_CORS_ORIGINS = "cors_allowed_origins" CONF_USE_X_FORWARDED_FOR = "use_x_forwarded_for" CONF_TRUSTED_PROXIES = "trusted_proxies" -CONF_TRUSTED_NETWORKS = "trusted_networks" CONF_LOGIN_ATTEMPTS_THRESHOLD = "login_attempts_threshold" CONF_IP_BAN_ENABLED = "ip_ban_enabled" CONF_SSL_PROFILE = "ssl_profile" @@ -59,37 +56,8 @@ DEFAULT_CORS = "https://cast.home-assistant.io" NO_LOGIN_ATTEMPT_THRESHOLD = -1 -def trusted_networks_deprecated(value): - """Warn user trusted_networks config is deprecated.""" - if not value: - return value - - _LOGGER.warning( - "Configuring trusted_networks via the http integration has been" - " deprecated. Use the trusted networks auth provider instead." - " For instructions, see https://www.home-assistant.io/docs/" - "authentication/providers/#trusted-networks" - ) - return value - - -def api_password_deprecated(value): - """Warn user api_password config is deprecated.""" - if not value: - return value - - _LOGGER.warning( - "Configuring api_password via the http integration has been" - " deprecated. Use the legacy api password auth provider instead." - " For instructions, see https://www.home-assistant.io/docs/" - "authentication/providers/#legacy-api-password" - ) - return value - - HTTP_SCHEMA = vol.Schema( { - vol.Optional(CONF_API_PASSWORD): vol.All(cv.string, api_password_deprecated), vol.Optional(CONF_SERVER_HOST, default=DEFAULT_SERVER_HOST): cv.string, vol.Optional(CONF_SERVER_PORT, default=SERVER_PORT): cv.port, vol.Optional(CONF_BASE_URL): cv.string, @@ -103,9 +71,6 @@ HTTP_SCHEMA = vol.Schema( vol.Inclusive(CONF_TRUSTED_PROXIES, "proxy"): vol.All( cv.ensure_list, [ip_network] ), - vol.Optional(CONF_TRUSTED_NETWORKS, default=[]): vol.All( - cv.ensure_list, [ip_network], trusted_networks_deprecated - ), vol.Optional( CONF_LOGIN_ATTEMPTS_THRESHOLD, default=NO_LOGIN_ATTEMPT_THRESHOLD ): vol.Any(cv.positive_int, NO_LOGIN_ATTEMPT_THRESHOLD), @@ -149,7 +114,6 @@ async def async_setup(hass, config): if conf is None: conf = HTTP_SCHEMA({}) - api_password = conf.get(CONF_API_PASSWORD) server_host = conf[CONF_SERVER_HOST] server_port = conf[CONF_SERVER_PORT] ssl_certificate = conf.get(CONF_SSL_CERTIFICATE) @@ -162,11 +126,6 @@ async def async_setup(hass, config): login_threshold = conf[CONF_LOGIN_ATTEMPTS_THRESHOLD] ssl_profile = conf[CONF_SSL_PROFILE] - if api_password is not None: - logging.getLogger("aiohttp.access").addFilter( - HideSensitiveDataFilter(api_password) - ) - server = HomeAssistantHTTP( hass, server_host=server_host, diff --git a/homeassistant/components/http/auth.py b/homeassistant/components/http/auth.py index 4ff581aef02..97bd9b7d4bc 100644 --- a/homeassistant/components/http/auth.py +++ b/homeassistant/components/http/auth.py @@ -1,14 +1,11 @@ """Authentication for HTTP component.""" -import base64 import logging from aiohttp import hdrs from aiohttp.web import middleware import jwt -from homeassistant.auth.providers import legacy_api_password from homeassistant.auth.util import generate_secret -from homeassistant.const import HTTP_HEADER_HA_AUTH from homeassistant.core import callback from homeassistant.util import dt as dt_util @@ -52,16 +49,6 @@ def async_sign_path(hass, refresh_token_id, path, expiration): @callback def setup_auth(hass, app): """Create auth middleware for the app.""" - old_auth_warning = set() - - support_legacy = hass.auth.support_legacy - if support_legacy: - _LOGGER.warning("legacy_api_password support has been enabled.") - - trusted_networks = [] - for prv in hass.auth.auth_providers: - if prv.type == "trusted_networks": - trusted_networks += prv.trusted_networks async def async_validate_auth_header(request): """ @@ -75,40 +62,16 @@ def setup_auth(hass, app): # If no space in authorization header return False - if auth_type == "Bearer": - refresh_token = await hass.auth.async_validate_access_token(auth_val) - if refresh_token is None: - return False + if auth_type != "Bearer": + return False - request[KEY_HASS_USER] = refresh_token.user - return True + refresh_token = await hass.auth.async_validate_access_token(auth_val) - if auth_type == "Basic" and support_legacy: - decoded = base64.b64decode(auth_val).decode("utf-8") - try: - username, password = decoded.split(":", 1) - except ValueError: - # If no ':' in decoded - return False + if refresh_token is None: + return False - if username != "homeassistant": - return False - - user = await legacy_api_password.async_validate_password(hass, password) - if user is None: - return False - - request[KEY_HASS_USER] = user - _LOGGER.info( - "Basic auth with api_password is going to deprecate," - " please use a bearer token to access %s from %s", - request.path, - request[KEY_REAL_IP], - ) - old_auth_warning.add(request.path) - return True - - return False + request[KEY_HASS_USER] = refresh_token.user + return True async def async_validate_signed_request(request): """Validate a signed request.""" @@ -140,50 +103,16 @@ def setup_auth(hass, app): request[KEY_HASS_USER] = refresh_token.user return True - async def async_validate_trusted_networks(request): - """Test if request is from a trusted ip.""" - ip_addr = request[KEY_REAL_IP] - - if not any(ip_addr in trusted_network for trusted_network in trusted_networks): - return False - - user = await hass.auth.async_get_owner() - if user is None: - return False - - request[KEY_HASS_USER] = user - return True - - async def async_validate_legacy_api_password(request, password): - """Validate api_password.""" - user = await legacy_api_password.async_validate_password(hass, password) - if user is None: - return False - - request[KEY_HASS_USER] = user - return True - @middleware async def auth_middleware(request, handler): """Authenticate as middleware.""" authenticated = False - if HTTP_HEADER_HA_AUTH in request.headers or DATA_API_PASSWORD in request.query: - if request.path not in old_auth_warning: - _LOGGER.log( - logging.INFO if support_legacy else logging.WARNING, - "api_password is going to deprecate. You need to use a" - " bearer token to access %s from %s", - request.path, - request[KEY_REAL_IP], - ) - old_auth_warning.add(request.path) - if hdrs.AUTHORIZATION in request.headers and await async_validate_auth_header( request ): - # it included both use_auth and api_password Basic auth authenticated = True + auth_type = "bearer token" # We first start with a string check to avoid parsing query params # for every request. @@ -193,39 +122,15 @@ def setup_auth(hass, app): and await async_validate_signed_request(request) ): authenticated = True + auth_type = "signed request" - elif trusted_networks and await async_validate_trusted_networks(request): - if request.path not in old_auth_warning: - # When removing this, don't forget to remove the print logic - # in http/view.py - request["deprecate_warning_message"] = ( - "Access from trusted networks without auth token is " - "going to be removed in Home Assistant 0.96. Configure " - "the trusted networks auth provider or use long-lived " - "access tokens to access {} from {}".format( - request.path, request[KEY_REAL_IP] - ) - ) - old_auth_warning.add(request.path) - authenticated = True - - elif ( - support_legacy - and HTTP_HEADER_HA_AUTH in request.headers - and await async_validate_legacy_api_password( - request, request.headers[HTTP_HEADER_HA_AUTH] + if authenticated: + _LOGGER.debug( + "Authenticated %s for %s using %s", + request[KEY_REAL_IP], + request.path, + auth_type, ) - ): - authenticated = True - - elif ( - support_legacy - and DATA_API_PASSWORD in request.query - and await async_validate_legacy_api_password( - request, request.query[DATA_API_PASSWORD] - ) - ): - authenticated = True request[KEY_AUTHENTICATED] = authenticated return await handler(request) diff --git a/homeassistant/components/http/cors.py b/homeassistant/components/http/cors.py index bd821335542..0e6b9f9439a 100644 --- a/homeassistant/components/http/cors.py +++ b/homeassistant/components/http/cors.py @@ -3,7 +3,7 @@ import aiohttp_cors from aiohttp.web_urldispatcher import Resource, ResourceRoute, StaticResource from aiohttp.hdrs import ACCEPT, CONTENT_TYPE, ORIGIN, AUTHORIZATION -from homeassistant.const import HTTP_HEADER_HA_AUTH, HTTP_HEADER_X_REQUESTED_WITH +from homeassistant.const import HTTP_HEADER_X_REQUESTED_WITH from homeassistant.core import callback @@ -14,7 +14,6 @@ ALLOWED_CORS_HEADERS = [ ACCEPT, HTTP_HEADER_X_REQUESTED_WITH, CONTENT_TYPE, - HTTP_HEADER_HA_AUTH, AUTHORIZATION, ] VALID_CORS_TYPES = (Resource, ResourceRoute, StaticResource) diff --git a/homeassistant/components/http/view.py b/homeassistant/components/http/view.py index 66864eba55e..804c90d4f96 100644 --- a/homeassistant/components/http/view.py +++ b/homeassistant/components/http/view.py @@ -17,7 +17,6 @@ from homeassistant.const import CONTENT_TYPE_JSON from homeassistant.core import Context, is_callback from homeassistant.helpers.json import JSONEncoder -from .ban import process_success_login from .const import KEY_AUTHENTICATED, KEY_HASS, KEY_REAL_IP _LOGGER = logging.getLogger(__name__) @@ -106,13 +105,8 @@ def request_handler_factory(view, handler): authenticated = request.get(KEY_AUTHENTICATED, False) - if view.requires_auth: - if authenticated: - if "deprecate_warning_message" in request: - _LOGGER.warning(request["deprecate_warning_message"]) - await process_success_login(request) - else: - raise HTTPUnauthorized() + if view.requires_auth and not authenticated: + raise HTTPUnauthorized() _LOGGER.debug( "Serving %s to %s (auth: %s)", diff --git a/homeassistant/components/websocket_api/auth.py b/homeassistant/components/websocket_api/auth.py index 716b20f4ca4..3971d39ee73 100644 --- a/homeassistant/components/websocket_api/auth.py +++ b/homeassistant/components/websocket_api/auth.py @@ -3,7 +3,6 @@ import voluptuous as vol from voluptuous.humanize import humanize_error from homeassistant.auth.models import RefreshToken, User -from homeassistant.auth.providers import legacy_api_password from homeassistant.components.http.ban import process_wrong_login, process_success_login from homeassistant.const import __version__ @@ -74,19 +73,6 @@ class AuthPhase: if refresh_token is not None: return await self._async_finish_auth(refresh_token.user, refresh_token) - elif self._hass.auth.support_legacy and "api_password" in msg: - self._logger.info( - "Received api_password, it is going to deprecate, please use" - " access_token instead. For instructions, see https://" - "developers.home-assistant.io/docs/en/external_api_websocket" - ".html#authentication-phase" - ) - user = await legacy_api_password.async_validate_password( - self._hass, msg["api_password"] - ) - if user is not None: - return await self._async_finish_auth(user, None) - self._send_message(auth_invalid_message("Invalid access token or password")) await process_wrong_login(self._request) raise Disconnect diff --git a/homeassistant/config.py b/homeassistant/config.py index 97c996d9e59..27137c08f1a 100644 --- a/homeassistant/config.py +++ b/homeassistant/config.py @@ -468,12 +468,7 @@ def _format_config_error(ex: Exception, domain: str, config: Dict) -> str: return message -async def async_process_ha_core_config( - hass: HomeAssistant, - config: Dict, - api_password: Optional[str] = None, - trusted_networks: Optional[Any] = None, -) -> None: +async def async_process_ha_core_config(hass: HomeAssistant, config: Dict) -> None: """Process the [homeassistant] section from the configuration. This method is a coroutine. @@ -486,14 +481,6 @@ async def async_process_ha_core_config( if auth_conf is None: auth_conf = [{"type": "homeassistant"}] - if api_password: - auth_conf.append( - {"type": "legacy_api_password", "api_password": api_password} - ) - if trusted_networks: - auth_conf.append( - {"type": "trusted_networks", "trusted_networks": trusted_networks} - ) mfa_conf = config.get( CONF_AUTH_MFA_MODULES, diff --git a/homeassistant/const.py b/homeassistant/const.py index e0f90834d94..592f6b60bc6 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -451,7 +451,6 @@ HTTP_SERVICE_UNAVAILABLE = 503 HTTP_BASIC_AUTHENTICATION = "basic" HTTP_DIGEST_AUTHENTICATION = "digest" -HTTP_HEADER_HA_AUTH = "X-HA-access" HTTP_HEADER_X_REQUESTED_WITH = "X-Requested-With" CONTENT_TYPE_JSON = "application/json" diff --git a/tests/components/auth/__init__.py b/tests/components/auth/__init__.py index e79d8a67845..5114e18889b 100644 --- a/tests/components/auth/__init__.py +++ b/tests/components/auth/__init__.py @@ -30,7 +30,7 @@ async def async_setup_auth( hass, provider_configs, module_configs ) ensure_auth_manager_loaded(hass.auth) - await async_setup_component(hass, "auth", {"http": {"api_password": "bla"}}) + await async_setup_component(hass, "auth", {}) if setup_api: await async_setup_component(hass, "api", {}) return await aiohttp_client(hass.http.app) diff --git a/tests/components/auth/test_init.py b/tests/components/auth/test_init.py index 80527c2636b..de91613b74b 100644 --- a/tests/components/auth/test_init.py +++ b/tests/components/auth/test_init.py @@ -103,7 +103,7 @@ def test_auth_code_store_expiration(): async def test_ws_current_user(hass, hass_ws_client, hass_access_token): """Test the current user command with homeassistant creds.""" - assert await async_setup_component(hass, "auth", {"http": {"api_password": "bla"}}) + assert await async_setup_component(hass, "auth", {}) refresh_token = await hass.auth.async_validate_access_token(hass_access_token) user = refresh_token.user diff --git a/tests/components/conftest.py b/tests/components/conftest.py index 8c2515939f3..4f1f3e64e02 100644 --- a/tests/components/conftest.py +++ b/tests/components/conftest.py @@ -40,7 +40,9 @@ def hass_ws_client(aiohttp_client, hass_access_token): assert auth_resp["type"] == TYPE_AUTH_REQUIRED if access_token is None: - await websocket.send_json({"type": TYPE_AUTH, "api_password": "bla"}) + await websocket.send_json( + {"type": TYPE_AUTH, "access_token": "incorrect"} + ) else: await websocket.send_json( {"type": TYPE_AUTH, "access_token": access_token} diff --git a/tests/components/google_assistant/test_google_assistant.py b/tests/components/google_assistant/test_google_assistant.py index 6473e8964b8..b43e913ab27 100644 --- a/tests/components/google_assistant/test_google_assistant.py +++ b/tests/components/google_assistant/test_google_assistant.py @@ -3,7 +3,7 @@ import asyncio import json -from aiohttp.hdrs import CONTENT_TYPE, AUTHORIZATION +from aiohttp.hdrs import AUTHORIZATION import pytest from homeassistant import core, const, setup @@ -24,11 +24,6 @@ from . import DEMO_DEVICES API_PASSWORD = "test1234" -HA_HEADERS = { - const.HTTP_HEADER_HA_AUTH: API_PASSWORD, - CONTENT_TYPE: const.CONTENT_TYPE_JSON, -} - PROJECT_ID = "hasstest-1234" CLIENT_ID = "helloworld" ACCESS_TOKEN = "superdoublesecret" diff --git a/tests/components/hassio/__init__.py b/tests/components/hassio/__init__.py index 8e2b6db777d..767ec59f366 100644 --- a/tests/components/hassio/__init__.py +++ b/tests/components/hassio/__init__.py @@ -1,4 +1,3 @@ """Tests for Hassio component.""" -API_PASSWORD = "pass1234" HASSIO_TOKEN = "123456" diff --git a/tests/components/hassio/conftest.py b/tests/components/hassio/conftest.py index d7d50b97eb8..0e246cf1b46 100644 --- a/tests/components/hassio/conftest.py +++ b/tests/components/hassio/conftest.py @@ -9,7 +9,7 @@ from homeassistant.setup import async_setup_component from homeassistant.components.hassio.handler import HassIO, HassioAPIError from tests.common import mock_coro -from . import API_PASSWORD, HASSIO_TOKEN +from . import HASSIO_TOKEN @pytest.fixture @@ -39,23 +39,19 @@ def hassio_stubs(hassio_env, hass, hass_client, aioclient_mock): side_effect=HassioAPIError(), ): hass.state = CoreState.starting - hass.loop.run_until_complete( - async_setup_component( - hass, "hassio", {"http": {"api_password": API_PASSWORD}} - ) - ) + hass.loop.run_until_complete(async_setup_component(hass, "hassio", {})) @pytest.fixture def hassio_client(hassio_stubs, hass, hass_client): """Return a Hass.io HTTP client.""" - yield hass.loop.run_until_complete(hass_client()) + return hass.loop.run_until_complete(hass_client()) @pytest.fixture def hassio_noauth_client(hassio_stubs, hass, aiohttp_client): """Return a Hass.io HTTP client without auth.""" - yield hass.loop.run_until_complete(aiohttp_client(hass.http.app)) + return hass.loop.run_until_complete(aiohttp_client(hass.http.app)) @pytest.fixture diff --git a/tests/components/hassio/test_addon_panel.py b/tests/components/hassio/test_addon_panel.py index 114935df3fc..480df508968 100644 --- a/tests/components/hassio/test_addon_panel.py +++ b/tests/components/hassio/test_addon_panel.py @@ -4,10 +4,8 @@ from unittest.mock import patch, Mock import pytest from homeassistant.setup import async_setup_component -from homeassistant.const import HTTP_HEADER_HA_AUTH from tests.common import mock_coro -from . import API_PASSWORD @pytest.fixture(autouse=True) @@ -53,9 +51,7 @@ async def test_hassio_addon_panel_startup(hass, aioclient_mock, hassio_env): "homeassistant.components.hassio.addon_panel._register_panel", Mock(return_value=mock_coro()), ) as mock_panel: - await async_setup_component( - hass, "hassio", {"http": {"api_password": API_PASSWORD}} - ) + await async_setup_component(hass, "hassio", {}) await hass.async_block_till_done() assert aioclient_mock.call_count == 3 @@ -98,9 +94,7 @@ async def test_hassio_addon_panel_api(hass, aioclient_mock, hassio_env, hass_cli "homeassistant.components.hassio.addon_panel._register_panel", Mock(return_value=mock_coro()), ) as mock_panel: - await async_setup_component( - hass, "hassio", {"http": {"api_password": API_PASSWORD}} - ) + await async_setup_component(hass, "hassio", {}) await hass.async_block_till_done() assert aioclient_mock.call_count == 3 @@ -113,14 +107,10 @@ async def test_hassio_addon_panel_api(hass, aioclient_mock, hassio_env, hass_cli hass_client = await hass_client() - resp = await hass_client.post( - "/api/hassio_push/panel/test2", headers={HTTP_HEADER_HA_AUTH: API_PASSWORD} - ) + resp = await hass_client.post("/api/hassio_push/panel/test2") assert resp.status == 400 - resp = await hass_client.post( - "/api/hassio_push/panel/test1", headers={HTTP_HEADER_HA_AUTH: API_PASSWORD} - ) + resp = await hass_client.post("/api/hassio_push/panel/test1") assert resp.status == 200 assert mock_panel.call_count == 2 diff --git a/tests/components/hassio/test_auth.py b/tests/components/hassio/test_auth.py index a2839b297b8..1fb6d32ccf7 100644 --- a/tests/components/hassio/test_auth.py +++ b/tests/components/hassio/test_auth.py @@ -1,11 +1,9 @@ """The tests for the hassio component.""" from unittest.mock import patch, Mock -from homeassistant.const import HTTP_HEADER_HA_AUTH from homeassistant.exceptions import HomeAssistantError from tests.common import mock_coro -from . import API_PASSWORD async def test_login_success(hass, hassio_client): @@ -18,7 +16,6 @@ async def test_login_success(hass, hassio_client): resp = await hassio_client.post( "/api/hassio_auth", json={"username": "test", "password": "123456", "addon": "samba"}, - headers={HTTP_HEADER_HA_AUTH: API_PASSWORD}, ) # Check we got right response @@ -36,7 +33,6 @@ async def test_login_error(hass, hassio_client): resp = await hassio_client.post( "/api/hassio_auth", json={"username": "test", "password": "123456", "addon": "samba"}, - headers={HTTP_HEADER_HA_AUTH: API_PASSWORD}, ) # Check we got right response @@ -51,9 +47,7 @@ async def test_login_no_data(hass, hassio_client): "HassAuthProvider.async_validate_login", Mock(side_effect=HomeAssistantError()), ) as mock_login: - resp = await hassio_client.post( - "/api/hassio_auth", headers={HTTP_HEADER_HA_AUTH: API_PASSWORD} - ) + resp = await hassio_client.post("/api/hassio_auth") # Check we got right response assert resp.status == 400 @@ -68,9 +62,7 @@ async def test_login_no_username(hass, hassio_client): Mock(side_effect=HomeAssistantError()), ) as mock_login: resp = await hassio_client.post( - "/api/hassio_auth", - json={"password": "123456", "addon": "samba"}, - headers={HTTP_HEADER_HA_AUTH: API_PASSWORD}, + "/api/hassio_auth", json={"password": "123456", "addon": "samba"} ) # Check we got right response @@ -93,7 +85,6 @@ async def test_login_success_extra(hass, hassio_client): "addon": "samba", "path": "/share", }, - headers={HTTP_HEADER_HA_AUTH: API_PASSWORD}, ) # Check we got right response diff --git a/tests/components/hassio/test_discovery.py b/tests/components/hassio/test_discovery.py index 89f1483ffab..a1b4ae2e900 100644 --- a/tests/components/hassio/test_discovery.py +++ b/tests/components/hassio/test_discovery.py @@ -3,10 +3,9 @@ from unittest.mock import patch, Mock from homeassistant.setup import async_setup_component from homeassistant.components.hassio.handler import HassioAPIError -from homeassistant.const import EVENT_HOMEASSISTANT_START, HTTP_HEADER_HA_AUTH +from homeassistant.const import EVENT_HOMEASSISTANT_START from tests.common import mock_coro -from . import API_PASSWORD async def test_hassio_discovery_startup(hass, aioclient_mock, hassio_client): @@ -101,9 +100,7 @@ async def test_hassio_discovery_startup_done(hass, aioclient_mock, hassio_client Mock(return_value=mock_coro({"type": "abort"})), ) as mock_mqtt: await hass.async_start() - await async_setup_component( - hass, "hassio", {"http": {"api_password": API_PASSWORD}} - ) + await async_setup_component(hass, "hassio", {}) await hass.async_block_till_done() assert aioclient_mock.call_count == 2 @@ -151,7 +148,6 @@ async def test_hassio_discovery_webhook(hass, aioclient_mock, hassio_client): ) as mock_mqtt: resp = await hassio_client.post( "/api/hassio_push/discovery/testuuid", - headers={HTTP_HEADER_HA_AUTH: API_PASSWORD}, json={"addon": "mosquitto", "service": "mqtt", "uuid": "testuuid"}, ) await hass.async_block_till_done() diff --git a/tests/components/hassio/test_http.py b/tests/components/hassio/test_http.py index 8f77d6b6234..96d53f93c3a 100644 --- a/tests/components/hassio/test_http.py +++ b/tests/components/hassio/test_http.py @@ -4,19 +4,13 @@ from unittest.mock import patch import pytest -from homeassistant.const import HTTP_HEADER_HA_AUTH - -from . import API_PASSWORD - @asyncio.coroutine def test_forward_request(hassio_client, aioclient_mock): """Test fetching normal path.""" aioclient_mock.post("http://127.0.0.1/beer", text="response") - resp = yield from hassio_client.post( - "/api/hassio/beer", headers={HTTP_HEADER_HA_AUTH: API_PASSWORD} - ) + resp = yield from hassio_client.post("/api/hassio/beer") # Check we got right response assert resp.status == 200 @@ -87,9 +81,7 @@ def test_forward_log_request(hassio_client, aioclient_mock): """Test fetching normal log path doesn't remove ANSI color escape codes.""" aioclient_mock.get("http://127.0.0.1/beer/logs", text="\033[32mresponse\033[0m") - resp = yield from hassio_client.get( - "/api/hassio/beer/logs", headers={HTTP_HEADER_HA_AUTH: API_PASSWORD} - ) + resp = yield from hassio_client.get("/api/hassio/beer/logs") # Check we got right response assert resp.status == 200 @@ -107,9 +99,7 @@ def test_bad_gateway_when_cannot_find_supervisor(hassio_client): "homeassistant.components.hassio.http.async_timeout.timeout", side_effect=asyncio.TimeoutError, ): - resp = yield from hassio_client.get( - "/api/hassio/addons/test/info", headers={HTTP_HEADER_HA_AUTH: API_PASSWORD} - ) + resp = yield from hassio_client.get("/api/hassio/addons/test/info") assert resp.status == 502 diff --git a/tests/components/http/__init__.py b/tests/components/http/__init__.py index c4f73fd15a6..db5e1ea5c7a 100644 --- a/tests/components/http/__init__.py +++ b/tests/components/http/__init__.py @@ -6,6 +6,10 @@ from aiohttp import web from homeassistant.components.http.const import KEY_REAL_IP +# Relic from the past. Kept here so we can run negative tests. +HTTP_HEADER_HA_AUTH = "X-HA-access" + + def mock_real_ip(app): """Inject middleware to mock real IP. diff --git a/tests/components/http/test_auth.py b/tests/components/http/test_auth.py index 842201beace..499ceab1556 100644 --- a/tests/components/http/test_auth.py +++ b/tests/components/http/test_auth.py @@ -11,10 +11,8 @@ from homeassistant.auth.providers import trusted_networks from homeassistant.components.http.auth import setup_auth, async_sign_path from homeassistant.components.http.const import KEY_AUTHENTICATED from homeassistant.components.http.real_ip import setup_real_ip -from homeassistant.const import HTTP_HEADER_HA_AUTH from homeassistant.setup import async_setup_component -from . import mock_real_ip - +from . import mock_real_ip, HTTP_HEADER_HA_AUTH API_PASSWORD = "test-password" @@ -87,29 +85,29 @@ async def test_auth_middleware_loaded_by_default(hass): assert len(mock_setup.mock_calls) == 1 -async def test_access_with_password_in_header(app, aiohttp_client, legacy_auth, hass): +async def test_cant_access_with_password_in_header( + app, aiohttp_client, legacy_auth, hass +): """Test access with password in header.""" setup_auth(hass, app) client = await aiohttp_client(app) - user = await get_legacy_user(hass.auth) req = await client.get("/", headers={HTTP_HEADER_HA_AUTH: API_PASSWORD}) - assert req.status == 200 - assert await req.json() == {"user_id": user.id} + assert req.status == 401 req = await client.get("/", headers={HTTP_HEADER_HA_AUTH: "wrong-pass"}) assert req.status == 401 -async def test_access_with_password_in_query(app, aiohttp_client, legacy_auth, hass): +async def test_cant_access_with_password_in_query( + app, aiohttp_client, legacy_auth, hass +): """Test access with password in URL.""" setup_auth(hass, app) client = await aiohttp_client(app) - user = await get_legacy_user(hass.auth) resp = await client.get("/", params={"api_password": API_PASSWORD}) - assert resp.status == 200 - assert await resp.json() == {"user_id": user.id} + assert resp.status == 401 resp = await client.get("/") assert resp.status == 401 @@ -118,15 +116,13 @@ async def test_access_with_password_in_query(app, aiohttp_client, legacy_auth, h assert resp.status == 401 -async def test_basic_auth_works(app, aiohttp_client, hass, legacy_auth): +async def test_basic_auth_does_not_work(app, aiohttp_client, hass, legacy_auth): """Test access with basic authentication.""" setup_auth(hass, app) client = await aiohttp_client(app) - user = await get_legacy_user(hass.auth) req = await client.get("/", auth=BasicAuth("homeassistant", API_PASSWORD)) - assert req.status == 200 - assert await req.json() == {"user_id": user.id} + assert req.status == 401 req = await client.get("/", auth=BasicAuth("wrong_username", API_PASSWORD)) assert req.status == 401 @@ -138,7 +134,7 @@ async def test_basic_auth_works(app, aiohttp_client, hass, legacy_auth): assert req.status == 401 -async def test_access_with_trusted_ip( +async def test_cannot_access_with_trusted_ip( hass, app2, trusted_networks_auth, aiohttp_client, hass_owner_user ): """Test access with an untrusted ip address.""" @@ -155,8 +151,7 @@ async def test_access_with_trusted_ip( for remote_addr in TRUSTED_ADDRESSES: set_mock_ip(remote_addr) resp = await client.get("/") - assert resp.status == 200, "{} should be trusted".format(remote_addr) - assert await resp.json() == {"user_id": hass_owner_user.id} + assert resp.status == 401, "{} shouldn't be trusted".format(remote_addr) async def test_auth_active_access_with_access_token_in_header( @@ -209,29 +204,24 @@ async def test_auth_active_access_with_trusted_ip( for remote_addr in TRUSTED_ADDRESSES: set_mock_ip(remote_addr) resp = await client.get("/") - assert resp.status == 200, "{} should be trusted".format(remote_addr) - assert await resp.json() == {"user_id": hass_owner_user.id} + assert resp.status == 401, "{} shouldn't be trusted".format(remote_addr) -async def test_auth_legacy_support_api_password_access( +async def test_auth_legacy_support_api_password_cannot_access( app, aiohttp_client, legacy_auth, hass ): """Test access using api_password if auth.support_legacy.""" setup_auth(hass, app) client = await aiohttp_client(app) - user = await get_legacy_user(hass.auth) req = await client.get("/", headers={HTTP_HEADER_HA_AUTH: API_PASSWORD}) - assert req.status == 200 - assert await req.json() == {"user_id": user.id} + assert req.status == 401 resp = await client.get("/", params={"api_password": API_PASSWORD}) - assert resp.status == 200 - assert await resp.json() == {"user_id": user.id} + assert resp.status == 401 req = await client.get("/", auth=BasicAuth("homeassistant", API_PASSWORD)) - assert req.status == 200 - assert await req.json() == {"user_id": user.id} + assert req.status == 401 async def test_auth_access_signed_path(hass, app, aiohttp_client, hass_access_token): diff --git a/tests/components/http/test_ban.py b/tests/components/http/test_ban.py index fc31de4b950..f50afcef8a8 100644 --- a/tests/components/http/test_ban.py +++ b/tests/components/http/test_ban.py @@ -148,6 +148,8 @@ async def test_failed_login_attempts_counter(hass, aiohttp_client): assert resp.status == 200 assert app[KEY_FAILED_LOGIN_ATTEMPTS][remote_ip] == 2 + # This used to check that with trusted networks we reset login attempts + # We no longer support trusted networks. resp = await client.get("/auth_true") assert resp.status == 200 - assert remote_ip not in app[KEY_FAILED_LOGIN_ATTEMPTS] + assert app[KEY_FAILED_LOGIN_ATTEMPTS][remote_ip] == 2 diff --git a/tests/components/http/test_cors.py b/tests/components/http/test_cors.py index 99b9e0b6e9a..1cea900d971 100644 --- a/tests/components/http/test_cors.py +++ b/tests/components/http/test_cors.py @@ -13,11 +13,12 @@ from aiohttp.hdrs import ( ) import pytest -from homeassistant.const import HTTP_HEADER_HA_AUTH from homeassistant.setup import async_setup_component from homeassistant.components.http.cors import setup_cors from homeassistant.components.http.view import HomeAssistantView +from . import HTTP_HEADER_HA_AUTH + TRUSTED_ORIGIN = "https://home-assistant.io" @@ -91,13 +92,13 @@ async def test_cors_preflight_allowed(client): headers={ ORIGIN: TRUSTED_ORIGIN, ACCESS_CONTROL_REQUEST_METHOD: "GET", - ACCESS_CONTROL_REQUEST_HEADERS: "x-ha-access", + ACCESS_CONTROL_REQUEST_HEADERS: "x-requested-with", }, ) assert req.status == 200 assert req.headers[ACCESS_CONTROL_ALLOW_ORIGIN] == TRUSTED_ORIGIN - assert req.headers[ACCESS_CONTROL_ALLOW_HEADERS] == HTTP_HEADER_HA_AUTH.upper() + assert req.headers[ACCESS_CONTROL_ALLOW_HEADERS] == "X-REQUESTED-WITH" async def test_cors_middleware_with_cors_allowed_view(hass): diff --git a/tests/components/http/test_init.py b/tests/components/http/test_init.py index d8e613df6df..ad8e3ac10fd 100644 --- a/tests/components/http/test_init.py +++ b/tests/components/http/test_init.py @@ -133,7 +133,7 @@ async def test_not_log_password(hass, aiohttp_client, caplog, legacy_auth): resp = await client.get("/api/", params={"api_password": "test-password"}) - assert resp.status == 200 + assert resp.status == 401 logs = caplog.text # Ensure we don't log API passwords diff --git a/tests/components/mqtt/test_server.py b/tests/components/mqtt/test_server.py index c210d773faf..3627c95040e 100644 --- a/tests/components/mqtt/test_server.py +++ b/tests/components/mqtt/test_server.py @@ -57,12 +57,7 @@ class TestMQTT: self.hass.config.api = MagicMock(api_password="api_password") assert setup_component( - self.hass, - mqtt.DOMAIN, - { - "http": {"api_password": "http_secret"}, - mqtt.DOMAIN: {CONF_PASSWORD: password}, - }, + self.hass, mqtt.DOMAIN, {mqtt.DOMAIN: {CONF_PASSWORD: password}} ) self.hass.block_till_done() assert mock_mqtt.called diff --git a/tests/components/websocket_api/__init__.py b/tests/components/websocket_api/__init__.py index 56def1b7fd9..4904270cc72 100644 --- a/tests/components/websocket_api/__init__.py +++ b/tests/components/websocket_api/__init__.py @@ -1,2 +1 @@ """Tests for the websocket API.""" -API_PASSWORD = "test-password" diff --git a/tests/components/websocket_api/conftest.py b/tests/components/websocket_api/conftest.py index 2ee28c0cb20..382de3142e8 100644 --- a/tests/components/websocket_api/conftest.py +++ b/tests/components/websocket_api/conftest.py @@ -5,8 +5,6 @@ from homeassistant.setup import async_setup_component from homeassistant.components.websocket_api.http import URL from homeassistant.components.websocket_api.auth import TYPE_AUTH_REQUIRED -from . import API_PASSWORD - @pytest.fixture def websocket_client(hass, hass_ws_client, hass_access_token): @@ -17,11 +15,7 @@ def websocket_client(hass, hass_ws_client, hass_access_token): @pytest.fixture def no_auth_websocket_client(hass, loop, aiohttp_client): """Websocket connection that requires authentication.""" - assert loop.run_until_complete( - async_setup_component( - hass, "websocket_api", {"http": {"api_password": API_PASSWORD}} - ) - ) + assert loop.run_until_complete(async_setup_component(hass, "websocket_api", {})) client = loop.run_until_complete(aiohttp_client(hass.http.app)) ws = loop.run_until_complete(client.ws_connect(URL)) diff --git a/tests/components/websocket_api/test_auth.py b/tests/components/websocket_api/test_auth.py index 19b9cbb2196..00387506020 100644 --- a/tests/components/websocket_api/test_auth.py +++ b/tests/components/websocket_api/test_auth.py @@ -17,21 +17,10 @@ from homeassistant.setup import async_setup_component from tests.common import mock_coro -from . import API_PASSWORD - -async def test_auth_via_msg(no_auth_websocket_client, legacy_auth): - """Test authenticating.""" - await no_auth_websocket_client.send_json( - {"type": TYPE_AUTH, "api_password": API_PASSWORD} - ) - - msg = await no_auth_websocket_client.receive_json() - - assert msg["type"] == TYPE_AUTH_OK - - -async def test_auth_events(hass, no_auth_websocket_client, legacy_auth): +async def test_auth_events( + hass, no_auth_websocket_client, legacy_auth, hass_access_token +): """Test authenticating.""" connected_evt = [] hass.helpers.dispatcher.async_dispatcher_connect( @@ -42,7 +31,7 @@ async def test_auth_events(hass, no_auth_websocket_client, legacy_auth): SIGNAL_WEBSOCKET_DISCONNECTED, lambda: disconnected_evt.append(1) ) - await test_auth_via_msg(no_auth_websocket_client, legacy_auth) + await test_auth_active_with_token(hass, no_auth_websocket_client, hass_access_token) assert len(connected_evt) == 1 assert not disconnected_evt @@ -60,7 +49,7 @@ async def test_auth_via_msg_incorrect_pass(no_auth_websocket_client): return_value=mock_coro(), ) as mock_process_wrong_login: await no_auth_websocket_client.send_json( - {"type": TYPE_AUTH, "api_password": API_PASSWORD + "wrong"} + {"type": TYPE_AUTH, "api_password": "wrong"} ) msg = await no_auth_websocket_client.receive_json() @@ -110,31 +99,25 @@ async def test_pre_auth_only_auth_allowed(no_auth_websocket_client): assert msg["message"].startswith("Auth message incorrectly formatted") -async def test_auth_active_with_token(hass, aiohttp_client, hass_access_token): +async def test_auth_active_with_token( + hass, no_auth_websocket_client, hass_access_token +): """Test authenticating with a token.""" - assert await async_setup_component( - hass, "websocket_api", {"http": {"api_password": API_PASSWORD}} + assert await async_setup_component(hass, "websocket_api", {}) + + await no_auth_websocket_client.send_json( + {"type": TYPE_AUTH, "access_token": hass_access_token} ) - client = await aiohttp_client(hass.http.app) - - async with client.ws_connect(URL) as ws: - auth_msg = await ws.receive_json() - assert auth_msg["type"] == TYPE_AUTH_REQUIRED - - await ws.send_json({"type": TYPE_AUTH, "access_token": hass_access_token}) - - auth_msg = await ws.receive_json() - assert auth_msg["type"] == TYPE_AUTH_OK + auth_msg = await no_auth_websocket_client.receive_json() + assert auth_msg["type"] == TYPE_AUTH_OK async def test_auth_active_user_inactive(hass, aiohttp_client, hass_access_token): """Test authenticating with a token.""" refresh_token = await hass.auth.async_validate_access_token(hass_access_token) refresh_token.user.is_active = False - assert await async_setup_component( - hass, "websocket_api", {"http": {"api_password": API_PASSWORD}} - ) + assert await async_setup_component(hass, "websocket_api", {}) client = await aiohttp_client(hass.http.app) @@ -150,9 +133,7 @@ async def test_auth_active_user_inactive(hass, aiohttp_client, hass_access_token async def test_auth_active_with_password_not_allow(hass, aiohttp_client): """Test authenticating with a token.""" - assert await async_setup_component( - hass, "websocket_api", {"http": {"api_password": API_PASSWORD}} - ) + assert await async_setup_component(hass, "websocket_api", {}) client = await aiohttp_client(hass.http.app) @@ -160,7 +141,7 @@ async def test_auth_active_with_password_not_allow(hass, aiohttp_client): auth_msg = await ws.receive_json() assert auth_msg["type"] == TYPE_AUTH_REQUIRED - await ws.send_json({"type": TYPE_AUTH, "api_password": API_PASSWORD}) + await ws.send_json({"type": TYPE_AUTH, "api_password": "some-password"}) auth_msg = await ws.receive_json() assert auth_msg["type"] == TYPE_AUTH_INVALID @@ -168,28 +149,23 @@ async def test_auth_active_with_password_not_allow(hass, aiohttp_client): async def test_auth_legacy_support_with_password(hass, aiohttp_client, legacy_auth): """Test authenticating with a token.""" - assert await async_setup_component( - hass, "websocket_api", {"http": {"api_password": API_PASSWORD}} - ) + assert await async_setup_component(hass, "websocket_api", {}) client = await aiohttp_client(hass.http.app) async with client.ws_connect(URL) as ws: - with patch("homeassistant.auth.AuthManager.support_legacy", return_value=True): - auth_msg = await ws.receive_json() - assert auth_msg["type"] == TYPE_AUTH_REQUIRED + auth_msg = await ws.receive_json() + assert auth_msg["type"] == TYPE_AUTH_REQUIRED - await ws.send_json({"type": TYPE_AUTH, "api_password": API_PASSWORD}) + await ws.send_json({"type": TYPE_AUTH, "api_password": "some-password"}) - auth_msg = await ws.receive_json() - assert auth_msg["type"] == TYPE_AUTH_OK + auth_msg = await ws.receive_json() + assert auth_msg["type"] == TYPE_AUTH_INVALID async def test_auth_with_invalid_token(hass, aiohttp_client): """Test authenticating with a token.""" - assert await async_setup_component( - hass, "websocket_api", {"http": {"api_password": API_PASSWORD}} - ) + assert await async_setup_component(hass, "websocket_api", {}) client = await aiohttp_client(hass.http.app) diff --git a/tests/components/websocket_api/test_commands.py b/tests/components/websocket_api/test_commands.py index a39a0a0e7a6..1de5b8bb2c1 100644 --- a/tests/components/websocket_api/test_commands.py +++ b/tests/components/websocket_api/test_commands.py @@ -14,8 +14,6 @@ from homeassistant.setup import async_setup_component from tests.common import async_mock_service -from . import API_PASSWORD - async def test_call_service(hass, websocket_client): """Test call service command.""" @@ -250,9 +248,7 @@ async def test_ping(websocket_client): async def test_call_service_context_with_user(hass, aiohttp_client, hass_access_token): """Test that the user is set in the service call context.""" - assert await async_setup_component( - hass, "websocket_api", {"http": {"api_password": API_PASSWORD}} - ) + assert await async_setup_component(hass, "websocket_api", {}) calls = async_mock_service(hass, "domain_test", "test_service") client = await aiohttp_client(hass.http.app) diff --git a/tests/components/websocket_api/test_sensor.py b/tests/components/websocket_api/test_sensor.py index 873b9e7269c..84b73060698 100644 --- a/tests/components/websocket_api/test_sensor.py +++ b/tests/components/websocket_api/test_sensor.py @@ -3,10 +3,12 @@ from homeassistant.bootstrap import async_setup_component from tests.common import assert_setup_component -from .test_auth import test_auth_via_msg +from .test_auth import test_auth_active_with_token -async def test_websocket_api(hass, no_auth_websocket_client, legacy_auth): +async def test_websocket_api( + hass, no_auth_websocket_client, hass_access_token, legacy_auth +): """Test API streams.""" with assert_setup_component(1): await async_setup_component( @@ -16,7 +18,7 @@ async def test_websocket_api(hass, no_auth_websocket_client, legacy_auth): state = hass.states.get("sensor.connected_clients") assert state.state == "0" - await test_auth_via_msg(no_auth_websocket_client, legacy_auth) + await test_auth_active_with_token(hass, no_auth_websocket_client, hass_access_token) state = hass.states.get("sensor.connected_clients") assert state.state == "1" diff --git a/tests/scripts/test_check_config.py b/tests/scripts/test_check_config.py index 18143c088be..5199f01807f 100644 --- a/tests/scripts/test_check_config.py +++ b/tests/scripts/test_check_config.py @@ -92,8 +92,8 @@ def test_secrets(isfile_patch, loop): files = { get_test_config_dir(YAML_CONFIG_FILE): BASE_CONFIG - + ("http:\n" " api_password: !secret http_pw"), - secrets_path: ("logger: debug\n" "http_pw: abc123"), + + ("http:\n" " cors_allowed_origins: !secret http_pw"), + secrets_path: ("logger: debug\n" "http_pw: http://google.com"), } with patch_yaml_files(files): @@ -103,17 +103,15 @@ def test_secrets(isfile_patch, loop): assert res["except"] == {} assert res["components"].keys() == {"homeassistant", "http"} assert res["components"]["http"] == { - "api_password": "abc123", - "cors_allowed_origins": ["https://cast.home-assistant.io"], + "cors_allowed_origins": ["http://google.com"], "ip_ban_enabled": True, "login_attempts_threshold": -1, "server_host": "0.0.0.0", "server_port": 8123, - "trusted_networks": [], "ssl_profile": "modern", } - assert res["secret_cache"] == {secrets_path: {"http_pw": "abc123"}} - assert res["secrets"] == {"http_pw": "abc123"} + assert res["secret_cache"] == {secrets_path: {"http_pw": "http://google.com"}} + assert res["secrets"] == {"http_pw": "http://google.com"} assert normalize_yaml_files(res) == [ ".../configuration.yaml", ".../secrets.yaml", diff --git a/tests/test_config.py b/tests/test_config.py index a67cd345797..362608e7af2 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -5,7 +5,6 @@ import copy import os import unittest.mock as mock from collections import OrderedDict -from ipaddress import ip_network import asynctest import pytest @@ -876,48 +875,6 @@ async def test_auth_provider_config_default(hass): assert hass.auth.auth_mfa_modules[0].id == "totp" -async def test_auth_provider_config_default_api_password(hass): - """Test loading default auth provider config with api password.""" - core_config = { - "latitude": 60, - "longitude": 50, - "elevation": 25, - "name": "Huis", - CONF_UNIT_SYSTEM: CONF_UNIT_SYSTEM_IMPERIAL, - "time_zone": "GMT", - } - if hasattr(hass, "auth"): - del hass.auth - await config_util.async_process_ha_core_config(hass, core_config, "pass") - - assert len(hass.auth.auth_providers) == 2 - assert hass.auth.auth_providers[0].type == "homeassistant" - assert hass.auth.auth_providers[1].type == "legacy_api_password" - assert hass.auth.auth_providers[1].api_password == "pass" - - -async def test_auth_provider_config_default_trusted_networks(hass): - """Test loading default auth provider config with trusted networks.""" - core_config = { - "latitude": 60, - "longitude": 50, - "elevation": 25, - "name": "Huis", - CONF_UNIT_SYSTEM: CONF_UNIT_SYSTEM_IMPERIAL, - "time_zone": "GMT", - } - if hasattr(hass, "auth"): - del hass.auth - await config_util.async_process_ha_core_config( - hass, core_config, trusted_networks=["192.168.0.1"] - ) - - assert len(hass.auth.auth_providers) == 2 - assert hass.auth.auth_providers[0].type == "homeassistant" - assert hass.auth.auth_providers[1].type == "trusted_networks" - assert hass.auth.auth_providers[1].trusted_networks[0] == ip_network("192.168.0.1") - - async def test_disallowed_auth_provider_config(hass): """Test loading insecure example auth provider is disallowed.""" core_config = {