0
votes

I've been following this documentation for using Azure AD B2C for authentication in a blazor web app https://docs.microsoft.com/en-us/aspnet/core/blazor/security/webassembly/hosted-with-azure-active-directory-b2c?view=aspnetcore-5.0

After following this documentation, we're left with a solution containing a server and a client, both running on https port 5001. Now, i'd like to switch to using an external api, rather than the one running on port 5001.

Everything seems good and authentication succeeds when manually using the access token retrieved by blazor. But blazor is only automatically attaching the authentication headers to requests starting with https://localhost:5001.

When i'm instead using https://localhost:5003, the authentication header is left empty.

Is there something i can add to the provider options of my MsalAuthentication, in order for it to pass this access token to my api running on https://localhost:5003?

builder.Services.AddHttpClient("{MyAssembly}.ServerAPI", client => client.BaseAddress = new Uri("https://localhost:5003"))
            .AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>();

// Supply HttpClient instances that include access tokens when making requests to the server project
builder.Services.AddScoped(sp => sp.GetRequiredService<IHttpClientFactory>().CreateClient("{MyAssembly}.ServerAPI"));

builder.Services.AddMsalAuthentication(options =>
{
    builder.Configuration.Bind("AzureAdB2C", options.ProviderOptions.Authentication);
    options.ProviderOptions.DefaultAccessTokenScopes.Add("https://{myproject}.onmicrosoft.com/e3b857b7-df50-4633-ae02-df4d4b20e911/API.Access openid offline_access");
});
1

1 Answers

2
votes

If you want to make outgoing requests to URIs that aren't within the app's base URI, you can create a custom AuthorizationMessageHandler class to implement it. For more details, please refer to here

For example

Create Custom AuthorizationMessageHandler class

using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;

public class CustomAuthorizationMessageHandler : AuthorizationMessageHandler
{
    public CustomAuthorizationMessageHandler(IAccessTokenProvider provider,
        NavigationManager navigationManager)
        : base(provider, navigationManager)
    {
        ConfigureHandler(
            authorizedUrls: new[] { "https://localhost:44389/" },
            scopes: new[] { "https://<>.onmicrosoft.com/api/user_impersonation" });
    }
}

Add the following code in Program.cs.

using System;
using System.Net.Http;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Text;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

namespace WebB2C
{
    public class Program
    {
        public static async Task Main(string[] args)
        {
            var builder = WebAssemblyHostBuilder.CreateDefault(args);
            builder.RootComponents.Add<App>("app");
          
            builder.Services.AddScoped<CustomAuthorizationMessageHandler>();
            builder.Services.AddHttpClient("ServerAPI", client =>
              client.BaseAddress = new Uri("https://localhost:44389/"))
                    .AddHttpMessageHandler<CustomAuthorizationMessageHandler>();
            builder.Services.AddScoped(sp => sp.GetRequiredService<IHttpClientFactory>()
             .CreateClient("ServerAPI"));

            builder.Services.AddMsalAuthentication(options =>
            {
                builder.Configuration.Bind("AzureAdB2C", options.ProviderOptions.Authentication);
                options.ProviderOptions.DefaultAccessTokenScopes.Add("https://<>.onmicrosoft.com/api/user_impersonation");
                options.ProviderOptions.DefaultAccessTokenScopes.Add("openid");
                options.ProviderOptions.DefaultAccessTokenScopes.Add("offline_access");
            });

            await builder.Build().RunAsync();
        }
    }
}