'Web API with Microsoft Identity Platform Authentication

I created a new ASP.NET Core Web API with Authentication type "Microsoft identity platform" based on the VS2022 template.

On Azure I setup the following with my trial subscription (where I am global administrator):

  • Create app API
  • Create app registration

To doublecheck if the app is running, I also added a TestController, which returns a simple string.

After setting up azure, I changed the appsettings.json file accordingly:

"AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "Domain": "[xxx]",
    "TenantId": "[xxx]",
    "ClientId": "[xxx]",
    "Scopes": "access_as_user",
    "CallbackPath": "/signin-oidc"
  },

Everything else is setup nicely already in the program.cs (I only extracted relevant code for you):

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAd"));
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();

After that I setup a YAML Pipeline on Azure Devops to deploy the API directly to the cloud.

The deployment seems to work: I can access the function of the TestController. However, when I try to access the weatherforecast I receive the Status Code (I try this with the global admin user):

401 Unauthorized

What have I tried so far?

  • I added user to Access Control (IAM) Contributor (For testing) both of the subscription and the app service itself (i.e. the App Api)

Note, the WeatherForecastController of the template looks like the following:

[ApiController]
[Route("[controller]")]
[RequiredScope(RequiredScopesConfigurationKey = "AzureAd:Scopes")]
public class WeatherForecastController : ControllerBase
{
    private static readonly string[] Summaries = new[]
    {
    "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};

    private readonly ILogger<WeatherForecastController> _logger;

    public WeatherForecastController(ILogger<WeatherForecastController> logger)
    {
        _logger = logger;
    }

    [HttpGet(Name = "GetWeatherForecast")]
    public IEnumerable<WeatherForecast> Get()
    {
        return Enumerable.Range(1, 5).Select(index => new WeatherForecast
        {
            Date = DateTime.Now.AddDays(index),
            TemperatureC = Random.Shared.Next(-20, 55),
            Summary = Summaries[Random.Shared.Next(Summaries.Length)]
        })
        .ToArray();
    }
}

Any ideas of what I am missing here or what I could check on Azure to narrow down the problem?



Solution 1:[1]

Please check if you are missing controller with the [Authorize] attribute. To protect an ASP.NET or ASP.NET Core web API, you must add the [Authorize] attribute to one of the following items:

1.The controller itself if you want all controller actions to be protected.

  1. The individual controller action for your API
    [Route("api/[controller]")]
    [ApiController]
    [Authorize]
    [RequiredScope(RequiredScopesConfigurationKey = "AzureAd:Scopes")]
    public class WeatherForecastController : ControllerBase
    {

After login , check the received token in browser in https://jwt.io and decode it and see which endpoint is present in issuer (“iss” claim) i.e v1 or v2 and then go to azure ad portal and change the accesstokenacceptedversion if it not according to that endpoint i.e; it must be null or 1 for V1 and 2 for V2.

enter image description here

If it is correct , please make the required scopes are exposed for that api In portal .

enter image description here

and make sure required api permissions are given and granted admin consent .

enter image description here

  • Make sure to check mark id token and access token in authentication blade.
  • when you generate a token, it should have the scope like api://clientid_of_the_app_exposed_api/access_as_user which can match the configuration in your code.

After trying above , still if there is error ,please check if audience = client id value, if not change clientId in appsettings by adding prefix api:// before client id. i.e clientId=api://<clientId>

References:

  1. Protected web API
  2. Protected web API: Verify scopes and app roles

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 kavyasaraboju-MT