Beispiel #1
0
        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IHttpProxy httpProxy, WPMessageInvokerFactory messageInvoker, WPProxySettings settings)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }


            app.UseStaticFiles();
            app.UseRouting();
            app.UseCookiePolicy();
            app.UseAuthentication();
            app.UseAuthorization();


            app.Use(next => context =>
            {
                // Force https scheme (since request inside a docker container may appear to be http)
                context.Request.Scheme = "https";
                return(next(context));
            });

            var transformer    = new WPRequestTransformer(); // or HttpTransformer.Default;
            var requestOptions = new RequestProxyOptions {
                Timeout       = TimeSpan.FromSeconds(100),
                Version       = new Version(1, 1), // Not all servers support HTTP 2
                VersionPolicy = HttpVersionPolicy.RequestVersionOrHigher
            };

            app.UseEndpoints(endpoints =>
            {
                // Dont't authenticate manifest.json
                endpoints.Map("/manifest.json", async httpContext => //
                {
                    var siteSettings = settings.GetForHost(httpContext.Request.Host.ToString());
                    await httpProxy.ProxyAsync(httpContext, siteSettings.SourceAddress, messageInvoker.Create(), requestOptions, transformer);
                });

                endpoints.Map("/{**catch-all}", async httpContext => //
                {
                    var siteSettings = settings.GetForHost(httpContext.Request.Host.ToString());
                    await httpProxy.ProxyAsync(httpContext, siteSettings.SourceAddress, messageInvoker.Create(), requestOptions, transformer);

                    var errorFeature = httpContext.Features.Get <IProxyErrorFeature>();
                    if (errorFeature != null)
                    {
                        var error     = errorFeature.Error;
                        var exception = errorFeature.Exception;
                        throw errorFeature.Exception;
                    }
                })
                .RequireAuthorization(WPProxySettings.AuthorizationPolicy);

                endpoints.MapDefaultControllerRoute();
            });
        }
Beispiel #2
0
        /// <summary>
        /// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        /// </summary>
        public void Configure(IApplicationBuilder app, IHttpProxy httpProxy)
        {
            var httpClient = new HttpMessageInvoker(new SocketsHttpHandler()
            {
                UseProxy               = false,
                AllowAutoRedirect      = false,
                AutomaticDecompression = DecompressionMethods.None,
                UseCookies             = false
            });

            // Copy all request headers except Host
            var transformer    = new CustomTransformer(); // or HttpTransformer.Default;
            var requestOptions = new RequestProxyOptions(TimeSpan.FromSeconds(100), null);

            app.UseRouting();
            app.UseAuthorization();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
                endpoints.Map("/{**catch-all}", async httpContext =>
                {
                    await httpProxy.ProxyAsync(httpContext, "https://localhost:10000/", httpClient, requestOptions, transformer);
                    var errorFeature = httpContext.Features.Get <IProxyErrorFeature>();
                    if (errorFeature != null)
                    {
                        var error     = errorFeature.Error;
                        var exception = errorFeature.Exception;
                    }
                });
            });
        }
