private async Task <bool> HandleUnauthorizedAsync(AuthenticationProperties properties) { // Extract the OpenID Connect request from the ASP.NET Core context. // If it cannot be found or doesn't correspond to an authorization // or a token request, throw an InvalidOperationException. var request = Context.GetOpenIdConnectRequest(); if (request == null || (!request.IsAuthorizationRequest() && !request.IsTokenRequest())) { throw new InvalidOperationException("An authorization or token response cannot be returned from this endpoint."); } // Note: if a response was already generated, throw an exception. var response = Context.GetOpenIdConnectResponse(); if (response != null || Response.HasStarted) { throw new InvalidOperationException("A response has already been sent."); } // Prepare a new OpenID Connect response. response = new OpenIdConnectResponse { Error = properties.GetProperty(OpenIdConnectConstants.Properties.Error), ErrorDescription = properties.GetProperty(OpenIdConnectConstants.Properties.ErrorDescription), ErrorUri = properties.GetProperty(OpenIdConnectConstants.Properties.ErrorUri) }; // Remove the error/error_description/error_uri properties from the ticket. properties.RemoveProperty(OpenIdConnectConstants.Properties.Error) .RemoveProperty(OpenIdConnectConstants.Properties.ErrorDescription) .RemoveProperty(OpenIdConnectConstants.Properties.ErrorUri); if (string.IsNullOrEmpty(response.Error)) { response.Error = request.IsAuthorizationRequest() ? OpenIdConnectConstants.Errors.AccessDenied : OpenIdConnectConstants.Errors.InvalidGrant; } if (string.IsNullOrEmpty(response.ErrorDescription)) { response.ErrorDescription = request.IsAuthorizationRequest() ? "The authorization was denied by the resource owner." : "The token request was rejected by the authorization server."; } Logger.LogTrace("A challenge operation was triggered: {Properties}.", properties.Items); var notification = new ProcessChallengeResponseContext(Context, Scheme, Options, properties, request, response); await Provider.ProcessChallengeResponse(notification); if (notification.Result != null) { if (notification.Result.Handled) { Logger.LogDebug("The challenge response was handled in user code."); return(true); } else if (notification.Result.Skipped) { Logger.LogDebug("The default challenge handling was skipped from user code."); return(false); } } else if (notification.IsRejected) { Logger.LogError("The request was rejected with the following error: {Error} ; {Description}", /* Error: */ notification.Error ?? OpenIdConnectConstants.Errors.InvalidRequest, /* Description: */ notification.ErrorDescription); if (request.IsAuthorizationRequest()) { return(await SendAuthorizationResponseAsync(new OpenIdConnectResponse { Error = notification.Error ?? OpenIdConnectConstants.Errors.InvalidRequest, ErrorDescription = notification.ErrorDescription, ErrorUri = notification.ErrorUri })); } return(await SendTokenResponseAsync(new OpenIdConnectResponse { Error = notification.Error ?? OpenIdConnectConstants.Errors.InvalidRequest, ErrorDescription = notification.ErrorDescription, ErrorUri = notification.ErrorUri })); } // Flow the changes made to the properties. properties = notification.Properties; // Create a new ticket containing an empty identity and // the authentication properties extracted from the context. var ticket = new AuthenticationTicket( new ClaimsPrincipal(new ClaimsIdentity()), properties, Scheme.Name); if (request.IsAuthorizationRequest()) { return(await SendAuthorizationResponseAsync(response, ticket)); } return(await SendTokenResponseAsync(response, ticket)); }
/// <summary> /// Represents an event called when processing a challenge response. /// </summary> /// <param name="context">The context instance associated with this event.</param> /// <returns>A <see cref="Task"/> that can be used to monitor the asynchronous operation.</returns> public virtual Task ProcessChallengeResponse(ProcessChallengeResponseContext context) => OnProcessChallengeResponse(context);