private async Task <bool> InvokeLogoutEndpointAsync()
        {
            OpenIdConnectMessage request = null;

            // Note: logout requests must be made via GET but POST requests
            // are also accepted to allow flowing large logout payloads.
            // See https://openid.net/specs/openid-connect-session-1_0.html#RPLogout
            if (string.Equals(Request.Method, "GET", StringComparison.OrdinalIgnoreCase))
            {
                request = new OpenIdConnectMessage(Request.Query.ToDictionary())
                {
                    RequestType = OpenIdConnectRequestType.LogoutRequest
                };
            }

            else if (string.Equals(Request.Method, "POST", StringComparison.OrdinalIgnoreCase))
            {
                // See http://openid.net/specs/openid-connect-core-1_0.html#FormSerialization
                if (string.IsNullOrEmpty(Request.ContentType))
                {
                    return(await SendErrorPageAsync(new OpenIdConnectMessage {
                        Error = OpenIdConnectConstants.Errors.InvalidRequest,
                        ErrorDescription = "A malformed logout request has been received: " +
                                           "the mandatory 'Content-Type' header was missing from the POST request."
                    }));
                }

                // May have media/type; charset=utf-8, allow partial match.
                if (!Request.ContentType.StartsWith("application/x-www-form-urlencoded", StringComparison.OrdinalIgnoreCase))
                {
                    return(await SendErrorPageAsync(new OpenIdConnectMessage {
                        Error = OpenIdConnectConstants.Errors.InvalidRequest,
                        ErrorDescription = "A malformed logout request has been received: " +
                                           "the 'Content-Type' header contained an unexcepted value. " +
                                           "Make sure to use 'application/x-www-form-urlencoded'."
                    }));
                }

                var form = await Request.ReadFormAsync(Context.RequestAborted);

                request = new OpenIdConnectMessage(form.ToDictionary())
                {
                    RequestType = OpenIdConnectRequestType.LogoutRequest
                };
            }

            else
            {
                Logger.LogInformation("A malformed request has been received by the logout endpoint.");

                return(await SendErrorPageAsync(new OpenIdConnectMessage {
                    Error = OpenIdConnectConstants.Errors.InvalidRequest,
                    ErrorDescription = "A malformed logout request has been received: " +
                                       "make sure to use either GET or POST."
                }));
            }

            // Store the logout request in the ASP.NET context.
            Context.SetOpenIdConnectRequest(request);

            // Note: post_logout_redirect_uri is not a mandatory parameter.
            // See http://openid.net/specs/openid-connect-session-1_0.html#RPLogout
            if (!string.IsNullOrEmpty(request.PostLogoutRedirectUri))
            {
                var clientNotification = new ValidateClientLogoutRedirectUriContext(Context, Options, request);
                await Options.Provider.ValidateClientLogoutRedirectUri(clientNotification);

                if (clientNotification.IsRejected)
                {
                    Logger.LogDebug("Unable to validate client information");

                    return(await SendErrorPageAsync(new OpenIdConnectMessage {
                        Error = clientNotification.Error,
                        ErrorDescription = clientNotification.ErrorDescription,
                        ErrorUri = clientNotification.ErrorUri
                    }));
                }
            }

            var notification = new LogoutEndpointContext(Context, Options, request);
            await Options.Provider.LogoutEndpoint(notification);

            if (notification.HandledResponse)
            {
                return(true);
            }

            return(false);
        }
 /// <summary>
 /// Called at the final stage of an incoming logout endpoint request before the execution continues on to the web application component
 /// responsible for producing the html response. Anything present in the OWIN pipeline following the Authorization Server may produce the
 /// response for the logout page. If running on IIS any ASP.NET technology running on the server may produce the response for the
 /// authorization page. If the web application wishes to produce the response directly in the LogoutEndpoint call it may write to the
 /// context.Response directly and should call context.RequestCompleted to stop other handlers from executing.
 /// </summary>
 /// <param name="context">The context of the event carries information in and results out.</param>
 /// <returns>Task to enable asynchronous execution</returns>
 public virtual Task LogoutEndpoint(LogoutEndpointContext context) => OnLogoutEndpoint(context);
 /// <summary>
 /// Called at the final stage of an incoming logout endpoint request before the execution continues on to the web application component 
 /// responsible for producing the html response. Anything present in the OWIN pipeline following the Authorization Server may produce the
 /// response for the logout page. If running on IIS any ASP.NET technology running on the server may produce the response for the 
 /// authorization page. If the web application wishes to produce the response directly in the LogoutEndpoint call it may write to the 
 /// context.Response directly and should call context.RequestCompleted to stop other handlers from executing.
 /// </summary>
 /// <param name="context">The context of the event carries information in and results out.</param>
 /// <returns>Task to enable asynchronous execution</returns>
 public virtual Task LogoutEndpoint(LogoutEndpointContext context) => OnLogoutEndpoint(context);