Beispiel #3
0
 /// <summary>
 /// Proxies the incoming request to the destination server, and the response back to the client.
 /// </summary>
 /// <param name="context">The HttpContent to proxy from.</param>
 /// <param name="destinationPrefix">The url prefix for where to proxy the request to.</param>
 /// <param name="httpClient">The HTTP client used to send the proxy request.</param>
 public static Task ProxyAsync(
     this IHttpProxy proxy,
     HttpContext context,
     string destinationPrefix,
     HttpMessageInvoker httpClient)
 {
     return(proxy.ProxyAsync(context, destinationPrefix, httpClient, requestOptions: default, HttpTransformer.Default));
Beispiel #4
0
 /// <summary>
 /// Proxies the incoming request to the destination server, and the response back to the client.
 /// </summary>
 /// <param name="context">The HttpContent to proxy from.</param>
 /// <param name="destinationPrefix">The url prefix for where to proxy the request to.</param>
 /// <param name="httpClient">The HTTP client used to send the proxy request.</param>
 /// <returns>The result of the request proxying to the destination.</returns>
 public static ValueTask <ProxyError> ProxyAsync(
     this IHttpProxy proxy,
     HttpContext context,
     string destinationPrefix,
     HttpMessageInvoker httpClient)
 {
     return(proxy.ProxyAsync(context, destinationPrefix, httpClient, RequestProxyConfig.Empty, HttpTransformer.Default));
 }
Beispiel #5
0
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IHttpProxy httpProxy)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            var httpClient = new HttpMessageInvoker(new SocketsHttpHandler()
            {
                UseProxy               = false,
                AllowAutoRedirect      = false,
                AutomaticDecompression = DecompressionMethods.None,
                UseCookies             = false
            });

            app.UseRouting();
            app.UseEndpoints(endpoints =>
            {
                endpoints.Map("/{**catch-all}", async httpContext =>
                {
                    var mocks  = httpContext.RequestServices.GetRequiredService <Mocks>();
                    var logger = httpContext.RequestServices.GetRequiredService <ILogger <Startup> >();

                    var match = mocks.Files.Values
                                .SelectMany(v => v.Log.Entries)
                                .Where(e => new Uri(e.Request.Url).AbsolutePath.ToLower() == httpContext.Request.Path.Value.ToLower())
                                .FirstOrDefault();

                    // Found match in HAR file mock api use HAR response
                    if (match != null)
                    {
                        logger.LogInformation($"Mocking API {new Uri(match.Request.Url).AbsolutePath}");

                        foreach (var header in match.Response.Headers)
                        {
                            if (!new[] { "content-length", "content-encoding" }.Any(h => header.Name.ToLower() == h))
                            {
                                httpContext.Response.Headers.TryAdd(header.Name, header.Value);
                            }
                        }

                        httpContext.Response.StatusCode = match.Response.Status;
                        await httpContext.Response.WriteAsync(match.Response.Content.Text);
                        return;
                    }

                    // No match found, forward request to original api
                    await httpProxy.ProxyAsync(httpContext, _config.GetValue <string>("Api:Url"), httpClient);

                    // Log errors from forwarded request
                    var errorFeature = httpContext.Features.Get <IProxyErrorFeature>();
                    if (errorFeature != null)
                    {
                        logger.LogError(errorFeature.Exception, $"{errorFeature.Error}");
                    }
                });
            });
        }
Beispiel #6
0
        /// <summary>
        /// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        /// </summary>
        public void Configure(IApplicationBuilder app, IHttpProxy httpProxy)
        {
            var httpClient = new HttpMessageInvoker(new SocketsHttpHandler()
            {
                UseProxy               = false,
                AllowAutoRedirect      = false,
                AutomaticDecompression = DecompressionMethods.None,
                UseCookies             = false
            });
            var proxyOptions = new RequestProxyOptions()
            {
                RequestTimeout = TimeSpan.FromSeconds(100),
                // Copy all request headers except Host
                Transforms = new Transforms(
                    copyRequestHeaders: true,
                    requestTransforms: Array.Empty <RequestParametersTransform>(),
                    requestHeaderTransforms: new Dictionary <string, RequestHeaderTransform>()
                {
                    { HeaderNames.Host, new RequestHeaderValueTransform(string.Empty, append: false) }
                },
                    responseHeaderTransforms: new Dictionary <string, ResponseHeaderTransform>(),
                    responseTrailerTransforms: new Dictionary <string, ResponseHeaderTransform>())
            };

            app.UseRouting();
            app.UseAuthorization();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
                endpoints.Map("/{**catch-all}", async httpContext =>
                {
                    await httpProxy.ProxyAsync(httpContext, "https://localhost:10000/", httpClient, proxyOptions);
                    var errorFeature = httpContext.Features.Get <IProxyErrorFeature>();
                    if (errorFeature != null)
                    {
                        var error     = errorFeature.Error;
                        var exception = errorFeature.Exception;
                    }
                });
            });
        }
        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHttpProxy httpProxy)
        {
            var httpClient = new HttpMessageInvoker(new SocketsHttpHandler()
            {
                UseProxy               = false,
                AllowAutoRedirect      = false,
                AutomaticDecompression = System.Net.DecompressionMethods.None,
                UseCookies             = false
            });

            var transformer    = new CustomTransformer();
            var requestOptions = new RequestProxyOptions();

            app.UseHttpsRedirection();

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.Map("/{**catch-all}", async httpContext =>
                {
                    var urls  = getUrls();
                    var teste = httpContext.Request.Headers.FirstOrDefault(c => c.Key == "teste").Value;
                    var url   = urls.FirstOrDefault(x => x.key == "1").url;
                    if (teste.Count != 0)
                    {
                        url = urls?.FirstOrDefault(x => x.key == teste.ToString()).url;
                    }

                    await httpProxy.ProxyAsync(httpContext, url, httpClient, requestOptions);
                    var errorFeature = httpContext.GetProxyErrorFeature();
                    if (errorFeature != null)
                    {
                        var error     = errorFeature.Error;
                        var exception = errorFeature.Exception;
                    }
                });
            });
        }
