Passing ApplicationUserManager to ApplicationOAuthProvider with Autofac with ASP.Net ID

I use the ASP.Net identifier and wanted to add the ApplicationUserManager service to all my user controllers, following this article: How to connect my Autofac container to ASP.NET Identity 2.1

This works fine in my controllers, but not when I try to create a token by calling localhost: xxxx / token on my API. The method below is, but context.OwinContext.GetUserManager returns null.

I tried to insert ApplicationUserManager in ApplicationOAuthProvider , but could not succeed. Could you point me in the right direction?

Edit: 10/15

Ok, so I got a little more, but I still stayed. I was able to initialize the classes as follows:

  var x = new DatabaseContext(); var store = new UserStore<ApplicationUser>(x); var options = new IdentityFactoryOptions<ApplicationUserManager>() { DataProtectionProvider = new Microsoft.Owin.Security.DataProtection.DpapiDataProtectionProvider("ApplicationName") }; builder.Register<DatabaseContext>(c => x); builder.Register<UserStore<ApplicationUser>>(c => store).AsImplementedInterfaces(); builder.Register<IdentityFactoryOptions<ApplicationUserManager>>(c => options); builder.RegisterType<ApplicationUserManager>(); builder.Register<ApplicationOAuthProvider>(c => new ApplicationOAuthProvider("self", new ApplicationUserManager(store, options))).As<IOAuthAuthorizationServerProvider>(); 

This allowed me to pass ApplicationUserManager to my ApplicationOAuthProvider constructor. In the Startup.Auth configuration Startup.Auth I initialize the Provider as follows:

 OAuthOptions = new OAuthAuthorizationServerOptions { TokenEndpointPath = new PathString("/Token"), Provider = (IOAuthAuthorizationServerProvider)GlobalConfiguration.Configuration.DependencyResolver.GetService(typeof(IOAuthAuthorizationServerProvider)), AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"), AccessTokenExpireTimeSpan = TimeSpan.FromDays(14), AllowInsecureHttp = true }; 

This brings me closer to a solution, but still has two problems.

First, when I call / token in the API, userManager.FindAsync(context.UserName, context.Password) returns a null value, but userManager.FindByEmailAsync(context.UserName) returns the desired user. My initial thought was the wrong password, but I made sure that this is the same password that I registered.

The second problem: if I call the register on my AccountController and then call / token, I get I can’t access the remote object. Object Name: "UserStore" . Therefore, I assume that this means that I am not initializing ApplicationOAuthProvider correctly in the Bootstrapper file.

Everyone is welcome any guide. Thanks!

+6
source share
1 answer

finally find a solution the first solution: first: change the startup class bootstrap you must add singleInstance (); to avoid dependency errors in queries [No scope with matching tag "AutofacWebRequest]

  builder.RegisterType<DatabaseContext>().AsSelf().SingleInstance(); builder.Register<IdentityFactoryOptions<ApplicationUserManager>>(c => new IdentityFactoryOptions<ApplicationUserManager>() { DataProtectionProvider = new DpapiDataProtectionProvider("your app name") }); builder.RegisterType<ApplicationUserManager>().AsSelf().SingleInstance(); // to resolve applicationUserManager builder.Register(c=>new ApplicationOAuthProvider(c.Resolve<ApplicationUserManager>())).AsImplementedInterfaces().SingleInstance(); builder.Register(c => new UserStore<ApplicationUser>(c.Resolve<DatabaseContext>())).AsImplementedInterfaces().SingleInstance(); builder.Register(c => HttpContext.Current.GetOwinContext().Authentication).As<IAuthenticationManager>(); 

seconds: in Startup.cs will remove GlobalConfiguration.configuration.DependencyResolver because it always gives null. Therefore, I will use the autofac container autoloader, but should use it from lifetimecope, this container is returned from your autofac auto-loading method

 OAuthOptions = new OAuthAuthorizationServerOptions { TokenEndpointPath = new PathString("/Token"), Provider = container.BeginLifetimeScope().Resolve<IOAuthAuthorizationServerProvider>(), AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"), AccessTokenExpireTimeSpan = TimeSpan.FromDays(14), AllowInsecureHttp = true }; 

thirdly: a constructor will be added to the ApplicationOAuthProvider class, which will take applicationUserManager as a parameter

this fix my zero error after two days google search and cannot find the answer, hope this helps.

second solution: since SingleInstance () is not suitable for enterprise applications, so you can use InstancePerRequest (); for all types of registers

  builder.RegisterType<DatabaseContext>().AsSelf().InstancePerRequest(); builder.Register<IdentityFactoryOptions<ApplicationUserManager>>(c => new IdentityFactoryOptions<ApplicationUserManager>() { DataProtectionProvider = new DpapiDataProtectionProvider("your app name") }); builder.RegisterType<ApplicationUserManager>().AsSelf().InstancePerRequest(); // to resolve applicationUserManager builder.Register(c=>new ApplicationOAuthProvider(c.Resolve<ApplicationUserManager>())).AsImplementedInterfaces().InstancePerRequest(); builder.Register(c => new UserStore<ApplicationUser>(c.Resolve<DatabaseContext>())).AsImplementedInterfaces().InstancePerRequest(); builder.Register(c => HttpContext.Current.GetOwinContext().Authentication).As<IAuthenticationManager>(); 

in startup.cs

  OAuthOptions = new OAuthAuthorizationServerOptions { TokenEndpointPath = new PathString("/Token"), // will instantiate new one to avoid Single Instance for resolving Provider = new CustomOAuthProvider(new ApplicationUserManager(new UserStore<Entities.ApplicationUser>(new DataContext()), AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"), AccessTokenExpireTimeSpan = TimeSpan.FromDays(14), AllowInsecureHttp = true }; 

Class CustomOAuthProvider

 using Microsoft.AspNet.Identity.Owin; using Microsoft.Owin.Security; using Microsoft.Owin.Security.OAuth; using System.Security.Claims; using System.Threading.Tasks; public class CustomOAuthProvider:OAuthAuthorizationServerProvider { private ApplicationUserManager _appUserManager; public CustomOAuthProvider(ApplicationUserManager appUserManager) { this._appUserManager = appUserManager; } public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context) { var allowedOrigin = "*"; context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { allowedOrigin }); var userManager = new ApplicationUserManager(new Microsoft.AspNet.Identity.EntityFramework.UserStore<AppUser>(new Data.DataContext()),new IdentityFactoryOptions<ApplicationUserManager>(),new Data.Repositories.SettingRepository(new Data.Infrastructure.DbFactory())); AppUser user = await userManager.FindAsync(context.UserName, context.Password); if (user == null) { context.SetError("invalid_grant", "Invalid username or password."); return; } if (!user.IsActive) { context.SetError("invalid_activation", "Inactive account, contact support."); return; } if (!user.EmailConfirmed) { context.SetError("invalid_grant", "User did not confirm email."); return; } ClaimsIdentity oAuthIdentity = await userManager.GenerateUserIdentityAsync(user, "JWT"); AuthenticationTicket ticket = new AuthenticationTicket(oAuthIdentity, null); context.Validated(ticket); } public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context) { if (context.ClientId == null) { context.Validated(); } return Task.FromResult<object>(null); } } 
+2
source

Source: https://habr.com/ru/post/976746/


All Articles