Reputation: 13
I am attempting to create a custom authorization policy for ASP.NET Core 6 MVC, but I cannot seem to get the requirement to evaluate. Here is the auth handler along with the requirement and the HandleRequirementAsync
method.
The log message in
HandleRequirementAsync ("Reached this point, evaluating requirements")
is never printed.
public class DpAuthRequirement : IAuthorizationRequirement { }
public class DpAuthHandler : AuthorizationHandler<DpAuthRequirement>
{
private readonly ILogger<DpAuthHandler> _logger;
private readonly site_masterContext _context;
public DpAuthHandler(site_masterContext context, ILogger<DpAuthHandler> logger)
{
_context = context;
_logger = logger;
_logger.LogInformation("Created auth handler"); //this is printed in the log
}
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, DpAuthRequirement requirement)
{
_logger.LogInformation("Reached this point, evaluating requirements"); //this is NOT printed
context.Fail();
return Task.CompletedTask;
}
}
Here is the Program.cs
:
public class Program
{
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAuthorization(options =>
{
options.AddPolicy("DpAuthRequirement", policy =>
{
policy.Requirements.Add(new DpAuthRequirement());
});
});
// cookies and session data
builder.Services.AddDistributedMemoryCache();
builder.Services.AddSession(options =>
{
//timeout currently set to 9 minutes
options.IdleTimeout = TimeSpan.FromSeconds(520);
options.Cookie.HttpOnly = true;
options.Cookie.IsEssential = true;
});
var logger = LoggerFactory.Create(config =>
{
config.AddConsole();
config.AddDebug();
config.AddAzureWebAppDiagnostics();
}).CreateLogger<Program>();
builder.Services.AddDbContext<site_masterContext>(options => options.UseSqlServer(Environment.GetEnvironmentVariable("SQLCONNSTR_MASTER_DB")));
builder.Services.AddScoped<site_masterContext>();
builder.Services.AddScoped<IAuthorizationHandler, DpAuthHandler>();
builder.Services.AddHttpContextAccessor();
// logging
#region LOGS
if (Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") != "Production")
{
builder.Logging.ClearProviders();
builder.Logging.AddConsole();
builder.Logging.AddDebug();
builder.Logging.AddAzureWebAppDiagnostics();
}
#endregion
JwtSecurityTokenHandler.DefaultMapInboundClaims = false;
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(builder.Configuration)
.EnableTokenAcquisitionToCallDownstreamApi()
.AddInMemoryTokenCaches();
builder.Services.AddControllersWithViews(options =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
options.Filters.Add(new AuthorizeFilter(policy));
}).AddMicrosoftIdentityUI();
var app = builder.Build();
app.UseSession();
string pattern = "{controller=Home}/{action=Index}/{id?}";
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
app.MapControllerRoute(
name: "default",
pattern: pattern);
}
else
{
app.MapControllerRoute(
name: "default",
pattern: pattern).AllowAnonymous();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.Run();
}
}
And finally, the controller has this:
[Authorize(Policy = "DpAuthRequirement")]
public class HomeController : Controller
{
// ....
}
I am expecting the requirement to evaluate and fail. But the code is never reached and the requirement always succeeds, loading the page just fine regardless of what I try. What am I missing?
Upvotes: 0
Views: 57
Reputation: 22409
I am expecting the requirement to evaluate and fail. But the code is never reached and the requirement always succeeds, loading the page just fine regardless of what I try. What am I missing?
Based on your shared code snippet and scenario I have tried to troubleshoot your implementation.
According to my investigation, it looks like you've set up most of the components correctly.
I have tried your code and it seems HandleRequirementAsync
has been executed as expected.
So I have noticed you have used OpenIdConnectDefaults.AuthenticationScheme
, I am not sure if your configuration is correct. I don't have the environment to verify OpenIdConnectDefaults
.
Therefore, I have used builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
which is the default authentication schema.
And rest of the code I have used as as yours and I was able to execute DpAuthRequirement
policy handler.
Here is my program.cs:
builder.Services.AddScoped<IAuthorizationHandler, DpAuthHandler>(); builder.Services.AddHttpContextAccessor()
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAuthorization(options =>
{
options.AddPolicy("DpAuthRequirement", policy =>
{
policy.Requirements.Add(new DpAuthRequirement());
});
});
//My DbConnection
/*
My Service reference DI
*/
builder.Services.AddScoped<IAuthorizationHandler, DpAuthHandler>();
builder.Services.AddHttpContextAccessor();
// Setting my default authentication scheme
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
options.LoginPath = "/Account/Login";
options.AccessDeniedPath = "/Account/AccessDenied";
});
builder.Services.AddControllersWithViews(options =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
options.Filters.Add(new AuthorizeFilter(policy));
});
var app = builder.Build();
Output:
Note: I think, DpAuthRequirement
has no issue, your program.cs is correct, so my concern is if you have configured your OpenIdConnectDefaults
stuff accordingly. Apart from that your environment conditional (!app.Environment.IsDevelopment()
) which I have get rid while I was testing might also cuase the issue . I would recommend, you to check this official document.
Upvotes: 0