Beispiel #8
0
        /// <summary>
        /// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        /// </summary>
        public void Configure(IApplicationBuilder app, IHttpProxy httpProxy)
        {
            var httpClient = new HttpMessageInvoker(new SocketsHttpHandler()
            {
                UseProxy               = false,
                AllowAutoRedirect      = false,
                AutomaticDecompression = DecompressionMethods.None,
                UseCookies             = false
            });

            var transformBuilder = app.ApplicationServices.GetRequiredService <ITransformBuilder>();
            var transformer      = transformBuilder.Create(context =>
            {
                context.AddQueryRemoveKey("param1");
                context.AddQueryValue("area", "xx2", false);
                context.AddOriginalHost(false);
            });

            // or var transformer = new CustomTransformer();
            // or var transformer = HttpTransformer.Default;

            var requestOptions = new RequestProxyOptions {
                Timeout = TimeSpan.FromSeconds(100)
            };

            app.UseRouting();
            app.UseEndpoints(endpoints =>
            {
                endpoints.Map("/{**catch-all}", async httpContext =>
                {
                    await httpProxy.ProxyAsync(httpContext, "https://example.com", httpClient, requestOptions, transformer);
                    var errorFeature = httpContext.GetProxyErrorFeature();
                    if (errorFeature != null)
                    {
                        var error     = errorFeature.Error;
                        var exception = errorFeature.Exception;
                    }
                });
            });
        }
Beispiel #9
0
        /// <summary>
        /// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        /// </summary>
        public void Configure(IApplicationBuilder app, IHttpProxy httpProxy)
        {
            // Configure our own HttpMessageInvoker for outbound calls for proxy operations
            var httpClient = new HttpMessageInvoker(new SocketsHttpHandler()
            {
                UseProxy               = false,
                AllowAutoRedirect      = false,
                AutomaticDecompression = DecompressionMethods.None,
                UseCookies             = false
            });

            // Setup our own request transform class
            var transformer    = new CustomTransformer(); // or HttpTransformer.Default;
            var requestOptions = new RequestProxyOptions {
                Timeout = TimeSpan.FromSeconds(100)
            };

            app.UseRouting();
            app.UseEndpoints(endpoints =>
            {
                // When using IHttpProxy for direct proxying you are responsible for routing, destination discovery, load balancing, affinity, etc..
                // For an alternate example that includes those features see BasicYarpSample.
                endpoints.Map("/{**catch-all}", async httpContext =>
                {
                    await httpProxy.ProxyAsync(httpContext, "https://example.com", httpClient, requestOptions, transformer);
                    var errorFeature = httpContext.Features.Get <IProxyErrorFeature>();

                    // Check if the proxy operation was successful
                    if (errorFeature != null)
                    {
                        var error     = errorFeature.Error;
                        var exception = errorFeature.Exception;
                    }
                });
            });
        }
