@@ -258,3 +258,50 @@ async def test_websocket_with_proxy_auth(self):
258
258
259
259
# Should accept connection with proxy auth
260
260
websocket .accept .assert_called_once ()
261
+
262
+ @pytest .mark .asyncio
263
+ async def test_streamable_http_auth_with_proxy_header (self ):
264
+ """streamable_http_auth should allow request when proxy header present and auth disabled."""
265
+ # from types import SimpleNamespace
266
+ # from starlette.datastructures import Headers
267
+ from mcpgateway .transports .streamablehttp_transport import streamable_http_auth
268
+
269
+ # Build ASGI scope
270
+ scope = {
271
+ "type" : "http" ,
272
+ "path" : "/servers/123/mcp" ,
273
+ "headers" : [(b"x-authenticated-user" , b"proxy-user" )],
274
+ }
275
+ # Patch settings dynamically
276
+ with patch ("mcpgateway.transports.streamablehttp_transport.settings" ) as mock_settings :
277
+ mock_settings .mcp_client_auth_enabled = False
278
+ mock_settings .trust_proxy_auth = True
279
+ mock_settings .proxy_user_header = "X-Authenticated-User"
280
+ mock_settings .jwt_secret_key = "secret"
281
+ mock_settings .jwt_algorithm = "HS256"
282
+ mock_settings .auth_required = False
283
+
284
+ allowed = await streamable_http_auth (scope , AsyncMock (), AsyncMock ())
285
+ assert allowed is True
286
+
287
+ @pytest .mark .asyncio
288
+ async def test_streamable_http_auth_no_header_denied_when_required (self ):
289
+ """Should deny when proxy header missing and auth_required true."""
290
+ from mcpgateway .transports .streamablehttp_transport import streamable_http_auth
291
+ scope = {
292
+ "type" : "http" ,
293
+ "path" : "/servers/123/mcp" ,
294
+ "headers" : [],
295
+ }
296
+ with patch ("mcpgateway.transports.streamablehttp_transport.settings" ) as mock_settings :
297
+ mock_settings .mcp_client_auth_enabled = False
298
+ mock_settings .trust_proxy_auth = True
299
+ mock_settings .proxy_user_header = "X-Authenticated-User"
300
+ mock_settings .jwt_secret_key = "secret"
301
+ mock_settings .jwt_algorithm = "HS256"
302
+ mock_settings .auth_required = True
303
+ send = AsyncMock ()
304
+ ok = await streamable_http_auth (scope , AsyncMock (), send )
305
+ # When denied, function returns False and send called with 401 response
306
+ assert ok is False
307
+ assert any (isinstance (call .args [0 ], dict ) and call .args [0 ].get ("status" ) == 401 for call in send .mock_calls )
0 commit comments