Search code examples
iisasp.net-core-webapi.net-6.0blazor-server-sidewindows-authentication

Unauthorized error web api windows authentication


I have Blazor Server & Web API inside the same project. I'm able to call the Web API inside my project on my laptop, but I get an unauthorized error after I deployed it to the web server; I'm using Windows authentication. I've also called the Web API using Postman with the same unauthorized result on the server. Here are the relevant codes:

File: Program.cs

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddAuthentication(NegotiateDefaults.AuthenticationScheme).AddNegotiate();
builder.Services.AddAuthorization(o => { o.FallbackPolicy = o.DefaultPolicy; });

var config = builder.Configuration;
builder.Services.AddDbContext<AppCtx>(o => o.UseSqlServer(config.GetConnectionString("APP")));

builder.Services.AddMvc();
builder.Services.AddServerSideBlazor();

string baseUrl = config.GetValue<string>("AppSettings:BaseUrl");
builder.Services.AddHttpClient<IAdminService, AdminService>(client =>
{
    client.BaseAddress = new Uri(baseUrl);
})
.ConfigurePrimaryHttpMessageHandler(() =>
    new HttpClientHandler()
    {
        UseDefaultCredentials = true,
        Credentials = System.Net.CredentialCache.DefaultCredentials,
        AllowAutoRedirect = true
    });

var app = builder.Build();

string pathBase = config.GetValue<string>("AppSettings:PathBase");
app.UsePathBase(pathBase);

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/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.UseStatusCodePages();
app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthentication();
app.UseAuthorization();

app.MapControllers();
app.MapBlazorHub();
app.MapFallbackToPage("/_Host");

app.Run();

File: AdminController.cs

[AllowAnonymous]
[ApiController]
[Route("[controller]/[action]")]
public class AdminController : ControllerBase
{
    private readonly AppCtx appCtx;

    public AdminController(AppCtx appCtx)
    {
        this.appCtx = appCtx;
    }

    public async Task<IEnumerable<LocationDto>> Locations(string locs)
    {
        var prm = new SqlParameter("@locs", SqlDbType.VarChar, 1024);
        prm.Value = locs;

        string sSql = "EXEC [dbo].[uspLW300_Offices] @locs";
        return await appCtx.SqlQueryAsync<LocationDto>(sSql, prm);
    }
}

Here's the error I'm seeing in the browser's Developer tools. I've copied the "html" part into a separate file so that it can be easily viewed.

enter image description here

enter image description here

Another view of the error from Postman: enter image description here


Solution

  • There were two settings I made in IIS in order to allow the Web API to work. One in the application pool, the other in the website.

    In the application pool, I change the Identity to use a custom account instead of using one of the built-in accounts. enter image description here

    In the website, I enabled the Anonymous Authentication. I also enabled the Windows Authentication since I need the user id in one of the razor components.

    enter image description here

    Per MS doc: When Windows Authentication is enabled and anonymous access is disabled, the [Authorize] and [AllowAnonymous] attributes have no effect.

    [Updated: 12/12/2022] I was able to use the default built-in Application Pool Identity (ApplicationPoolIdentity), after I made the following change:

    app.MapControllers().AllowAnonymous();