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)