Exemple #1
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);
        }
        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);
        }