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