public async Task <IActionResult> ExecuteFuncAsync(string functionName, Dictionary <string, object> arguments, CancellationToken cancellationToken) { var request = arguments[ScriptConstants.AzureFunctionsHttpRequestKey] as HttpRequest; if (CheckForInfiniteLoop(request)) { return(new BadRequestObjectResult("Infinite loop detected when trying to call a local function or proxy from a proxy.")); } var httpContext = request.HttpContext; httpContext.Items.Add(HttpExtensionConstants.AzureWebJobsUseReverseRoutesKey, true); var route = httpContext.GetRouteData(); RouteContext rc = new RouteContext(httpContext); foreach (var router in route.Routers) { if (router is WebJobsRouter webJobsRouter) { await webJobsRouter.RouteAsync(rc); if (rc.Handler != null) { break; } } } httpContext.Items.Remove(HttpExtensionConstants.AzureWebJobsUseReverseRoutesKey); httpContext.Items.Remove(ScriptConstants.AzureFunctionsHostKey); if (rc.Handler == null) { return(new NotFoundResult()); } await rc.Handler.Invoke(httpContext); FunctionInvocationMiddleware functionInvocationMiddleware = new FunctionInvocationMiddleware(null); if (!httpContext.Items.TryGetValue(ScriptConstants.AzureFunctionsNestedProxyCount, out object nestedProxiesCount)) { httpContext.Items.Add(ScriptConstants.AzureFunctionsNestedProxyCount, 1); } else { httpContext.Items[ScriptConstants.AzureFunctionsNestedProxyCount] = (int)nestedProxiesCount + 1; } await functionInvocationMiddleware.Invoke(httpContext); var result = (IActionResult)httpContext.Items[ScriptConstants.AzureFunctionsProxyResult]; httpContext.Items.Remove(ScriptConstants.AzureFunctionsProxyResult); return(result); }
public void RequiresAuthz_ReturnsExpectedResult() { var uri = new Uri("http://localhost/test"); var request = new DefaultHttpContext().Request; var requestFeature = request.HttpContext.Features.Get <IHttpRequestFeature>(); requestFeature.Method = "GET"; requestFeature.Scheme = uri.Scheme; requestFeature.Path = uri.GetComponents(UriComponents.KeepDelimiter | UriComponents.Path, UriFormat.Unescaped); requestFeature.PathBase = string.Empty; requestFeature.QueryString = uri.GetComponents(UriComponents.KeepDelimiter | UriComponents.Query, UriFormat.Unescaped); requestFeature.Headers = new HeaderDictionary { { "Host", uri.Host } }; // Function level auth requires authz FunctionMetadata metadata = new FunctionMetadata(); var function = new Mock <FunctionDescriptor>(MockBehavior.Strict, "test", null, metadata, null, null, null, null); var attribute = new HttpTriggerAttribute(AuthorizationLevel.Function, "get") { Route = "test" }; function.SetupGet(p => p.HttpTriggerAttribute).Returns(() => attribute); bool result = FunctionInvocationMiddleware.RequiresAuthz(request, function.Object); Assert.True(result); // Proxies don't require authz metadata = new ProxyFunctionMetadata(null); function = new Mock <FunctionDescriptor>(MockBehavior.Strict, "test", null, metadata, null, null, null, null); attribute = new HttpTriggerAttribute(AuthorizationLevel.Function, "get") { Route = "test" }; function.SetupGet(p => p.HttpTriggerAttribute).Returns(() => attribute); result = FunctionInvocationMiddleware.RequiresAuthz(request, function.Object); Assert.False(result); // Anonymous functions don't require authz metadata = new FunctionMetadata(); function = new Mock <FunctionDescriptor>(MockBehavior.Strict, "test", null, metadata, null, null, null, null); attribute = new HttpTriggerAttribute(AuthorizationLevel.Anonymous, "get") { Route = "test" }; function.SetupGet(p => p.HttpTriggerAttribute).Returns(() => attribute); result = FunctionInvocationMiddleware.RequiresAuthz(request, function.Object); Assert.False(result); // Anonymous functions with EasyAuth header require authz requestFeature.Headers = new HeaderDictionary { { ScriptConstants.EasyAuthIdentityHeader, "abc123" } }; result = FunctionInvocationMiddleware.RequiresAuthz(request, function.Object); Assert.True(result); // Anonymous functions with key header require authz requestFeature.Headers = new HeaderDictionary { { AuthenticationLevelHandler.FunctionsKeyHeaderName, "abc123" } }; result = FunctionInvocationMiddleware.RequiresAuthz(request, function.Object); Assert.True(result); // Anonymous functions with key query param require authz uri = new Uri("http://localhost/test?code=abc123"); request = new DefaultHttpContext().Request; requestFeature = request.HttpContext.Features.Get <IHttpRequestFeature>(); requestFeature.Method = "GET"; requestFeature.Scheme = uri.Scheme; requestFeature.Path = uri.GetComponents(UriComponents.KeepDelimiter | UriComponents.Path, UriFormat.Unescaped); requestFeature.PathBase = string.Empty; requestFeature.QueryString = uri.GetComponents(UriComponents.KeepDelimiter | UriComponents.Query, UriFormat.Unescaped); requestFeature.Headers = new HeaderDictionary { { "Host", uri.Host } }; result = FunctionInvocationMiddleware.RequiresAuthz(request, function.Object); Assert.True(result); }