protected override async Task HandleSignOutAsync(SignOutContext context) { // request may be null when no logout request has been received // or has been already handled by InvokeLogoutEndpointAsync. var request = Context.GetOpenIdConnectRequest(); if (request == null) { return; } // Stop processing the request if there's no signout context that matches // the authentication type associated with this middleware instance // or if the response status code doesn't indicate a successful response. if (context == null || Response.StatusCode != 200) { return; } // post_logout_redirect_uri is added to the response message since it can be // set or replaced from the ValidateClientLogoutRedirectUri event. var response = new OpenIdConnectMessage { PostLogoutRedirectUri = request.PostLogoutRedirectUri, State = request.State }; var notification = new ApplyLogoutResponseContext(Context, Options, request, response); await Options.Provider.ApplyLogoutResponse(notification); if (notification.HandledResponse) { return; } else if (notification.Skipped) { return; } // Stop processing the request if no explicit // post_logout_redirect_uri has been provided. if (string.IsNullOrEmpty(response.PostLogoutRedirectUri)) { return; } var location = response.PostLogoutRedirectUri; foreach (var parameter in response.Parameters) { // Don't include post_logout_redirect_uri in the query string. if (string.Equals(parameter.Key, OpenIdConnectParameterNames.PostLogoutRedirectUri, StringComparison.Ordinal)) { continue; } location = QueryHelpers.AddQueryString(location, parameter.Key, parameter.Value); } Response.Redirect(location); }
private async Task <bool> SendLogoutResponseAsync(OpenIdConnectResponse response) { var request = Context.GetOpenIdConnectRequest(); Context.SetOpenIdConnectResponse(response); response.SetProperty(OpenIdConnectConstants.Properties.MessageType, OpenIdConnectConstants.MessageTypes.LogoutResponse); // Note: as this stage, the request may be null (e.g if it couldn't be extracted from the HTTP request). var notification = new ApplyLogoutResponseContext(Context, Scheme, Options, request, response) { PostLogoutRedirectUri = request?.GetProperty <string>(OpenIdConnectConstants.Properties.PostLogoutRedirectUri) }; await Provider.ApplyLogoutResponse(notification); if (notification.Result != null) { if (notification.Result.Handled) { Logger.LogDebug("The logout request was handled in user code."); return(true); } else if (notification.Result.Skipped) { Logger.LogDebug("The default logout request handling was skipped from user code."); return(false); } } if (!string.IsNullOrEmpty(response.Error)) { // Apply a 400 status code by default. Response.StatusCode = 400; if (Options.ApplicationCanDisplayErrors) { // Return false to allow the rest of // the pipeline to handle the request. return(false); } Logger.LogInformation("The logout response was successfully returned " + "as a plain-text document: {Response}.", response); return(await SendNativePageAsync(response)); } // Don't redirect the user agent if no explicit post_logout_redirect_uri was // provided or if the URI was not fully validated by the application code. if (string.IsNullOrEmpty(notification.PostLogoutRedirectUri)) { Logger.LogInformation("The logout response was successfully returned: {Response}.", response); return(true); } // At this stage, throw an exception if the request was not properly extracted, if (request == null) { throw new InvalidOperationException("The logout response cannot be returned."); } // Attach the request state to the end session response. if (string.IsNullOrEmpty(response.State)) { response.State = request.State; } // Create a new parameters dictionary holding the name/value pairs. var parameters = new Dictionary <string, string>(); foreach (var parameter in response.GetParameters()) { // Ignore null or empty parameters, including JSON // objects that can't be represented as strings. var value = (string)parameter.Value; if (string.IsNullOrEmpty(value)) { continue; } parameters.Add(parameter.Key, value); } Logger.LogInformation("The logout response was successfully returned to '{PostLogoutRedirectUri}': {Response}.", notification.PostLogoutRedirectUri, response); var location = QueryHelpers.AddQueryString(notification.PostLogoutRedirectUri, parameters); Response.Redirect(location); return(true); }
/// <summary> /// Called before the LogoutEndpoint endpoint redirects its response to the caller. /// If the web application wishes to produce the authorization 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. /// This call may also be used to add additional response parameters to the authorization response. /// </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 ApplyLogoutResponse(ApplyLogoutResponseContext context) => OnApplyLogoutResponse(context);
private async Task <bool> SendLogoutResponseAsync(OpenIdConnectResponse response) { var request = Context.GetOpenIdConnectRequest(); if (request == null) { request = new OpenIdConnectRequest(); } Context.SetOpenIdConnectResponse(response); var notification = new ApplyLogoutResponseContext(Context, Options, request, response); await Options.Provider.ApplyLogoutResponse(notification); if (notification.HandledResponse) { return(true); } else if (notification.Skipped) { return(false); } if (!string.IsNullOrEmpty(response.Error)) { // Apply a 400 status code by default. Response.StatusCode = 400; if (Options.ApplicationCanDisplayErrors) { // Return false to allow the rest of // the pipeline to handle the request. return(false); } return(await SendNativePageAsync(response)); } // Don't redirect the user agent if no explicit post_logout_redirect_uri was // provided or if the URI was not fully validated by the application code. if (string.IsNullOrEmpty(response.PostLogoutRedirectUri)) { return(true); } // Create a new parameters dictionary holding the name/value pairs. var parameters = new Dictionary <string, string>(); foreach (var parameter in response.GetParameters()) { // Don't include post_logout_redirect_uri in the parameters dictionary. if (string.Equals(parameter.Key, OpenIdConnectConstants.Parameters.PostLogoutRedirectUri, StringComparison.Ordinal)) { continue; } var value = parameter.Value as JValue; if (value == null) { Logger.LogWarning("A parameter whose type was incompatible was ignored and excluded " + "from the logout response: '{Parameter}'.", parameter.Key); continue; } parameters.Add(parameter.Key, (string)value); } var location = QueryHelpers.AddQueryString(response.PostLogoutRedirectUri, parameters); Response.Redirect(location); return(true); }
private async Task <bool> SendLogoutResponseAsync(OpenIdConnectMessage request, OpenIdConnectMessage response) { if (request == null) { request = new OpenIdConnectMessage(); } var notification = new ApplyLogoutResponseContext(Context, Options, request, response); await Options.Provider.ApplyLogoutResponse(notification); if (notification.HandledResponse) { return(true); } else if (notification.Skipped) { return(false); } if (!string.IsNullOrEmpty(response.Error)) { // When returning an error, remove the authorization request from the OWIN context // to inform TeardownCoreAsync that there's nothing more to handle. Context.SetOpenIdConnectRequest(request: null); // Apply a 400 status code by default. Response.StatusCode = 400; if (Options.ApplicationCanDisplayErrors) { Context.SetOpenIdConnectResponse(response); // Return false to allow the rest of // the pipeline to handle the request. return(false); } return(await SendNativePageAsync(response)); } // Don't redirect the user agent if no explicit post_logout_redirect_uri was // provided or if the URI was not fully validated by the application code. if (string.IsNullOrEmpty(response.PostLogoutRedirectUri)) { return(true); } var location = response.PostLogoutRedirectUri; foreach (var parameter in response.Parameters) { // Don't include post_logout_redirect_uri in the query string. if (string.Equals(parameter.Key, OpenIdConnectParameterNames.PostLogoutRedirectUri, StringComparison.Ordinal)) { continue; } location = QueryHelpers.AddQueryString(location, parameter.Key, parameter.Value); } Response.Redirect(location); return(true); }
private async Task <bool> SendLogoutResponseAsync(OpenIdConnectResponse response) { var request = Context.GetOpenIdConnectRequest(); Context.SetOpenIdConnectResponse(response); response.SetProperty(OpenIdConnectConstants.Properties.MessageType, OpenIdConnectConstants.MessageTypes.LogoutResponse); // Note: as this stage, the request may be null (e.g if it couldn't be extracted from the HTTP request). var notification = new ApplyLogoutResponseContext(Context, Scheme, Options, request, response) { PostLogoutRedirectUri = request?.GetProperty <string>(OpenIdConnectConstants.Properties.PostLogoutRedirectUri) }; await Provider.ApplyLogoutResponse(notification); if (notification.Result != null) { if (notification.Result.Handled) { Logger.LogDebug("The logout request was handled in user code."); return(true); } else if (notification.Result.Skipped) { Logger.LogDebug("The default logout request handling was skipped from user code."); return(false); } } if (!string.IsNullOrEmpty(response.Error)) { // Apply a 400 status code by default. Response.StatusCode = 400; if (Options.ApplicationCanDisplayErrors) { // Return false to allow the rest of // the pipeline to handle the request. return(false); } Logger.LogInformation("The logout response was successfully returned " + "as a plain-text document: {Response}.", response); return(await SendNativePageAsync(response)); } // Don't redirect the user agent if no explicit post_logout_redirect_uri was // provided or if the URI was not fully validated by the application code. if (string.IsNullOrEmpty(notification.PostLogoutRedirectUri)) { Logger.LogInformation("The logout response was successfully returned: {Response}.", response); return(true); } // At this stage, throw an exception if the request was not properly extracted, if (request == null) { throw new InvalidOperationException("The logout response cannot be returned."); } // Attach the request state to the end session response. if (string.IsNullOrEmpty(response.State)) { response.State = request.State; } // Note: a dictionary is deliberately not used here to allow multiple parameters with the // same name to be specified. While initially not allowed by the core OAuth2 specification, // this is now accepted by derived drafts like the OAuth2 token exchange specification. // For consistency, multiple parameters with the same name are also supported by this endpoint. var parameters = new List <KeyValuePair <string, string> >(); foreach (var parameter in response.GetParameters()) { var values = (string[])parameter.Value; if (values == null) { continue; } foreach (var value in values) { parameters.Add(new KeyValuePair <string, string>(parameter.Key, value)); } } Logger.LogInformation("The logout response was successfully returned to '{PostLogoutRedirectUri}': {Response}.", notification.PostLogoutRedirectUri, response); var location = notification.PostLogoutRedirectUri; foreach (var parameter in parameters) { location = QueryHelpers.AddQueryString(location, parameter.Key, parameter.Value); } Response.Redirect(location); return(true); }
private async Task <bool> SendLogoutResponseAsync(OpenIdConnectResponse response) { var request = Context.GetOpenIdConnectRequest(); Context.SetOpenIdConnectResponse(response); response.SetProperty(OpenIdConnectConstants.Properties.MessageType, OpenIdConnectConstants.MessageTypes.LogoutResponse); var notification = new ApplyLogoutResponseContext(Context, Options, request, response); await Options.Provider.ApplyLogoutResponse(notification); if (notification.HandledResponse) { Logger.LogDebug("The logout request was handled in user code."); return(true); } else if (notification.Skipped) { Logger.LogDebug("The default logout request handling was skipped from user code."); return(false); } if (!string.IsNullOrEmpty(response.Error)) { // Apply a 400 status code by default. Response.StatusCode = 400; if (Options.ApplicationCanDisplayErrors) { // Return false to allow the rest of // the pipeline to handle the request. return(false); } Logger.LogInformation("The logout response was successfully returned " + "as a plain-text document: {Response}", response); return(await SendNativePageAsync(response)); } Logger.LogInformation("The logout response was successfully returned: {Response}", response); // Don't redirect the user agent if no explicit post_logout_redirect_uri was // provided or if the URI was not fully validated by the application code. if (string.IsNullOrEmpty(response.PostLogoutRedirectUri)) { return(true); } // Create a new parameters dictionary holding the name/value pairs. var parameters = new Dictionary <string, string>(); foreach (var parameter in response.GetParameters()) { // Don't include post_logout_redirect_uri in the parameters dictionary. if (string.Equals(parameter.Key, OpenIdConnectConstants.Parameters.PostLogoutRedirectUri, StringComparison.Ordinal)) { continue; } // Ignore null or empty parameters, including JSON // objects that can't be represented as strings. var value = (string)parameter.Value; if (string.IsNullOrEmpty(value)) { continue; } parameters.Add(parameter.Key, value); } var location = QueryHelpers.AddQueryString(response.PostLogoutRedirectUri, parameters); Response.Redirect(location); return(true); }