From eaa9582e389a0cacbffd835f9a8af29f386cf542 Mon Sep 17 00:00:00 2001 From: James Hodgkinson Date: Wed, 15 Jul 2026 11:43:50 +1000 Subject: [PATCH] fix(dashboard): set headers for Nous JWKS requests The Nous PyJWKClient was constructed without explicit headers, while the self_hosted provider already sends Accept + User-Agent. Without them the Portal WAF can block the JWKS fetch, so the same failure mode remained for the Nous dashboard-auth route. Mirror the self_hosted fix and add a constructor-contract regression test. --- plugins/dashboard_auth/nous/__init__.py | 4 ++++ .../plugins/dashboard_auth/test_nous_provider.py | 16 ++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/plugins/dashboard_auth/nous/__init__.py b/plugins/dashboard_auth/nous/__init__.py index 480617916dafe..69acd18e36b54 100644 --- a/plugins/dashboard_auth/nous/__init__.py +++ b/plugins/dashboard_auth/nous/__init__.py @@ -420,6 +420,10 @@ class NousDashboardAuthProvider(DashboardAuthProvider): self._jwks_url, cache_keys=True, lifespan=_JWKS_CACHE_SECONDS, + headers={ + "Accept": "application/json", + "User-Agent": "HermesAgent/1.0", + }, ) return self._jwks_client diff --git a/tests/plugins/dashboard_auth/test_nous_provider.py b/tests/plugins/dashboard_auth/test_nous_provider.py index ffd9efac98de7..19cb0bf160acb 100644 --- a/tests/plugins/dashboard_auth/test_nous_provider.py +++ b/tests/plugins/dashboard_auth/test_nous_provider.py @@ -528,6 +528,22 @@ class TestVerifySession: _patched_jwks(p, rsa_keypair) return p + def test_jwks_client_sends_explicit_http_headers(self, provider): + """Constructor-contract regression: the JWKS fetch must send an + explicit Accept + User-Agent so it isn't blocked by the Portal WAF + (same fix as the self_hosted provider).""" + provider._jwks_client = None + with patch("jwt.PyJWKClient") as client_cls: + provider._get_jwks_client() + client_cls.assert_called_once_with( + provider._jwks_url, + cache_keys=True, + lifespan=nous_plugin._JWKS_CACHE_SECONDS, + headers={ + "Accept": "application/json", + "User-Agent": "HermesAgent/1.0", + }, + ) def test_expired_token_returns_none(self, provider, rsa_keypair): token = _mint_token(rsa_keypair, ttl_seconds=-1)