AzureAD, Client confidential app calling webapi with a custom Application ID URI, returns 401

Maccari Fabio 21 Reputation points
2021-07-18T06:36:42.773+00:00

I'm trying to develop an API which can be called from different web apps (both in client confidential or with the user token).

If I call the api with a client confidential app, using the default scope (api://[APIclientId]/.default), everything works.

But If I specify a custom Application ID URI for the API app registration (like: api://myapi.iss.it), and I set the scope to api://myapi.iss.it/.default, I get HTTP401 from the webapp.

This is the method to retrieve the token for the webapp to call the api:

private async Task PrepareAuthenticatedClient()
    {
        IConfidentialClientApplication app;
        string AURY = String.Format(CultureInfo.InvariantCulture, _config["AzureAd:Instance"] + "{0}", _config["AzureAd:TenantId"]);
        app = ConfidentialClientApplicationBuilder.Create(_config["AzureAd:ClientId"])
            .WithClientSecret(_config["AzureAd:ClientSecret"])
            .WithAuthority(new Uri(AURY))
            .Build();
        var accessToken = await app.AcquireTokenForClient(new string[] { _config["API:scope"] }).ExecuteAsync();
        Console.WriteLine("token: " + accessToken.AccessToken);
        //var accessToken = await _tokenAcquisition.GetAccessTokenForAppAsync(_TodoListScope);
        _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken.AccessToken);
        _httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    }

I notice that the Audience is still api://[APIclientId] in the token, even if I set the api:scope to api://myapi.iss.it/.default

Is it correct? any idea what could be the problem?

ASP.NET Core
ASP.NET Core
A set of technologies in the .NET Framework for building web applications and XML web services.
4,560 questions
Microsoft Entra ID
Microsoft Entra ID
A Microsoft Entra identity service that provides identity management and access control capabilities. Replaces Azure Active Directory.
21,793 questions
{count} votes

Accepted answer
  1. Tiny Wang-MSFT 2,646 Reputation points Microsoft Vendor
    2021-07-19T10:22:36.96+00:00

    Hi, @Maccari Fabio in my opinion, your token is correct and the issue should come from your api validation. According to this section, after enabling bearer token validation in your api program, aud claim will be validated at first. Hence we need to set Audience in appsettings.json. Here I set up a asp.net core mvc program to test it. It worked well and please refer to my code snippet below:

    appsettings.json need to add these:

    "AzureAd": {  
        "Instance": "https://login.microsoftonline.com/",  
        "ClientId": "2c0e06_xxxxxxx_df157",  
        "Domain": "tenant_name.onmicrosoft.com",   
        "TenantId": "common",  
        "Audience": "client_id_that_expose_api"//you can get it by decoding access token and the aud claim  
      }  
    

    StartUp.cs need to modify ConfigurationServices and Configure

    public void ConfigureServices(IServiceCollection services)  
            {  
                services.AddMicrosoftIdentityWebApiAuthentication(Configuration);  
                services.AddControllersWithViews();  
            }  
      
    app.UseRouting();  
                // adding next 2 lines in Configure method  
                app.UseAuthentication();  
                app.UseAuthorization();  
      
                app.UseEndpoints(endpoints =>  
                {  
                    endpoints.MapControllerRoute(  
                        name: "default",  
                        pattern: "{controller=Home}/{action=Index}/{id?}");  
                });  
    

    And this is my controller:

    using Microsoft.AspNetCore.Authorization;  
    using Microsoft.AspNetCore.Mvc;  
    using Microsoft.Identity.Web.Resource;  
    using WebApplication1.Models;  
      
    namespace WebApplication1.Controllers  
    {  
        [Authorize]  
        public class HelloController : Controller  
        {  
            public IActionResult Index()  
            {  
                HttpContext.ValidateAppRole("Tiny.Read");  
                Student stu = new Student();  
                stu.age = 18;  
                return Json(stu) ;  
            }  
        }  
    }  
    

    This is my testing result:

    115856-image.png


    If the answer is helpful, please click "Accept Answer" and upvote it.
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.
    Best Regards,
    TinyWang

    2 people found this answer helpful.

0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.