From c79b2bf70e13a7cb9fa6f46dac762bb7e5401ba9 Mon Sep 17 00:00:00 2001 From: Jason Hunter Date: Mon, 5 Oct 2026 10:36:20 -0400 Subject: [PATCH] Correct OAuth discovery metadata for public clients (#184254) --- homeassistant/components/auth/login_flow.py | 5 ++++ tests/components/auth/test_login_flow.py | 27 +++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/homeassistant/components/auth/login_flow.py b/homeassistant/components/auth/login_flow.py index 59a3e3d20bec..b5134ce5205c 100644 --- a/homeassistant/components/auth/login_flow.py +++ b/homeassistant/components/auth/login_flow.py @@ -121,6 +121,7 @@ class WellKnownOAuthInfoView(HomeAssistantView): """View to host the OAuth2 information.""" requires_auth = False + cors_allowed = True url = "/.well-known/oauth-authorization-server" name = "well-known/oauth-authorization-server" @@ -138,6 +139,9 @@ class WellKnownOAuthInfoView(HomeAssistantView): "authorization_endpoint": f"{url_prefix}/auth/authorize", "token_endpoint": f"{url_prefix}/auth/token", "revocation_endpoint": f"{url_prefix}/auth/revoke", + "grant_types_supported": ["authorization_code", "refresh_token"], + "token_endpoint_auth_methods_supported": ["none"], + "revocation_endpoint_auth_methods_supported": ["none"], # Home Assistant accepts URL-based client_ids via IndieAuth without # prior registration, and discovers allowed redirect URIs from link # tags or a Client ID Metadata Document served at the client_id URL. @@ -162,6 +166,7 @@ class WellKnownProtectedResourceView(HomeAssistantView): """View to host the OAuth2 Protected Resource Metadata per RFC9728.""" requires_auth = False + cors_allowed = True url = "/.well-known/oauth-protected-resource" name = "well-known/oauth-protected-resource" diff --git a/tests/components/auth/test_login_flow.py b/tests/components/auth/test_login_flow.py index bf386c212628..96cefdf7910f 100644 --- a/tests/components/auth/test_login_flow.py +++ b/tests/components/auth/test_login_flow.py @@ -425,6 +425,9 @@ async def test_well_known_auth_info( "authorization_endpoint": f"{expected_url_prefix}/auth/authorize", "token_endpoint": f"{expected_url_prefix}/auth/token", "revocation_endpoint": f"{expected_url_prefix}/auth/revoke", + "grant_types_supported": ["authorization_code", "refresh_token"], + "token_endpoint_auth_methods_supported": ["none"], + "revocation_endpoint_auth_methods_supported": ["none"], "client_id_metadata_document_supported": True, "code_challenge_methods_supported": ["S256"], "response_types_supported": ["code"], @@ -564,3 +567,27 @@ async def test_login_flow_pkce_validation( assert resp.status == HTTPStatus.BAD_REQUEST result = await resp.json() assert expected_message in result["message"] + + +@pytest.mark.parametrize( + "path", + [ + pytest.param( + "/.well-known/oauth-authorization-server", id="authorization-server" + ), + pytest.param("/.well-known/oauth-protected-resource", id="protected-resource"), + ], +) +async def test_well_known_auth_info_allows_cors( + hass: HomeAssistant, aiohttp_client: ClientSessionGenerator, path: str +) -> None: + """Test browser clients can discover authorization server capabilities.""" + client = await async_setup_auth(hass, aiohttp_client, setup_api=True) + + resp = await client.get( + path, + headers={"origin": "https://client.example"}, + ) + + assert resp.status == HTTPStatus.OK + assert resp.headers["Access-Control-Allow-Origin"] == "https://client.example"