Search code examples
asp.netblazorblazor-server-sidemicrosoft-identity-platform

Accessing user token when using AzureAdB2C with Microsoft.Identity.Web


I have a simple Blazor server side application that logs in a user using the microsoft-identity-web 0.2.1-preview package.

The aim is to provide authentication using an AzureAdB2C login which allows a user to sign in using their Microsoft Personal account and use delegated access to call Microsoft Graph functions. (In future I would like to expand this to include other cloud providers hence using B2C).

In my Startup.cs I have added the MicrosoftWebAppAuth and my service as follows:

            services.AddMicrosoftWebAppAuthentication(Configuration, "AzureAdB2C")
               .AddMicrosoftWebAppCallsWebApi(Configuration, new string[] { "User.Read", Constants.ScopeSpecialFolder})
               .AddInMemoryTokenCaches();

            services.AddTransient<MyService>();

My service is correctly called with an initialized ITokenAcquisition

        public MyService(ITokenAcquisition tokenAcquisition,
                              IOptions<WebOptions> webOptionValue, AuthenticationStateProvider AuthenticationStateProvider)
        {

If I then call await tokenAcquisition.GetAccessTokenForAppAsync(scopes); A NullReferenceException is thrown with the following stacktrace:

   at Microsoft.Identity.Web.TokenAcquisition.<BuildConfidentialClientApplicationAsync>d__18.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
   at Microsoft.Identity.Web.TokenAcquisition.<GetOrBuildConfidentialClientApplicationAsync>d__17.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
   at Microsoft.Identity.Web.TokenAcquisition.<GetAccessTokenForAppAsync>d__15.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()

The exact code works fine with AzureAd authentication. I'm assuming this is not the correct way to access the user token when using B2C authentication? What should I be calling instead to make delegated Microsoft API calls?


Solution

  • You are using GetAccessTokenForAppAsync which is a method to acquire an access token for apps using client credential (users are not involved here).

    What you should use is GetAccessTokenForUserAsync():

    await tokenAcquisition.GetAccessTokenForUserAsync(scopes);