The code below is what I was able to use to get this to work. The only drawback to this solution is that everything must be managed in Azure. This means, roles, users, etc... Which is fine if everyone using your app is in the same organization, but you can't add external users unless you make them part of your Azure AD instance. For now, this works because this is an internal application. However, we do have another application, which is used by external users as will as internal users, and we want to provide the SharePoint access that we have in the other app. There doesn't seem to be a way to connect an Azure AD account managed in the cloud, with one managed in a local DB. Ideally, we want to authenticate with Azure AD, but we want to Authorize, using identity roles, claims, etc.. at the local DB level. I think for that, we will need to use a Managed Identity.
However, this code will work for an internal application. If I'm wrong, please show me where I'm wrong.
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.Authorization
using Microsoft.AspNetCore.Mvc.Authorization;
using Microsoft.AspNetCore.Rewrite;
using Microsoft.EntityFrameworkCore;
using Microsoft.Identity.Web;
using Microsoft.Identity.Web.UI;
var builder = WebApplication.CreateBuilder(args);
var initialScopes = builder.Configuration["DownstreamApi:Scopes"]?.Split(' ') ?? builder.Configuration["MicrosoftGraph:Scopes"]?.Split(' ');
builder.Services.AddDbContext<InvoiceAuditingContext>(options =>
options.UseSqlServer(
builder.Configuration.GetConnectionString("DefaultConnection")));
//builder.Services.AddDatabaseDeveloperPageExceptionFilter();
// Add services to the container.
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"))
.EnableTokenAcquisitionToCallDownstreamApi(initialScopes)
.AddMicrosoftGraph(builder.Configuration.GetSection("MicrosoftGraph"))
.AddInMemoryTokenCaches();
builder.Services.AddAuthorization(options =>
{
options.FallbackPolicy = options.DefaultPolicy;
});
#region Interfaces
builder.Services.AddScoped<IIARepo, IARepo>();
#region IA
builder.Services.AddTransient<IIAObservationLogProvider, IAObservationLogProvider>();
builder.Services.AddTransient<IIADataImportExportProvider, IADataImportExportProvider>();
#endregion
#region Global
builder.Services.AddTransient<IImportColumnProvider, ImportColumnProvider>();
#endregion
#region CB Components
//Excel
builder.Services.AddTransient<IExcelExtensionsProvider, ExcelExtensionsProvider>();
builder.Services.AddTransient<IExcelFileAndSheetValidationProvider, ExcelFileAndSheetValidationProvider>();
builder.Services.AddTransient<IExcelExportProvider, ExcelExportProvider>();
#endregion
#endregion
builder.Services.AddControllersWithViews(options =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
options.Filters.Add(new AuthorizeFilter(policy));
});
builder.Services.AddRazorPages()
.AddMicrosoftIdentityUI();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.MapRazorPages();
app.MapControllers();
app.Run();