I am trying to add a handler to my services in Startup.cs. Doing this will give me the following error:
Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: Microsoft.AspNetCore.Authorization.IAuthorizationService Lifetime: Transient ImplementationType: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService': Unable to resolve service for type 'Microsoft.AspNetCore.Http.IHttpContextAccessor' while attempting to activate 'ApiPortal.Classes.PolicyAuthorizationHandler')
Here is my Startup.cs ConfigureServices:
public void ConfigureServices(IServiceCollection services) { services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd")); services.Configure<OpenIdConnectOptions>("azure", options => { var existingOnTokenValidatedHandler = options.Events.OnTokenValidated; options.Events.OnTokenValidated = async context => { await existingOnTokenValidatedHandler(context); await context.HttpContext.SignInAsync( CookieAuthenticationDefaults.AuthenticationScheme, context.Principal); }; var existingOnUserInformationReceived = options.Events.OnUserInformationReceived; options.Events.OnUserInformationReceived = async context => { await existingOnUserInformationReceived(context); }; }); services.AddAuthorization(options => { options.AddPolicy("AzureAccount", policy_builder => policy_builder.AddRequirements(new PolicyRequirement())); }); services.AddScoped<IAuthorizationHandler, PolicyAuthorizationHandler>(); services.AddControllersWithViews(options => { var policy = new AuthorizationPolicyBuilder() .RequireAuthenticatedUser() .Build(); options.Filters.Add(new AuthorizeFilter(policy)); }); services.AddRazorPages() .AddMicrosoftIdentityUI(); } Here is my PolicyAuthorizationHandler.cs:
public class PolicyAuthorizationHandler : AuthorizationHandler<PolicyRequirement> { readonly IHttpContextAccessor _contextAccessor; public PolicyAuthorizationHandler(IHttpContextAccessor ca) { _contextAccessor = ca; } protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, PolicyRequirement requirement) { if (context.Resource is AuthorizationFilterContext filterContext) { var area = ""; var controller = (filterContext.RouteData.Values["controller"] as string)?.ToLower(); var action = (filterContext.RouteData.Values["action"] as string)?.ToLower(); var id = ""; if (await requirement.Pass(context, _contextAccessor, area, controller, action, id)) { context.Succeed(requirement); } } if (context.Resource is DefaultHttpContext httpContext) { var area = ""; var controller = httpContext.Request.RouteValues["controller"].ToString(); var action = httpContext.Request.RouteValues["action"].ToString(); var id = ""; if (await requirement.Pass(context, _contextAccessor, area, controller, action, id)) { context.Succeed(requirement); } } } } Here is my PolicyRequirement.cs class:
public class PolicyRequirement : IAuthorizationRequirement { IHttpContextAccessor _contextAccessor; AuthorizationHandlerContext _context; public async Task<bool> Pass(AuthorizationHandlerContext context, IHttpContextAccessor contextAccessor, string area, string controller, string action, string id) { _context = context; _contextAccessor = contextAccessor; bool authorized = false; //authorization logic goes here string email = contextAccessor.HttpContext.User.Identity.Name; if (email == "[email protected]") authorized = true; return await Task.FromResult(authorized); } } I have already tried changing services.AddScoped<IAuthorizationHandler, PolicyAuthorizationHandler>() to services.AddTransient<IAuthorizationHandler, PolicyAuthorizationHandler>() and services.AddSingleton<IAuthorizationHandler, PolicyAuthorizationHandler>(). These don't seem to work.
I have also taken a look at this and this thread, but I can't seem to find a solution for my problem here as well.
What am I doing wrong and what can I do to fix this error? Thanks in advance.