0

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

ikenahim
  • 331
  • 1
  • 3
  • 15
  • You could possibly help us help you by figuring out how far through Main() you get before the crash occurs. I don't have knowledge of this code environment, but you should step through it if you're able, otherwise delete code from the end of Main() backwards until it doesn't crash, and then you know the code you most recently deleted was where it crashed. – Aiken Drum Apr 22 '21 at 22:53
  • I added more description to the whole picture and work flow im trying to achieve. – ikenahim Apr 23 '21 at 11:56
  • Use https://jwt.ms/ to parse the access token and provide a screenshot. – Carl Zhao Apr 28 '21 at 07:36
  • I cant see where the token is been send to the Api. the `data = await Http.GetFromJsonAsync(@"API-url--runs-locally-on-docker");` does that automatically somehow – ikenahim Apr 28 '21 at 07:38
  • Can you provide a screenshot of Expose an API of the api application? By the way, you also need to add the client application to the api. https://i.stack.imgur.com/tG0co.png – Carl Zhao Apr 28 '21 at 07:47
  • Oh I haven't added the client app to the Api. let me try this first – ikenahim Apr 28 '21 at 08:01
  • I update the question with token screenshot and also expose api tab, the client app still return 401 :/ – ikenahim Apr 28 '21 at 08:12

1 Answers1

1

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

Carl Zhao
  • 8,543
  • 2
  • 11
  • 19
  • Im lost here, can you please explain more? I defined scope in Api and that scope is used by the client application. what is wrong here? – ikenahim Apr 28 '21 at 09:27
  • @ikenahim The `scope` is only granted to the client application by you, and it will be displayed in the token. – Carl Zhao Apr 28 '21 at 09:31
  • @ikenahim Try it out according to my method and see how it turns out. – Carl Zhao Apr 28 '21 at 09:35
  • I created scope `AccessApi` in the Api and expose this scope, and the client application use this scope. I still dont understand you :/. – ikenahim Apr 28 '21 at 09:36
  • Do you mean the scope has be created in the client application ? not at the API? – ikenahim Apr 28 '21 at 09:37
  • @ikenahim This `scope` is similar to the permissions of ms graph api. If you want to access the graph api, you need to grant permissions to the application. The truth is the same. – Carl Zhao Apr 28 '21 at 09:44
  • I attached a screenshot of the API permission for client app - as you can see i already give grant permission to the client app to use API scope `AccessApi` , im not sure if this what you mean – ikenahim Apr 28 '21 at 09:49
  • @ikenahim This is exactly what I mean. see: https://stackoverflow.com/questions/66363001/id-token-from-azure-ad-federation-does-not-contains-roles-claim/66364900#66364900 – Carl Zhao Apr 28 '21 at 09:55
  • @ikenahim see: https://i.stack.imgur.com/Pdczb.png – Carl Zhao Apr 28 '21 at 10:04
  • That exactly my implementation, I think the problem is somewhere else maybe in the config file. – ikenahim Apr 28 '21 at 10:04
  • I figure it out the problem was at `appsettings,json` where I had `clientId` value of client app instead of the clientid of the`Api`. I will test this first to see how the token will be. – ikenahim Apr 28 '21 at 10:09
  • The jwt token has now the clientId of the API instead of clientId of client app, however, I dont see the scope :/ – ikenahim Apr 28 '21 at 10:13
  • @ikenahim It may be that the user or the administrator has not yet consent. – Carl Zhao Apr 28 '21 at 10:17
  • @ikenahim But it doesn't matter, you can use the token to call the api to test it and see if an error is reported. – Carl Zhao Apr 28 '21 at 10:19
  • Im getting different error with `cors policy` tho the api allows any `origin`, I will fix this first and try it. I will mark your question as an answer but i will highlight `apsettings.json` as well as part of the problem. thanks for help :) – ikenahim Apr 28 '21 at 10:28
  • I fixed the `cors` problem, while testing the call to the api the token doesnt have the scope, since the scope doesnt need a `user consent`, do I still need to consent it ? – ikenahim Apr 28 '21 at 10:48
  • Sorry, I just saw the comment, how about it, is the problem solved? – Carl Zhao Apr 29 '21 at 02:06