I'm using ASP.NET Core 3.1 with Windows authentication. If I use [Authorize] alone everything is fine, however, if I decorate my controller with [Authorize(Roles = "GlobalAdmin")] authorisation fails.
This happens in both dev on my local, and after deployment on an intranet.
I definitely have the right roles assigned, because the following works fine:
if(await _userManager.IsInRoleAsync(await _userManager.FindByNameAsync(User.Identity.Name), "GlobalAdmin"))
{
return View();
}
But I don't want to have to do this on every method in my controller, and I can't use it in a constructor on a base controller because User.Identity returns null in a constructor.
And using the following, var y shows me my correct roles
var x = await _userManager.FindByNameAsync(User.Identity.Name);
var y = await _userManager.GetRolesAsync(x);
In the past I was able to create a custom override on the Authorize attribute and I did my own role validation in there, but core 3.1 seems to have changed methods so they aren't there to override.
But why doesn't the [Authorize] attribute work for my roles in the first place?
In my startup I have
public void ConfigureServices(IServiceCollection services)
{
services.AddIdentity<IdentityUser, IdentityRole>()
.AddRoleManager<RoleManager<IdentityRole>>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
services.Configure<IdentityOptions>(options =>
{
options.User.AllowedUserNameCharacters =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-.\\";
options.User.RequireUniqueEmail = true;
});
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("MyConnString")));
services.AddControllersWithViews();
}
and
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
//app.UseMiddleware<Helpers.ErrorHandlingMiddleware>();
app.UseDeveloperExceptionPage();
}
else
{
app.UseMiddleware<Helpers.ErrorHandlingMiddleware>();
// 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.UseAuthentication();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
}
The entire stacktrace looks like this:
Win32Exception: The trust relationship between this workstation and the primary domain failed.
System.Security.Principal.NTAccount.TranslateToSids(IdentityReferenceCollection sourceAccounts, out bool someFailed)
System.Security.Principal.NTAccount.Translate(IdentityReferenceCollection sourceAccounts, Type targetType, out bool someFailed)
System.Security.Principal.NTAccount.Translate(IdentityReferenceCollection sourceAccounts, Type targetType, bool forceSuccess)
System.Security.Principal.WindowsPrincipal.IsInRole(string role)
Microsoft.AspNetCore.Authorization.Infrastructure.RolesAuthorizationRequirement+<>c__DisplayClass4_0.b__0(string r)
System.Linq.Enumerable.Any(IEnumerable source, Func<TSource, bool> predicate)
Microsoft.AspNetCore.Authorization.Infrastructure.RolesAuthorizationRequirement.HandleRequirementAsync(AuthorizationHandlerContext context, RolesAuthorizationRequirement requirement)
Microsoft.AspNetCore.Authorization.AuthorizationHandler.HandleAsync(AuthorizationHandlerContext context)
Microsoft.AspNetCore.Authorization.Infrastructure.PassThroughAuthorizationHandler.HandleAsync(AuthorizationHandlerContext context)
Microsoft.AspNetCore.Authorization.DefaultAuthorizationService.AuthorizeAsync(ClaimsPrincipal user, object resource, IEnumerable requirements)
Microsoft.AspNetCore.Authorization.Policy.PolicyEvaluator.AuthorizeAsync(AuthorizationPolicy policy, AuthenticateResult authenticationResult, HttpContext context, object resource)
Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)