Unable to inject IAntiforgery in the startup class

Viewed 592

Need to use IAntiforgery for csrf protection. Was simply trying to inject the service. While doing that I am getting a "Unable to resolve service for type 'Microsoft.AspNetCore.Antiforgery.IAntiforgery' while attempting to activate 'APi.Startup'." error. I am posting the code here. Hopefully, the community will be able to help me here.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using APi.Models;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Antiforgery;
using Microsoft.AspNetCore.Razor.TagHelpers;

 

namespace APi
{
    public class Startup
    {
        IAntiforgery _antiforgery;
        public Startup(IConfiguration configuration,IAntiforgery antiforgery)
        {
            Configuration = configuration;
            _antiforgery = antiforgery;
        }

 

        public IConfiguration Configuration { get; }

 

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllersWithViews();
            services.AddTransient<IAntiforgery>();
            services.AddDbContext<EmployeeContext>(options => 
            options.UseSqlServer(Configuration.GetConnectionString("SQLServerConnection")));
        }

 

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/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.UseHttpsRedirection();
            app.UseStaticFiles();

 

            app.UseRouting();

 

            app.UseAuthorization();

 

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Index}/{id?}");
            });
        }
    }
}
2 Answers

Late to the game but this is how you would do it in 6.0. I've confirmed this works. The good news is that you can still use the Configure constructor in Startup if you like, plugging in the IAntiforgery interface. The difference from 5.0 is that the IAntiforgery interface isn't in the DI, you need to retrieve it from the service collection.

NOTE: If you are using ControllersWithViews you don't need

services.AddAntiforgery(options => { options.HeaderName = "X-XSRF-TOKEN"; options.Cookie.HttpOnly = false; });

because it's automagically added. But this allows us to control the header name. They need to match client and server side.

Program.cs

var services = builder.Services;
// Add services to the container.
services.AddAntiforgery(options => { options.HeaderName = "X-XSRF-TOKEN"; options.Cookie.HttpOnly = false; })
services.AddControllersWithViews();
var startup = new Startup(builder.Configuration);
var antiforgery = app.Services.GetRequiredService<IAntiforgery>();
startup.ConfigureServices(builder.Services);
builder.Services.AddAntiforgery(options => { options.HeaderName = "X-XSRF-TOKEN"; options.Cookie.HttpOnly = false; });
var app = builder.Build();
var antiforgery = app.Services.GetRequiredService<IAntiforgery>();
startup.Configure(app, app.Environment,antiforgery);
app.Run();

Startup.cs

public void Configure(IApplicationBuilder app, IWebHostEnvironment env, 
   IAntiforgery antiforgery)
   {
     app.Use((context, next) =>
     {
         var requestPath = context.Request.Path.Value;

        if (string.Equals(requestPath, "/auth", StringComparison.OrdinalIgnoreCase))
        {
            var tokenSet = antiforgery.GetAndStoreTokens(context);        
            context.Response.Cookies.Append("XSRF-TOKEN", tokenSet.RequestToken!,
            new CookieOptions { HttpOnly = false });
        }

        return next(context);
      });

You can't inject IAntiforgery in startup constructor. Only the following service types can be injected into the Startup constructor when using the Generic Host (IHostBuilder):

  • IWebHostEnvironment
  • IHostEnvironment
  • IConfiguration

Reference

Related