Update authorization server to prefer absolute urls (#152313)

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
Allen Porter
2025-09-14 14:07:31 -07:00
committed by Franck Nijhof
parent 8728312e87
commit 0b159bdb9c
2 changed files with 56 additions and 9 deletions

View File

@@ -92,7 +92,11 @@ from homeassistant.components.http.ban import (
from homeassistant.components.http.data_validator import RequestDataValidator
from homeassistant.components.http.view import HomeAssistantView
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.network import is_cloud_connection
from homeassistant.helpers.network import (
NoURLAvailableError,
get_url,
is_cloud_connection,
)
from homeassistant.util.network import is_local
from . import indieauth
@@ -125,11 +129,18 @@ class WellKnownOAuthInfoView(HomeAssistantView):
async def get(self, request: web.Request) -> web.Response:
"""Return the well known OAuth2 authorization info."""
hass = request.app[KEY_HASS]
# Some applications require absolute urls, so we prefer using the
# current requests url if possible, with fallback to a relative url.
try:
url_prefix = get_url(hass, require_current_request=True)
except NoURLAvailableError:
url_prefix = ""
return self.json(
{
"authorization_endpoint": "/auth/authorize",
"token_endpoint": "/auth/token",
"revocation_endpoint": "/auth/revoke",
"authorization_endpoint": f"{url_prefix}/auth/authorize",
"token_endpoint": f"{url_prefix}/auth/token",
"revocation_endpoint": f"{url_prefix}/auth/revoke",
"response_types_supported": ["code"],
"service_documentation": (
"https://developers.home-assistant.io/docs/auth_api"

View File

@@ -7,6 +7,7 @@ from unittest.mock import patch
import pytest
from homeassistant.core import HomeAssistant
from homeassistant.core_config import async_process_ha_core_config
from . import BASE_CONFIG, async_setup_auth
@@ -371,19 +372,54 @@ async def test_login_exist_user_ip_changes(
assert response == {"message": "IP address changed"}
@pytest.mark.usefixtures("current_request_with_host") # Has example.com host
@pytest.mark.parametrize(
("config", "expected_url_prefix"),
[
(
{
"internal_url": "http://192.168.1.100:8123",
# Current request matches external url
"external_url": "https://example.com",
},
"https://example.com",
),
(
{
# Current request matches internal url
"internal_url": "https://example.com",
"external_url": "https://other.com",
},
"https://example.com",
),
(
{
# Current request does not match either url
"internal_url": "https://other.com",
"external_url": "https://again.com",
},
"",
),
],
ids=["external_url", "internal_url", "no_match"],
)
async def test_well_known_auth_info(
hass: HomeAssistant, aiohttp_client: ClientSessionGenerator
hass: HomeAssistant,
aiohttp_client: ClientSessionGenerator,
config: dict[str, str],
expected_url_prefix: str,
) -> None:
"""Test logging in and the ip address changes results in an rejection."""
"""Test the well-known OAuth authorization server endpoint with different URL configurations."""
await async_process_ha_core_config(hass, config)
client = await async_setup_auth(hass, aiohttp_client, setup_api=True)
resp = await client.get(
"/.well-known/oauth-authorization-server",
)
assert resp.status == 200
assert await resp.json() == {
"authorization_endpoint": "/auth/authorize",
"token_endpoint": "/auth/token",
"revocation_endpoint": "/auth/revoke",
"authorization_endpoint": f"{expected_url_prefix}/auth/authorize",
"token_endpoint": f"{expected_url_prefix}/auth/token",
"revocation_endpoint": f"{expected_url_prefix}/auth/revoke",
"response_types_supported": ["code"],
"service_documentation": "https://developers.home-assistant.io/docs/auth_api",
}