Search code examples
c#asp.net-core.net-coreautofac

JwtSecurityTokenHandler not registered in IoC


I have the following code in asp.net core 2.2:

public class JwtTokenManager : IJwtTokenManager
{
    private readonly JwtBearerSettings jwtBearerSettings;
    private readonly JwtSecurityTokenHandler jwtSecurityTokenHandler;

    public JwtTokenManager(IOptions<JwtBearerSettings> options,
                            JwtSecurityTokenHandler jwtSecurityTokenHandler)
    {
        this.jwtSecurityTokenHandler = jwtSecurityTokenHandler;
        jwtBearerSettings = options.Value;
    }

When I try to run the project I get the following error:

Autofac.Core.DependencyResolutionException: None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'IdentityTemplate.Infrastructure.Security.Jwt.JwtTokenManager' can be invoked with the available services and parameters:
Cannot resolve parameter 'System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler jwtSecurityTokenHandler' of constructor 'Void .ctor(Microsoft.AspNetCore.Identity.UserManager`1[IdentityTemplate.Domain.Users.CustomUser], Microsoft.Extensions.Options.IOptions`1[IdentityTemplate.Infrastructure.Security.Jwt.JwtBearerSettings], System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler)'.

Does anyone know how can I register the JwtSecurityTokenHandler?

Update (Added startup.cs)

public class Startup
{
    public IConfiguration Configuration { get; }

    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public void ConfigureServices(IServiceCollection services)
    {
        services.Configure<AppSettings>(Configuration.GetSection("App"));
        services.Configure<JwtBearerSettings>(Configuration.GetSection("JwtBearerSettings"));
        services.Configure<EmailSettings>(Configuration.GetSection("EmailSettings"));

        services.AddDefaultIdentity<CustomUser>(config =>
                    {
                        config.SignIn.RequireConfirmedEmail = true;
                    })
                .AddRoles<RoleExtended>()
                .AddEntityFrameworkStores<MyDbContext>()
                .AddDefaultTokenProviders();

        // ===== Add Jwt Authentication ========
        JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); // => remove default claims
        services.AddAuthentication(options =>
                    {
                        options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                        options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
                        options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;

                    })
                .AddJwtBearer(cfg =>
                    {
                        cfg.RequireHttpsMetadata = false;
                        cfg.SaveToken = true;
                        cfg.TokenValidationParameters = new TokenValidationParameters
                        {
                            ValidIssuer = Configuration["JwtBearerSettings:Issuer"],
                            ValidAudience = Configuration["JwtBearerSettings:Issuer"],
                            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["JwtBearerSettings:SecurityKey"])),
                            ClockSkew = TimeSpan.Zero // remove delay of token when expire
                        };
                    });


        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);


        services.AddHttpClient();

        services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());

        // Register the Swagger generator, defining 1 or more Swagger documents
        services.AddSwaggerGen(c =>
        {
            c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
        });
    }

    public void ConfigureContainer(ContainerBuilder builder)
    {
        BootstrapConfig.Register(builder);
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Error");
        }

        app.UseAuthentication();

        app.UseStaticFiles();
        app.UseMvc(routes =>
        {
            routes.MapRoute("default", "{controller}/{action}/{id?}");
        });

        // Enable middleware to serve generated Swagger as a JSON endpoint.
        app.UseSwagger();

        // Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.),
        // specifying the Swagger JSON endpoint.
        app.UseSwaggerUI(c =>
        {
            c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
        });


        loggerFactory.AddLog4Net();
    }

Solution

  • The AddJwtBearer registers Authentication Scheme for Jwt authorization not more not less. if you want to inject JwtSecurityTokenHandler in your class for testing case, just register it in asp.net core built-in container into ConfigureService method otherwise you can new it directly.

    services.AddScoped<JwtSecurityTokenHandler>();