question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[Question] How to handle the MsalUiRequiredException for incremental consent with AJAX calls

See original GitHub issue

Which version of Microsoft Identity Web are you using? v0.4.0-preview Where is the issue?

  • Web app
    • Sign-in users
    • [x ] Sign-in users and call web APIs
  • Web API
    • Protected web APIs (validating tokens)
    • Protected web APIs (validating scopes)
    • Protected web APIs call downstream web APIs
  • Token cache serialization
    • In-memory caches
    • Session caches
    • Distributed caches
  • Other (please describe)

Is this a new or an existing app? c. This is a new app or an experiment.

Repro

in startup.cs configureservices:
string[] initialScopes = Configuration.GetValue<string>("DownstreamApi:Scopes")?.Split(' ');
            services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
                .AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd"))
                .EnableTokenAcquisitionToCallDownstreamApi(initialScopes)
                .AddMicrosoftGraph(Configuration.GetSection("DownstreamApi"))
                .AddDistributedTokenCaches();

            services.AddControllersWithViews(options =>
            {
                var policy = new AuthorizationPolicyBuilder()
                    .RequireAuthenticatedUser()
                    .Build();
                options.Filters.Add(new AuthorizeFilter(policy));
            }).AddMicrosoftIdentityUI();
in appsettings.json:
  "DownstreamApi": {
    /*
     'Scopes' contains space separated scopes of the Web API you want to call. This can be:
      - a scope for a V2 application (for instance api:b3682cc7-8b30-4bd2-aaba-080c6bf0fd31/access_as_user)
      - a scope corresponding to a V1 application (for instance <App ID URI>/.default, where  <App ID URI> is the
        App ID URI of a legacy v1 Web application
      Applications are registered in the https:portal.azure.com portal.
    */
    "BaseUrl": "https://graph.microsoft.com/v1.0",
    "Scopes": "user.read"
in controller:
       [Authorize]
        [HttpGet]
        [Route("RecognitionTile")]
        [AuthorizeForScopes(Scopes = new[] { "https://ccbcc.sharepoint.com/AllSites.Read" })]
        public ViewComponentResult RecognitionTile()
        {
            return ViewComponent("RecognitionTile");
        }
for token acquistion;
        /// <summary>
        /// Private: Gets and returns an access token for the provided resource.
        /// </summary>
        /// <param name="resource">Resource to obtain access token for</param>
        /// <returns></returns>
        private async Task<string> GetAccessTokenforResource(string resource)
        {
            // Get the access token for the resource.
            string accessToken = await _tokenAcquisition.GetAccessTokenForUserAsync(new[] { resource });
           //resource is actually same as controller scope -- "https://ccbcc.sharepoint.com/AllSites.Read"

Expected behavior Expect the incremental consent prompt to come up when call the controller. Actual behavior When call the tokenAcquisition.GetAccessTokenForUserAsync(new[] { resource }) they exception is thrown: IDW10502 An MsalUiRequiredException was thrown due to a challenge for the user. Inner Exeption: AADSTS65001: The user or administrator has not consented to use the application with ID ‘xxx’ named ‘xxxx’. Send an interactive authorization request for this user and resource.

Possible solution

Additional context / logs / screenshots This code is trying to access sharepoint api with incremental scope. The initial scope cause the initial consent prompt during authentication: image Cleared all the Permissions prior: image After initial consent: image

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:31 (15 by maintainers)

github_iconTop GitHub Comments

3reactions
creativebrothercommented, Oct 1, 2020

@creativebrother any luck with your AJAX calls after steps taken in this thread? I am facing the same issues.

@OnAzureCloud9 I tried to do the following in startup.cs and it solved the AJAX issue similar as Cookie Authentication scheme mentioned earlier by @Tratcher. Basically it detect AJAX request and return 401 in Response and in Header Location parameter pass the incremental consent page to get Auth Code. The AJAX has a chance to redirect the browser window by window.location = authcode url and avoid CORS errors.

        services.Configure<OpenIdConnectOptions>(OpenIdConnectDefaults.AuthenticationScheme, options =>
        {
            options.Events = new OpenIdConnectEvents()
            {
                OnRedirectToIdentityProvider = context =>
                {
                    if (IsAjaxRequest(context.Request))
                    {
                        var message = context.ProtocolMessage;
                        var properties = context.Properties;
                        if (!string.IsNullOrEmpty(message.State))
                        {
                            properties.Items[OpenIdConnectDefaults.UserstatePropertiesKey] = message.State;
                        }
                        // When redeeming a 'code' for an AccessToken, this value is needed
                        properties.Items.Add(OpenIdConnectDefaults.RedirectUriForCodePropertiesKey, message.RedirectUri);

                        message.State = options.StateDataFormat.Protect(properties);
                        if (string.IsNullOrEmpty(message.IssuerAddress))
                        {
                            throw new InvalidOperationException(
                                "Cannot redirect to the authorization endpoint, the configuration may be missing or invalid.");
                        }

                        if (options.AuthenticationMethod == OpenIdConnectRedirectBehavior.RedirectGet)
                        {
                            var redirectUri = message.CreateAuthenticationRequestUrl();
                            context.Response.Headers["Location"] = redirectUri;
                            context.Response.StatusCode = 401;

                        }
                        else if (options.AuthenticationMethod == OpenIdConnectRedirectBehavior.FormPost)
                        {
                           // similar just let AJAX bring up a form post to avoid the CORS here too...
                        }
                        context.HandleResponse();
                    }
                    return Task.FromResult(0);
                }
            };
        });

But I have another problem after I introduced this OnRedirectToIdentityProvider OpenIdConnectEvent, which is now causing an infinite loop on this authcode page similar to #573, #531. It seems that the it is interfering with the following method protected override async Task HandleChallengeAsync(AuthenticationProperties properties) within public class OpenIdConnectHandler : RemoteAuthenticationHandler<OpenIdConnectOptions>, IAuthenticationSignOutHandler. The method is processing posted auth code and then within same method redeming access token. Trying reading all kind of document about auth code flow which is up to date with the code is a challenging task alone,

I just upgraded the Microsoft.Identity.Web to the 1.0.0, will look if there is any luck.

For my project to move ahead, I just admin consent them all and removed the incremental consent, sadly.

Read more comments on GitHub >

github_iconTop Results From Across the Web

AuthorizeForScopes 'x-ReturnUrl' not being redirected to
Because I am calling the decorated controller with an Ajax request upon erroring with a MsalUiRequiredException a redirect causes a Cors error.
Read more >
Requesting permissions through consent
Learn how developers can request for permissions through consent in the Microsoft identity platform endpoint.
Read more >
Addinmemorytokencaches net core. Caching. NET Classic ...
NET MsalUiRequiredException to handle conditional access and incremental consent. ... NET Core; Implement app roles authorization with Azure AD and ASP.
Read more >
Addinmemorytokencaches get token. Web). In-memory ...
Incremental consent. In that case, the following code continues the example code shown in A web API that calls web APIs: Acquire a...
Read more >
Optimize Authentication and Authorization in your web apps ...
... adding authentication and authorization support to web apps and web APIs ... Identity Platform community call on April 21st at 9:00am PT....
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found