Beispiel #10
0
        /// <inheritdoc/>
        public async Task InvokeAsync(HttpContext context)
        {
            Contracts.CheckValue(context, nameof(context));

            var aspNetCoreEndpoint = context.GetEndpoint();

            if (aspNetCoreEndpoint == null)
            {
                throw new ReverseProxyException($"ASP .NET Core Endpoint wasn't set for the current request. This is a coding defect.");
            }

            var routeConfig = aspNetCoreEndpoint.Metadata.GetMetadata <RouteConfig>();

            if (routeConfig == null)
            {
                throw new ReverseProxyException($"ASP .NET Core Endpoint is missing {typeof(RouteConfig).FullName} metadata. This is a coding defect.");
            }

            var backend = routeConfig.BackendOrNull;

            if (backend == null)
            {
                throw new ReverseProxyException($"Route has no backend information.");
            }

            var dynamicState = backend.DynamicState.Value;

            if (dynamicState == null)
            {
                throw new ReverseProxyException($"Route has no up to date information on its backend '{backend.BackendId}'. Perhaps the backend hasn't been probed yet? This can happen when a new backend is added but isn't ready to serve traffic yet.");
            }

            // TODO: Set defaults properly
            BackendConfig.BackendLoadBalancingOptions loadBalancingOptions = default;
            var backendConfig = backend.Config.Value;

            if (backendConfig != null)
            {
                loadBalancingOptions = backendConfig.LoadBalancingOptions;
            }

            var endpoint = _operationLogger.Execute(
                "ReverseProxy.PickEndpoint",
                () => _loadBalancer.PickEndpoint(dynamicState.HealthyEndpoints, dynamicState.AllEndpoints, in loadBalancingOptions));

            if (endpoint == null)
            {
                throw new ReverseProxyException($"No available endpoints.");
            }

            var endpointConfig = endpoint.Config.Value;

            if (endpointConfig == null)
            {
                throw new ReverseProxyException($"Chosen endpoint has no configs set: '{endpoint.EndpointId}'");
            }

            // TODO: support StripPrefix and other url transformations
            var targetUrl = BuildOutgoingUrl(context, endpointConfig.Address);

            _logger.LogInformation($"Proxying to {targetUrl}");
            var targetUri = new Uri(targetUrl, UriKind.Absolute);

            using (var shortCts = CancellationTokenSource.CreateLinkedTokenSource(context.RequestAborted))
            {
                // TODO: Configurable timeout, measure from request start, make it unit-testable
                shortCts.CancelAfter(TimeSpan.FromSeconds(30));

                // TODO: Retry against other endpoints
                try
                {
                    // TODO: Apply caps
                    backend.ConcurrencyCounter.Increment();
                    endpoint.ConcurrencyCounter.Increment();

                    // TODO: Duplex channels should not have a timeout (?), but must react to Proxy force-shutdown signals.
                    var longCancellation = context.RequestAborted;

                    var proxyTelemetryContext = new ProxyTelemetryContext(
                        backendId: backend.BackendId,
                        routeId: routeConfig.Route.RouteId,
                        endpointId: endpoint.EndpointId);

                    await _operationLogger.ExecuteAsync(
                        "ReverseProxy.Proxy",
                        () => _httpProxy.ProxyAsync(context, targetUri, backend.ProxyHttpClientFactory, proxyTelemetryContext, shortCancellation: shortCts.Token, longCancellation: longCancellation));
                }
                finally
                {
                    endpoint.ConcurrencyCounter.Decrement();
                    backend.ConcurrencyCounter.Decrement();
                }
            }
        }
