/// <summary>
        /// Handles the <see cref="MsalUiRequiredException"/>.
        /// </summary>
        /// <param name="context">Context provided by ASP.NET Core.</param>
        public override void OnException(ExceptionContext context)
        {
            if (context != null)
            {
                MsalUiRequiredException?msalUiRequiredException = FindMsalUiRequiredExceptionIfAny(context.Exception);
                if (msalUiRequiredException != null &&
                    IncrementalConsentAndConditionalAccessHelper.CanBeSolvedByReSignInOfUser(msalUiRequiredException))
                {
                    // the users cannot provide both scopes and ScopeKeySection at the same time
                    if (!string.IsNullOrWhiteSpace(ScopeKeySection) && Scopes != null && Scopes.Length > 0)
                    {
                        throw new InvalidOperationException(
                                  string.Format(
                                      CultureInfo.InvariantCulture,
                                      IDWebErrorMessage.ProvideEitherScopeKeySectionOrScopes,
                                      nameof(ScopeKeySection),
                                      nameof(Scopes)));
                    }

                    // Do not re-use the property Scopes. For more info: https://github.com/Azure-Samples/active-directory-aspnetcore-webapp-openidconnect-v2/issues/273
                    string[]? incrementalConsentScopes;

                    // If the user wishes us to pick the Scopes from a particular config setting.
                    if (!string.IsNullOrWhiteSpace(ScopeKeySection))
                    {
                        // Load the injected IConfiguration
                        IConfiguration configuration = context.HttpContext.RequestServices.GetRequiredService <IConfiguration>();

                        if (configuration == null)
                        {
                            throw new InvalidOperationException(
                                      string.Format(
                                          CultureInfo.InvariantCulture,
                                          IDWebErrorMessage.ScopeKeySectionIsProvidedButNotPresentInTheServicesCollection,
                                          nameof(ScopeKeySection)));
                        }

                        incrementalConsentScopes = new string[] { configuration.GetValue <string>(ScopeKeySection) };

                        if (Scopes != null && Scopes.Length > 0 && incrementalConsentScopes.Length > 0)
                        {
                            throw new InvalidOperationException(IDWebErrorMessage.NoScopesProvided);
                        }
                    }
                    else
                    {
                        incrementalConsentScopes = Scopes;
                    }

                    AuthenticationProperties properties = IncrementalConsentAndConditionalAccessHelper.BuildAuthenticationProperties(
                        incrementalConsentScopes,
                        msalUiRequiredException,
                        context.HttpContext.User,
                        UserFlow);
                    context.Result = new ChallengeResult(properties);
                }
            }

            base.OnException(context);
        }
        /// <summary>
        /// Finds an MsalUiRequiredException in one of the inner exceptions.
        /// </summary>
        /// <param name="exception">Exception from which we look for an MsalUiRequiredException.</param>
        /// <returns>The MsalUiRequiredException if there is one, null, otherwise.</returns>
        internal /* for testing */ static MsalUiRequiredException?FindMsalUiRequiredExceptionIfAny(Exception exception)
        {
            MsalUiRequiredException?msalUiRequiredException = exception as MsalUiRequiredException;

            if (msalUiRequiredException != null)
            {
                return(msalUiRequiredException);
            }
            else if (exception.InnerException != null)
            {
                return(FindMsalUiRequiredExceptionIfAny(exception.InnerException));
            }
            else
            {
                return(null);
            }
        }
        /// <summary>
        /// Handles the <see cref="MsalUiRequiredException"/>.
        /// </summary>
        /// <param name="context">Context provided by ASP.NET Core.</param>
        public override void OnException(ExceptionContext context)
        {
            if (context != null)
            {
                MsalUiRequiredException?msalUiRequiredException = FindMsalUiRequiredExceptionIfAny(context.Exception);
                if (msalUiRequiredException != null &&
                    IncrementalConsentAndConditionalAccessHelper.CanBeSolvedByReSignInOfUser(msalUiRequiredException))
                {
                    // the users cannot provide both scopes and ScopeKeySection at the same time
                    if (!string.IsNullOrWhiteSpace(ScopeKeySection) && Scopes != null && Scopes.Length > 0)
                    {
                        throw new InvalidOperationException(
                                  string.Format(
                                      CultureInfo.InvariantCulture,
                                      IDWebErrorMessage.ProvideEitherScopeKeySectionOrScopes,
                                      nameof(ScopeKeySection),
                                      nameof(Scopes)));
                    }

                    // Do not re-use the property Scopes. For more info: https://github.com/Azure-Samples/active-directory-aspnetcore-webapp-openidconnect-v2/issues/273
                    string[]? incrementalConsentScopes;

                    // If the user wishes us to pick the Scopes from a particular config setting.
                    if (!string.IsNullOrWhiteSpace(ScopeKeySection))
                    {
                        // Load the injected IConfiguration
                        IConfiguration?configuration = context.HttpContext.RequestServices.GetService <IConfiguration>();

                        if (configuration == null)
                        {
                            throw new InvalidOperationException(
                                      string.Format(
                                          CultureInfo.InvariantCulture,
                                          IDWebErrorMessage.ScopeKeySectionIsProvidedButNotPresentInTheServicesCollection,
                                          nameof(ScopeKeySection)));
                        }

                        incrementalConsentScopes = new string[] { configuration.GetValue <string>(ScopeKeySection) };

                        if (Scopes != null && Scopes.Length > 0 && incrementalConsentScopes.Length > 0)
                        {
                            throw new InvalidOperationException(IDWebErrorMessage.NoScopesProvided);
                        }
                    }
                    else
                    {
                        incrementalConsentScopes = Scopes;
                    }

                    HttpRequest     httpRequest;
                    ClaimsPrincipal user;
                    HttpContext     httpContext = context.HttpContext;

                    lock (httpContext)
                    {
                        httpRequest = httpContext.Request;
                        user        = httpContext.User;
                    }

                    AuthenticationProperties properties = IncrementalConsentAndConditionalAccessHelper.BuildAuthenticationProperties(
                        incrementalConsentScopes,
                        msalUiRequiredException,
                        user,
                        UserFlow);

                    if (IsAjaxRequest(httpRequest) && (!string.IsNullOrEmpty(httpRequest.Headers[Constants.XReturnUrl]) ||
                                                       !string.IsNullOrEmpty(httpRequest.Query[Constants.XReturnUrl])))
                    {
                        string redirectUri = !string.IsNullOrEmpty(httpRequest.Headers[Constants.XReturnUrl]) ? httpRequest.Headers[Constants.XReturnUrl]
                            : httpRequest.Query[Constants.XReturnUrl];

                        UrlHelper urlHelper = new UrlHelper(context);
                        if (urlHelper.IsLocalUrl(redirectUri))
                        {
                            properties.RedirectUri = redirectUri;
                        }
                    }

                    if (AuthenticationScheme != null)
                    {
                        context.Result = new ChallengeResult(AuthenticationScheme, properties);
                    }
                    else
                    {
                        context.Result = new ChallengeResult(properties);
                    }
                }
            }

            base.OnException(context);
        }