0

My Azure Web App is calling my Azure API App endpoint. Both app services are in the same Azure subscription and RG. Web App is a .NET Core Web Application and API App is a .NET Core Web API. Web App is using standard HttpClient class to call the API App endpoint.

I followed https://learn.microsoft.com/en-us/azure/app-service/overview-managed-identity?tabs=portal%2Cdotnet and created a user-assigned managed identity. Then assigned this identity to the Azure API App with role as contributor.

Web App still not assigned with the mentioned managed identity, but it can still access this API App without throwing the expected un-authorized error.

My question is that how can I restrict that only this managed identity should access the mentioned API app? code middlweware or some other Azure settings?

1 Answer 1

1

Your API should be receiving a JWT token from your App. You need to configure your API to validate the token and reject ones that don't meet your requirements. You get some basic validation out of the box - the token must pass audience, issuer and signing certificate validation - but if you want to restrict it to a single identity then you need to tell it what that is.

There are a number of ways you can go about this, and Policy based authz is worth a read so you know the the approach (https://learn.microsoft.com/en-us/aspnet/core/security/authorization/policies?view=aspnetcore-6.0).

Your identity will have a unique, immutable identifier, the objectId of the managed identity. This gets transmitted on the subject claim on your JWT token, so you can lock down your API to that identity with a simple global policy

In your API start up where you have an AddAuthorization call, you can add a policy like so

services.AddAuthorization(options =>
{
    options.AddPolicy("OnlyMatchingSubject", policy =>
        policy.RequireAssertion(context => context.User.HasClaim(c =>
            c.Type is ClaimConstants.Sub && c.Value == "your-unique-subject-guid")));

    options.DefaultPolicy = options.GetPolicy("OnlyMatchingSubject");
});

Here, we say that your token must have a sub claim, and it must be a particular value to pass (just get your objectId for your identity from the portal), and then make that the default authentication policy.

Here's a full example for a dotnet 6 minimal API.

using System.Security.Claims;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Identity.Web;

var builder = WebApplication.CreateBuilder(args);

builder.Services
    .AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAd"));

builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("OnlyMatchingSubject", policy =>
        policy.RequireAssertion(context => context.User.HasClaim(MatchesExpectedSubjectClaim())));

    var policy = options.GetPolicy("OnlyMatchingSubject");
    options.DefaultPolicy = policy;
    options.FallbackPolicy = policy;
});

var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();
app.MapGet("/", () => "Hello World!");

app.Run();

Predicate<Claim> MatchesExpectedSubjectClaim()
{
    return c => c.Type is "sub" && c.Value == "your-unique-subject-guid";
}

You'll need to set an AzureAd config in your settings, as per this documentation https://learn.microsoft.com/en-us/azure/active-directory/develop/scenario-protected-web-api-app-configuration#config-file

Sign up to request clarification or add additional context in comments.

3 Comments

Added below lines in Program.cs as I am using .NET 6.0 . still couldn't produce un-authorize error. builder.Services.AddAuthorization(options => { options.AddPolicy("OnlyMatchingSubject", policy => policy.RequireAssertion(context => context.User.HasClaim(c => c.Type is ClaimConstants.Sub && c.Value == "<<objectId of ManagedIdentity>>"))); options.DefaultPolicy = options.GetPolicy("OnlyMatchingSubject"); });1st to see un-authorized error without token .so this.WeatherForecastList = await client.GetFromJsonAsync<List<WeatherForecast>>(apiURL) from web app
Added a working demo for a dotnet 6 minimal API. Run that and put a breakpoint in the predicate, you'll see it evaluating as you make requests.
That's it!! I was missing the additional in AddAuthentication() based on appsettings.json entries. I am closing this ticket as my goal here was to get un-authorize error if no token has passed. Thanks for the help. Now in to access the managed identity token and pass it during REST calls. finger crossed and I will create separate ticket if any issues faced there.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.