Beispiel #11
0
        public async Task Invoke(
            HttpContext context,
            AuthenticationManager authenticationManager,
            SingleSignOnHandler singleSignOnHandler,
            ConfigurationProvider configurationProvider,
            SecureRandom secureRandom
            )
        {
            MemorySingletonProxyConfigProvider.Route?route = GetMatchingRoute(context);

            if (route != null)
            {
                bool shouldHandle = true;

                PathString requestPath = context.Request.Path;
                if (requestPath.StartsWithSegments("/.well-known/acme-challenge"))
                {
                    string challenge = ((string)requestPath).Split('/').Last();
                    if (_acmeChallengeSingleton.Challenges.ContainsKey(challenge))
                    {
                        shouldHandle = false;
                    }
                }

                if (shouldHandle)
                {
                    configurationProvider.TryGet(AuthServer.Server.GRPC.InstallService.PRIMARY_DOMAIN_KEY, out string primaryDomain);

                    bool isAuthRequest = singleSignOnHandler.IsAuthRequest(context);
                    if (isAuthRequest)
                    {
                        singleSignOnHandler.Handle(context);
                        return;
                    }

                    bool isPublicEndpoint = route.PublicRoutes.Contains(context.Request.Path);

                    if (!isPublicEndpoint)
                    {
                        bool isAuthenticated = authenticationManager.IsAuthenticated(context, out Guid? sessionId);

                        if (!isAuthenticated)
                        {
                            string csrf = secureRandom.GetRandomString(16);
                            context.Response.Cookies.Append("gatekeeper.csrf", csrf);

                            Dictionary <string, string> queryDictionary = new Dictionary <string, string>()
                            {
                                { "id", route.ProxySettingId.ToString() },
                                { "csrf", csrf },
                            };

                            UriBuilder uriBuilder = new UriBuilder();
                            uriBuilder.Scheme = "https";
                            uriBuilder.Host   = primaryDomain;
                            uriBuilder.Path   = "/auth/sso-connect";
                            uriBuilder.Query  = await((new System.Net.Http.FormUrlEncodedContent(queryDictionary)).ReadAsStringAsync());

                            context.Response.Redirect(uriBuilder.ToString(), false);
                            return;
                        }
                        else
                        {
                            if (sessionId == null)
                            {
                                // This should never happen
                                return;
                            }

                            bool isAuthorized = await authenticationManager.IsAuthorizedAsync((Guid)sessionId, route);

                            if (!isAuthorized)
                            {
                                context.Response.Redirect("https://" + primaryDomain + "/auth/403");
                                return;
                            }
                        }
                    }

                    Dictionary <string, RequestHeaderTransform> requestHeaderTransforms = new Dictionary <string, RequestHeaderTransform>()
                    {
                        {
                            "X-Forwarded-For",
                            new RequestHeaderValueTransform(context.Connection.RemoteIpAddress.ToString(), append: false)
                        },
                        {
                            "X-Forwarded-Host",
                            new RequestHeaderValueTransform(route.PublicHostname, append: false)
                        },
                        {
                            HeaderNames.Host,
                            new RequestHeaderValueTransform(String.Empty, append: false)
                        }
                    };

                    if (context.Request.Cookies.TryGetValue(AuthenticationManager.AUTH_COOKIE, out string?authCookieValue))
                    {
                        // FIXME: This is currently also sent as cookie. Remove this and only send it as header.
                        requestHeaderTransforms.Add(
                            "X-Gatekeeper-Jwt-Assertion",
                            new RequestHeaderValueTransform(authCookieValue, append: false)
                            );
                    }

                    RequestProxyOptions proxyOptions = new RequestProxyOptions()
                    {
                        RequestTimeout = TimeSpan.FromSeconds(100),
                        Transforms     = new Transforms(
                            copyRequestHeaders: true,
                            requestTransforms: Array.Empty <RequestParametersTransform>(),
                            requestHeaderTransforms: requestHeaderTransforms,
                            responseHeaderTransforms: new Dictionary <string, ResponseHeaderTransform>(),
                            responseTrailerTransforms: new Dictionary <string, ResponseHeaderTransform>()
                            )
                    };

                    await _httpProxy.ProxyAsync(context, route.InternalHostname, _httpClient, proxyOptions);

                    return;
                }
            }

            await _nextMiddleware(context);
        }
Beispiel #12
0
        /// <inheritdoc/>
        public async Task Invoke(HttpContext context)
        {
            Contracts.CheckValue(context, nameof(context));

            var backend   = context.Features.Get <BackendInfo>() ?? throw new InvalidOperationException("Backend unspecified.");
            var endpoints = context.Features.Get <IAvailableBackendEndpointsFeature>()?.Endpoints
                            ?? throw new InvalidOperationException("The AvailableBackendEndpoints collection was not set.");
            var routeConfig = context.GetEndpoint()?.Metadata.GetMetadata <RouteConfig>()
                              ?? throw new InvalidOperationException("RouteConfig unspecified.");

            if (endpoints.Count == 0)
            {
                _logger.LogWarning("No available endpoints.");
                context.Response.StatusCode = 503;
                return;
            }

            var endpoint = endpoints[0];

            if (endpoints.Count > 1)
            {
                _logger.LogWarning("More than one endpoint available, load balancing may not be configured correctly. Choosing randomly.");
                endpoint = endpoints[_random.Next(endpoints.Count)];
            }

            var endpointConfig = endpoint.Config.Value;

            if (endpointConfig == null)
            {
                throw new InvalidOperationException($"Chosen endpoint has no configs set: '{endpoint.EndpointId}'");
            }

            // TODO: support StripPrefix and other url transformations
            var targetUrl = BuildOutgoingUrl(context, endpointConfig.Address);

            _logger.LogInformation($"Proxying to {targetUrl}");
            var targetUri = new Uri(targetUrl, UriKind.Absolute);

            using (var shortCts = CancellationTokenSource.CreateLinkedTokenSource(context.RequestAborted))
            {
                // TODO: Configurable timeout, measure from request start, make it unit-testable
                shortCts.CancelAfter(TimeSpan.FromSeconds(30));

                // TODO: Retry against other endpoints
                try
                {
                    // TODO: Apply caps
                    backend.ConcurrencyCounter.Increment();
                    endpoint.ConcurrencyCounter.Increment();

                    // TODO: Duplex channels should not have a timeout (?), but must react to Proxy force-shutdown signals.
                    var longCancellation = context.RequestAborted;

                    var proxyTelemetryContext = new ProxyTelemetryContext(
                        backendId: backend.BackendId,
                        routeId: routeConfig.Route.RouteId,
                        endpointId: endpoint.EndpointId);

                    await _operationLogger.ExecuteAsync(
                        "ReverseProxy.Proxy",
                        () => _httpProxy.ProxyAsync(context, targetUri, backend.ProxyHttpClientFactory, proxyTelemetryContext, shortCancellation: shortCts.Token, longCancellation: longCancellation));
                }
                finally
                {
                    endpoint.ConcurrencyCounter.Decrement();
                    backend.ConcurrencyCounter.Decrement();
                }
            }
        }
