Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Injecting SignInManager and AspNetUserManager to Middleware in Asp.Net Core 2

I am attempting to inject SignInManager<ApplicationUser> and AspNetUserManager<ApplicationUser> into my Refresh Token middleware for my WebApi. Just to not I am using Identity, so the my ApplicationUser class is

public class ApplicationUser : IdentityUser<int>, IEntity

In my Middleware constructor I have;

private readonly AuthService _service;

public TokenProviderMiddleware(
    RequestDelegate next, 
    Func<IMyDataContext> context,
    SignInManager<ApplicationUser> signInManager,
    AspNetUserManager<ApplicationUser> userManager)
{
    _next = next;

    _serializerSettings = new JsonSerializerSettings
    {
        Formatting = Formatting.Indented
    };

    _service = new AuthService(context, signInManager, userManager);
}

An in my Startup.cs I have the following;

public void ConfigureServices(IServiceCollection services)
{
        services.AddDbContext<MyDataContext>(
            options => options.UseSqlServer(DbGlobals.DevDatabase));

        services.AddTransient<IMyDataContext, MyDataContext>();
        services.AddTransient<Func<IMyDataContext>>(provider => () => provider.GetService<IMyDataContext>());

        services.AddIdentity<ApplicationUser, ApplicationRole>()
        .AddEntityFrameworkStores<BemfeitoDataContext>()
        .AddDefaultTokenProviders();

        services.Configure<IdentityOptions>(options =>
        {
            // Password settings
            options.Password.RequireDigit = true;
            options.Password.RequiredLength = 8;
            options.Password.RequireNonAlphanumeric = false;
            options.Password.RequireUppercase = true;
            options.Password.RequireLowercase = false;
            options.Password.RequiredUniqueChars = 6;

            // Lockout settings
            options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(30);
            options.Lockout.MaxFailedAccessAttempts = 10;
            options.Lockout.AllowedForNewUsers = true;

            // User settings
            options.User.RequireUniqueEmail = true;
        });

        // Configure JwtIssuerOptions
        services.Configure<JwtIssuerOptions>(options =>
        {
            options.Issuer = JwtSettings.Issuer;
            options.Audience = JwtSettings.Audience;
            options.SigningCredentials = new SigningCredentials(_signingKey, SecurityAlgorithms.HmacSha256);
        });

        var tokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidIssuer = JwtSettings.Issuer,

            ValidateAudience = true,
            ValidAudience = JwtSettings.Audience,

            ValidateIssuerSigningKey = true,
            IssuerSigningKey = _signingKey,

            RequireExpirationTime = false,
            ValidateLifetime = true,
            ClockSkew = TimeSpan.Zero
        };

        services.AddAuthentication(options =>
        {
             options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
             options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
         })
         .AddJwtBearer(configureOptions =>
         {
             configureOptions.ClaimsIssuer = JwtSettings.Issuer;
             configureOptions.TokenValidationParameters = tokenValidationParameters;
             configureOptions.SaveToken = true;
             configureOptions.Events = new JwtBearerEvents
             {
                 OnAuthenticationFailed = context =>
                 {
                     Console.WriteLine("OnAuthenticationFailed: " +
                        context.Exception.Message);
                        return Task.CompletedTask;
                 },
                 OnTokenValidated = context =>
                 {
                     Console.WriteLine("OnTokenValidated: " +
                        context.SecurityToken);
                        return Task.CompletedTask;
                 }
            };
        });

            // api user claim policy
            services.AddAuthorization(options =>
            {
                options.AddPolicy("ApiUser", policy => policy.RequireClaim(JwtClaimIdentifiers.Rol, JwtClaims.ApiAccess));
            });

            services.AddMvc();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseHttpErrorHandlerMiddleware();

            app.UseTokenProviderMiddleware();
            app.UseRefreshTokenProviderMiddleware();
            app.UseAuthentication();

            app.UseMvc();

        }

When I run this I receive the following error;

InvalidOperationException: Cannot resolve scoped service 'Microsoft.AspNetCore.Identity.SignInManager`1[ApplicationUser]' from root provider.

I have tried adding the following Transients;

        services.AddTransient<IUserStore<ApplicationUser>, UserStore<ApplicationUser, ApplicationRole, MyDataContext, int>>();
        services.AddTransient<SignInManager<ApplicationUser>>();
        services.AddTransient<UserManager<ApplicationUser>>();

But I seem to be going down a rabbit hole of injecting dependencies as it is now requesting UserStore be injected as well? Is there an easier way I missing to inject these services?

like image 614
Matthew Flynn Avatar asked Mar 19 '18 09:03

Matthew Flynn


People also ask

Can we add custom middleware in the ASP NET Core Application?

Thus, we can add custom middleware in the ASP.NET Core application. Want to check how much you know ASP.NET Core?

How to inject services into a view in ASP NET Core?

Dependency injection into views in ASP.NET Core 1 A Simple Example. You can inject a service into a view using the @inject directive. 2 Populating Lookup Data. View injection can be useful to populate options in UI elements,... 3 Overriding Services. In addition to injecting new services, this technique can also be used...

What is dependency injection in ASP NET Core?

ASP. NET Core ASP.NET Core supports dependency injection into views. This can be useful for view-specific services, such as localization or data required only for populating view elements. Most of the data views display should be passed in from the controller.

Does everything still apply to ASP NET Core 2?

EDIT (2017-12-21): I reviewed this post to make sure everything still applies to ASP.NET Core 2.0 – and it does. There were no breaking changes in this area between 1.0 and 2.0. So, first, what is a middleware?


1 Answers

There may be an easier way for you to access these services inside your middleware. Consider the following approach, instead of trying to inject the SignInManager signInManager and AspNetUserManager userManager into your middleware directly, inject an Microsoft.AspNetCore.Http.IHttpContextAccessor _httpContextAccessor

Then you can use the _httpContextAccessor to access the signInManager and userManager services like so:

var userManager = _httpContextAccessor.HttpContext.RequestServices.GetService<AspNetUserManager<ApplicationUser>>();
var signInManager = _httpContextAccessor.HttpContext.RequestServices.GetService<SignInManager<ApplicationUser>>();

Also make sure your middleware class has the following using statement: using Microsoft.Extensions.DependencyInjection;

like image 122
Thrillseeker419 Avatar answered Sep 28 '22 03:09

Thrillseeker419