Home > front end >  Error while validating the service descriptor
Error while validating the service descriptor

Time:12-29


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.

CodePudding user response:

This error means that PolicyAuthorizationHandler class depends on a service of type IHttpContextAccessor, but that service is not registered in the service container.

you need to register IHttpContextAccessor in ConfigureServices by adding line services.AddHttpContextAccessor();

and after this, you can pass IHttpContextAccessor to the constructor of PolicyAuthorizationHandler `

  •  Tags:  
  • c#
  • Related