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);