Beispiel #13
0
        public async Task Invoke(
            HttpContext context,
            AuthenticationManager authenticationManager,
            SingleSignOnHandler singleSignOnHandler,
            ConfigurationProvider configurationProvider,
            SecureRandom secureRandom
            )
        {
            MemorySingletonProxyConfigProvider.Route?route = GetMatchingRoute(context);

            if (route != null)
            {
                bool shouldHandle = true;

                PathString requestPath = context.Request.Path;
                if (requestPath.StartsWithSegments("/.well-known/acme-challenge"))
                {
                    string challenge = ((string)requestPath).Split('/').Last();
                    if (_acmeChallengeSingleton.Challenges.ContainsKey(challenge))
                    {
                        shouldHandle = false;
                    }
                }

                if (shouldHandle)
                {
                    configurationProvider.TryGet(AuthServer.Server.GRPC.InstallService.PRIMARY_DOMAIN_KEY, out string primaryDomain);

                    bool isAuthRequest = singleSignOnHandler.IsAuthRequest(context);
                    if (isAuthRequest)
                    {
                        singleSignOnHandler.Handle(context);
                        return;
                    }

                    bool isPublicEndpoint = route.PublicRoutes.Contains(context.Request.Path);

                    if (!isPublicEndpoint)
                    {
                        bool isAuthenticated = authenticationManager.IsAuthenticated(context, out Guid? sessionId);

                        if (!isAuthenticated)
                        {
                            string csrf = secureRandom.GetRandomString(16);
                            context.Response.Cookies.Append("gatekeeper.csrf", csrf);

                            Dictionary <string, string> queryDictionary = new Dictionary <string, string>()
                            {
                                { "id", route.ProxySettingId.ToString() },
                                { "csrf", csrf },
                            };

                            UriBuilder uriBuilder = new UriBuilder();
                            uriBuilder.Scheme = "https";
                            uriBuilder.Host   = primaryDomain;
                            uriBuilder.Path   = "/auth/sso-connect";
                            uriBuilder.Query  = await((new System.Net.Http.FormUrlEncodedContent(queryDictionary)).ReadAsStringAsync());

                            context.Response.Redirect(uriBuilder.ToString(), false);
                            return;
                        }
                        else
                        {
                            if (sessionId == null)
                            {
                                // This should never happen
                                return;
                            }

                            bool isAuthorized = await authenticationManager.IsAuthorizedAsync((Guid)sessionId, route);

                            if (!isAuthorized)
                            {
                                context.Response.Redirect("https://" + primaryDomain + "/auth/403");
                                return;
                            }
                        }
                    }

                    RequestProxyOptions proxyOptions = new RequestProxyOptions(
                        TimeSpan.FromSeconds(100),
                        null
                        );

                    await _httpProxy.ProxyAsync(
                        context,
                        route.InternalHostname,
                        _httpClient,
                        proxyOptions,
                        new Gatekeeper.Server.Web.Services.ReverseProxy.Transformer.RequestTransformer(route)
                        );

                    return;
                }
            }

            await _nextMiddleware(context);
        }