ikenahim
ikenahim

Reputation: 351

WebAssembly Razor client app return 401 while calling a protected API in Azure with Admin Role

I have API protected by Azure AD where Authentication is required to get access data, where I expose the API with only one simple scope for now.

The API and client app both are registered in Azure AD. Roles are also configured for the API, only a a user with Admin role can call my API.

Do I need to assign this Admin role as well to the client App? or AccessApi scope is enough?

Scopes  Who can consent     Admin consent display name     User consent display name   State 

api://xx  User              AccessApi                      AccessApi                 Enable

And a client application build using webassembly blazor also registered in Azure AD, and its configured with Api permission to use delegated access to AccessApi.

API / Permissions name  Type       Description   Admin consent required    Status
myApi (1)   

AccessApi              Delegated     AccessApi              No

I configured webassembly blazor client application to authenticate against azure and get token and use that token to call myApi, however I keep getting loading but no data is being displayed without any error.

Im not sure what went wrong here ?

program class of client application:

 private static string scope = @"api://xxx/AccessApi";

...

            var builder = WebAssemblyHostBuilder.CreateDefault(args);
            builder.RootComponents.Add<App>("app");


            builder.Services.AddScoped<GraphAPIAuthorizationMessageHandler>();

            builder.Services.AddHttpClient("ServerAPI",
                client => client.BaseAddress = new Uri("https://localhost:44314"))
                .AddHttpMessageHandler<GraphAPIAuthorizationMessageHandler>();

            builder.Services.AddScoped(sp => sp.GetRequiredService<IHttpClientFactory>()
                .CreateClient("ServerAPI"));

            builder.Services.AddMsalAuthentication(options =>
            {
                builder.Configuration.Bind("AzureAd", options.ProviderOptions.Authentication);
                options.ProviderOptions.DefaultAccessTokenScopes.Add(scope);
            });

At fetch data razor page I imported all necessary libraries

@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@inject IAccessTokenProvider TokenProvider
@attribute [Authorize]

@inject NavigationManager UriHelper
@inject HttpClient Http

...

data = await Http.GetFromJsonAsync<data[]>(@"API-url--runs-locally-on-docker");

The authorization message handler class

 private static string scope = @"api://xxx/AccessApi";
    public GraphAPIAuthorizationMessageHandler(IAccessTokenProvider provider,
        NavigationManager navigationManager)
        : base(provider, navigationManager)
    {
        ConfigureHandler(
            authorizedUrls: new[] { "https://localhost:44314" },
            scopes: new[] { scope });
    }

After authenticated myself with Azure AD account, the client app shows loading.. but no data is being displayed. at the console level shows this error.

Failed to load resource: the server responded with a status of 401 (Unauthorized)

I followed Microsoft documentation and I'm not sure what I'm missing here. what could be wrong here ?

Update

The Api expose tab: enter image description here

Api permission for the client app: enter image description here

Upvotes: 0

Views: 403

Answers (1)

Carl Zhao
Carl Zhao

Reputation: 9569

Obviously, your scope is set incorrectly. You should set the scope to the client id of the api application instead of the client id of the client application. In your question, I think your scope should be: api://7b4d6df9-63cd-4ed7-881bxxx/AccessApi.

Parse the token and you should see scp claim and roles claim.

enter image description here

Upvotes: 1

Related Questions