public override async Task ValidateClientLogoutRedirectUri(ValidateClientLogoutRedirectUriContext context) {
            var database = context.HttpContext.RequestServices.GetRequiredService<ApplicationContext>();

            // Note: ValidateClientLogoutRedirectUri is not invoked when post_logout_redirect_uri is null.
            // When provided, post_logout_redirect_uri must exactly match the address registered by the client application.
            if (!await database.Applications.AnyAsync(application => application.LogoutRedirectUri == context.PostLogoutRedirectUri)) {
                context.Rejected(error: "invalid_client", description: "Invalid post_logout_redirect_uri");

                return;
            }

            context.Validated();
        }
 /// <summary>
 /// Called to validate that context.PostLogoutRedirectUri a valid and registered URL.
 /// This only occurs when processing the logout endpoint. The application MUST implement this call, and it MUST validate
 /// both of those factors before calling context.Validated. If the context.Validated method is called with a given redirectUri parameter,
 /// then IsValidated will only become true if the incoming redirect URI matches the given redirect URI.
 /// If context.Validated is not called the request will not proceed further.
 /// </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 ValidateClientLogoutRedirectUri(ValidateClientLogoutRedirectUriContext context) => OnValidateClientLogoutRedirectUri(context);
        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 to validate that context.PostLogoutRedirectUri a valid and registered URL.
 /// This only occurs when processing the logout endpoint. The application MUST implement this call, and it MUST validate
 /// both of those factors before calling context.Validated. If the context.Validated method is called with a given redirectUri parameter,
 /// then IsValidated will only become true if the incoming redirect URI matches the given redirect URI. 
 /// If context.Validated is not called the request will not proceed further. 
 /// </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 ValidateClientLogoutRedirectUri(ValidateClientLogoutRedirectUriContext context) => OnValidateClientLogoutRedirectUri(context);