From 9e0d3fe461c8c09b504a2348b234d6620c50c1d8 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Wed, 4 Mar 2026 21:55:49 +0100 Subject: [PATCH] Return 401 for non-Basic Authorization headers on /auth endpoint (#6612) aiohttp's BasicAuth.decode() raises ValueError for any non-Basic auth method (e.g. Bearer tokens). This propagated as an unhandled exception, causing a 500 response instead of the expected 401 Unauthorized. Catch the ValueError in _process_basic() and raise HTTPUnauthorized with the WWW-Authenticate realm header so clients get a proper 401 response. Fixes SUPERVISOR-BFG Co-authored-by: Claude Sonnet 4.6 --- supervisor/api/auth.py | 5 ++++- tests/api/test_auth.py | 12 ++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/supervisor/api/auth.py b/supervisor/api/auth.py index 9b194054b..7fc132e1c 100644 --- a/supervisor/api/auth.py +++ b/supervisor/api/auth.py @@ -49,7 +49,10 @@ class APIAuth(CoreSysAttributes): Return a coroutine. """ - auth = BasicAuth.decode(request.headers[AUTHORIZATION]) + try: + auth = BasicAuth.decode(request.headers[AUTHORIZATION]) + except ValueError as err: + raise HTTPUnauthorized(headers=REALM_HEADER) from err return self.sys_auth.check_login(addon, auth.login, auth.password) def _process_dict( diff --git a/tests/api/test_auth.py b/tests/api/test_auth.py index 7d83cf62a..315809e1a 100644 --- a/tests/api/test_auth.py +++ b/tests/api/test_auth.py @@ -330,6 +330,18 @@ async def test_auth_basic_auth_failure( assert resp.status == 401 +@pytest.mark.parametrize("api_client", [TEST_ADDON_SLUG], indirect=True) +async def test_auth_bearer_token_returns_401( + api_client: TestClient, install_addon_ssh: Addon +): + """Test that a Bearer token in Authorization header returns 401, not 500.""" + resp = await api_client.post( + "/auth", headers={"Authorization": "Bearer sometoken123"} + ) + assert "Basic realm" in resp.headers[WWW_AUTHENTICATE] + assert resp.status == 401 + + @pytest.mark.parametrize("api_client", ["local_example"], indirect=True) async def test_auth_addon_no_auth_access( api_client: TestClient, install_addon_example: Addon