Use Azure AD B2C to protect Web API endpoints, official document is out of date

63 Views Asked by At

I am establishing a new project on Azure, I have a backend Web API project and a frontend WebApp project.

I followed this Official Document to create 2 Registered Application under AD B2C one for WebAPI and one for WebApp.

Then when I followed to the Step 3: Initiate the authentication library I found that there is no Startup.cs file in the newly created Asp.NET Core WebAPI project. Even I manually created the Startup.cs and pasted in the ConfigureServices() it errors out. So I am stuck here.

enter image description here

My .NET version is 8.0.200.

Any suggestions from Microsoft team or anyone who had the same issue?


Update 1

I used the code suggested by @AsleshaKantamsetti and then all my endpoints start to fail with Status Code 500

enter image description here


Update 2

I just found that I didn't provide the correct section name in appsettings.json, I then rectified the name and it still errors out with 401.

enter image description here

Here is the Program.cs

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

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApi(options =>
                                {
                                    builder.Configuration.Bind("AzureAd", options);
                                    options.TokenValidationParameters.NameClaimType = ClaimTypes.Name;
                                },
                                options =>
                                {
                                    builder.Configuration.Bind("AzureAd", options);
                                }
    );
//builder.Services.AddMicrosoftIdentityWebApiAuthentication(builder.Configuration.GetSection("AzureAd"));
// End of the Microsoft Identity platform block    

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


builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(c => {
    c.SwaggerDoc("v1", new Microsoft.OpenApi.Models.OpenApiInfo
    {
        Title = "JWTToken_Auth_API",
        Version = " v1"
    });

    c.AddSecurityDefinition("Bearer", new Microsoft.OpenApi.Models.OpenApiSecurityScheme()
    {
        Name = "Authorization",
        Type = Microsoft.OpenApi.Models.SecuritySchemeType.ApiKey,
        Scheme = "Bearer",
        BearerFormat = "JWT",
        In = Microsoft.OpenApi.Models.ParameterLocation.Header,
        Description = "Wahaha"
    });

    c.AddSecurityRequirement(new OpenApiSecurityRequirement {
        {
            new OpenApiSecurityScheme {
                Reference = new OpenApiReference {
                    Type = ReferenceType.SecurityScheme,
                        Id = "Bearer"
                }
            },
            new string[] {}
        }
    });
});

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.UseAuthentication();

app.UseAuthorization();

app.MapControllers();

app.Run();

WeatherForecastController.cs

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Identity.Web.Resource;

namespace MyBackend.Controllers
{
    [Authorize]
    [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 = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
                TemperatureC = Random.Shared.Next(-20, 55),
                Summary = Summaries[Random.Shared.Next(Summaries.Length)]
            })
            .ToArray();
        }
    }
}

appsettings.json and its development version are same:

{
  "AzureAd": {
    "Instance": "https://<mydomain>.b2clogin.com/",
    "Domain": "<mydomain>.onmicrosoft.com",
    "TenantId": "...",
    "ClientId": "...",
    "CallbackPath": "/signin-oidc",
    "Scopes": ".default",
    "SignUpSignInPolicyId": "B2C_1_susi",
    "SignedOutCallbackPath": "/signout/B2C_1_susi",
    "ResetPasswordPolicyId": "b2c_1_reset",
    "EditProfilePolicyId": "b2c_1_edit_profile",
    "EnablePiiLogging": true
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*"
}
1

There are 1 best solutions below

3
Aslesha Kantamsetti On

In .NET 8, ASP.NET Web API Core does not have a Startup.cs file. Therefore, you can add the following configuration code in the Program.cs file.

Code:

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
          .AddMicrosoftIdentityWebApi(options =>
          {
              builder.Configuration.Bind("AzureAdB2C", options);
           options.TokenValidationParameters.NameClaimType = "name";
          },
  options => { builder.Configuration.Bind("AzureAdB2C", options); });