Identity 2.2.1 & UserManager with Ninject - c#

I've been using Identity 2.2.1 with Ninject on a Web API project and all seems to be working well other than the UserManager. The UserManager is created but when it's injected into a service it only contains it's default implementation and not the configuration it should be using.
I've tried to follow multiple solutions to answers on here but to no avail. Could someone point out where I'm going wrong please.
Startup.cs
public class Startup
{
internal static IDataProtectionProvider DataProtectionProvider { get; private set; }
public void Configuration(IAppBuilder app)
{
var config = new HttpConfiguration();
var kernel = NinjectConfig.CreateKernel();
app.UseNinjectMiddleware(() => kernel);
WebApiConfig.Register(config);
ConfigureOAuth(app, kernel);
app.UseNinjectWebApi(config);
app.UseWebApi(config);
}
private void ConfigureOAuth(IAppBuilder app, IKernel kernel)
{
DataProtectionProvider = app.GetDataProtectionProvider();
app.CreatePerOwinContext<UserManager>((option, context) =>
{
return kernel.Get<UserManager>();
});
app.UseCors(CorsOptions.AllowAll);
app.UseOAuthAuthorizationServer(new OAuthAuthorizationServerOptions
{
TokenEndpointPath = new PathString("/token"),
Provider = new AuthorizationServerProvider(),
AccessTokenExpireTimeSpan = TimeSpan.FromHours(6),
AllowInsecureHttp = true // TODO: Change when in production
});
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
}
}
NinjectConfig.cs
public static class NinjectConfig
{
public static IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Load(Assembly.GetExecutingAssembly());
RegisterServices(kernel);
return kernel;
}
private static void RegisterServices(IKernel kernel)
{
GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel);
}
}
IdentityModule.cs
public class IdentityModule : NinjectModule
{
public override void Load()
{
Bind<IUserStore<User>>().To<UserStore<User>>().WithConstructorArgument("context", new NeedsCollectorDbContext());
Bind<UserManager>().ToSelf();
}
}
UserManager.cs
public class UserManager : UserManager<User>
{
public UserManager(IUserStore<User> store) : base(store)
{
UserValidator = new UserValidator<User>(this)
{
AllowOnlyAlphanumericUserNames = false,
RequireUniqueEmail = true
};
PasswordValidator = new PasswordValidator
{
RequiredLength = 6,
RequireNonLetterOrDigit = false,
RequireDigit = true,
RequireLowercase = true,
RequireUppercase = true,
};
var dataProtectionProvider = Startup.DataProtectionProvider;
if (dataProtectionProvider != null)
{
UserTokenProvider = new DataProtectorTokenProvider<User>(dataProtectionProvider.Create("ASP.NET Identity"));
}
}
}
The UserManager gets instantiated with the correct configuration within Startup.cs but when injected into the service later it's lost, please see the screenshots - the UserTokenProvider is null when injected.
Startup.cs
Within a service
Thanks

Related

HttpContext.User.Claims zero elements in Controller base

I am incorporating AWS-CognitoIdentity Provider in my ASP.Net Core Web Api project and after following the official documentation i still get HttpContext.User NULL. Is there is a step by step guide that someone has used before successfully to get AWS-CognitoIdentity provider working.
I have setup the CognitoIdentity in my Startup.cs and later in my other controllers i am trying to access the User.
public class Startup
{
private static readonly ILog logger = LogManager.GetLogger(typeof(Startup));
private string poolId;
private string appClientId;
private static string providerName;
private static AmazonCognitoIdentityProviderClient provider;
private static CognitoUserPool pool;
public IConfiguration Configuration { get; }
public Startup(IConfiguration configuration)
{
Configuration = configuration;
appClientId = Configuration.GetValue<string>("AWS:UserPoolClientId");
providerName = Configuration.GetValue<string>("AWS:ProviderName");
poolId = Configuration.GetValue<string>("AWS:UserPoolId");
AWSConfigs.RegionEndpoint = RegionEndpoint.EUWest2;
provider = new AmazonCognitoIdentityProviderClient();
pool = new CognitoUserPool(poolId, appClientId, provider, "");
}
public void ConfigureServices(IServiceCollection services)
{
services.Configure<IdentityOptions>(options =>
{
options.Lockout.MaxFailedAccessAttempts = 10;
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(10);
});
services.AddCognitoIdentity();
services.AddAuthentication("Bearer").AddJwtBearer(options =>
{
options.Audience = Configuration.GetValue<string>("AWS:UserPoolClientId");
options.Authority = Configuration.GetValue<string>("AWS:ProviderName");
options.TokenValidationParameters = new TokenValidationParameters
{
ValidIssuer = Configuration.GetValue<string>("AWS:ProviderName"),
ValidateIssuerSigningKey = true,
ValidateIssuer = true,
ValidateLifetime = true,
ValidAudience = Configuration.GetValue<string>("AWS:UserPoolClientId"),
ValidateAudience = true,
IssuerSigningKeyResolver = (s, securityToken, identifier, parameters) =>
{
var json = new WebClient().DownloadString(Configuration.GetValue<string>("AWS:MetadataAddress"));
var keys = JsonConvert.DeserializeObject<JsonWebKeySet>(json).Keys;
return (IEnumerable<SecurityKey>)keys;
},
};
options.Events = new JwtBearerEvents
{
OnMessageReceived = context =>
{
Console.WriteLine("Message Received-------------------------------------------------------------\n");
return Task.CompletedTask;
},
OnTokenValidated = context =>
{
Console.WriteLine("TokenValidated Received-------------------------------------------------------\n");
return Task.CompletedTask;
}
};
});
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
public void Configure(
IApplicationBuilder app,
IHostingEnvironment env,
UserManager<CognitoUser> _userManager,
SignInManager<CognitoUser> _signInManager)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseAuthentication();
app.UsePermissions();
app.UseMvc();
app.UseSwagger();
}
}
Controller
namespace DataControllers
{
//[Authorize]
[Route("api/[controller]/[action]")]
public class ContentController : Controller
{
private readonly CognitoUserManager<CognitoUser> _userManager;
public ContentController(UserManager<CognitoUser> userManager)
{
_userManager = userManager as CognitoUserManager<CognitoUser>;
}
[HttpGet]
public async Task<IActionResult> Menu()
{
var email = User.Claims.FirstOrDefault(e => e.Type == "email"); ;
}
}
}

ASP.NET MVC: No IUserTokenProvider is registered using Ninject

I am running into the error No IUserTokenProvider is registered on a call to _userManager.GenerateEmailConfirmationTokenAsync(user.Id); which is generating a token to be sent in an account registration e-mail. I have reviewed many posts related to this and none have solved my issue. From what I've learned, this functionality is hooked up in the ApplicationUserManager class by the following:
if (dataProtectionProvider != null)
{
IDataProtector dataProtector = dataProtectionProvider.Create("ASP.NET Identity");
this.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser>(dataProtector);
}
I've attempted to resolve the issue by doing the following as suggested elsewhere: My ApplicationUserManager class has teh following signature:
public ApplicationUserManager(IUserStore<ApplicationUser> store, IDataProtectionProvider dataProtectionProvider)
and the dataProtectionProvider I am injecting is bound by Ninject in Startup.cs like this:
private IAppBuilder _app;
public void Configuration(IAppBuilder app)
{
_app = app;
ConfigureAuth(app);
app.UseNinjectMiddleware(CreateKernel);
}
private IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Load(Assembly.GetExecutingAssembly());
//bindings
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
kernel.Bind<DbContext>().To<MvcIndividualAuthContext>().InRequestScope();
kernel.Bind(typeof(IUserStore<>)).To(typeof(UserStore<>)).InRequestScope();
kernel.Load(Assembly.GetExecutingAssembly());
kernel.Bind<MvcIndividualAuthContext>().ToSelf().InRequestScope();
kernel.Bind<IUserStore<ApplicationUser, string>>().To<ApplicationUserStore>();
kernel.Bind<ApplicationUserManager>().ToSelf();
kernel.Bind<ApplicationSignInManager>().ToSelf();
kernel.Bind<IAuthenticationManager>().ToMethod(x => HttpContext.Current.GetOwinContext().Authentication);
kernel.Bind<IdentityFactoryOptions<ApplicationUserManager>>().ToSelf();
//this bind should be binding the IDataProtectionProvider for my
//ApplicationUserManager
kernel.Bind<IDataProtectionProvider>().ToMethod(x => _app.GetDataProtectionProvider());
return kernel;
}
however the binding doesn't seem to be working because my ApplicationUserManager's UserTokenProvider is still null at the time of generating my token. For reference, you can find the code for my ApplicationUserManager below:
public class ApplicationUserManager : UserManager<ApplicationUser>
{
public ApplicationUserManager(IUserStore<ApplicationUser> store, IDataProtectionProvider dataProtectionProvider)
: base(store)
{
// Configure validation logic for usernames
this.UserValidator = new UserValidator<ApplicationUser>(this)
{
AllowOnlyAlphanumericUserNames = false,
RequireUniqueEmail = true
};
// Configure validation logic for passwords
this.PasswordValidator = new PasswordValidator
{
RequiredLength = 6,
RequireNonLetterOrDigit = true,
RequireDigit = true,
RequireLowercase = true,
RequireUppercase = true,
};
// Configure user lockout defaults
this.UserLockoutEnabledByDefault = true;
this.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5);
this.MaxFailedAccessAttemptsBeforeLockout = 5;
// Register two factor authentication providers. This application uses Phone and Emails as a step of receiving a code for verifying the user
// You can write your own provider and plug it in here.
this.RegisterTwoFactorProvider("Phone Code", new PhoneNumberTokenProvider<ApplicationUser>
{
MessageFormat = "Your security code is {0}"
});
this.RegisterTwoFactorProvider("Email Code", new EmailTokenProvider<ApplicationUser>
{
Subject = "Security Code",
BodyFormat = "Your security code is {0}"
});
this.EmailService = new EmailService();
this.SmsService = new SmsService();
if (dataProtectionProvider != null)
{
IDataProtector dataProtector = dataProtectionProvider.Create("ASP.NET Identity");
this.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser>(dataProtector);
}
}
}
All help is greatly appreciated.
After cleaning and building the solution, the issue has been resolved. Note that the solution had been built numerous times during while the issue was occurring but not cleaned.

No IUserTokenProvider is registered when using dependency injection

I got an error when my GeneratePasswordResetTokenAsync() method is call. I configured autofac with owin identity.
The error is :
No IUserTokenProvider is registered when using dependency injection
In my sample.web project there is a AutofacConfig.cs file where I register signinmanager and usermanager which I created in sample.repository project.
AutofacConfig.cs
public class AutofacConfig
{
public static Autofac.IContainer RegisterDependencies()
{
var containerBuilder = new ContainerBuilder();
// REGISTER DEPENDENCIES
containerBuilder.RegisterType<SampleDataContext>()
.As<DbContext>()
.InstancePerDependency();
containerBuilder.RegisterType<UserStore<SampleUser>>()
.As<IUserStore<SampleUser>>()
.InstancePerRequest();
containerBuilder.RegisterType<ApplicationUserManager>()
.AsSelf()
.InstancePerRequest();
containerBuilder.RegisterType<ApplicationSignInManager>()
.AsSelf()
.InstancePerRequest();
containerBuilder.RegisterType<EmailService>();
containerBuilder.Register<IAuthenticationManager>(c => HttpContext.Current.GetOwinContext().Authentication)
.InstancePerRequest();
var container = containerBuilder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
var resolver = new AutofacWebApiDependencyResolver(container);
GlobalConfiguration.Configuration.DependencyResolver = resolver;
return container;
}
}
ApplicationUserManager.cs
public class ApplicationUserManager : UserManager<SampleUser>
{
public ApplicationUserManager(IUserStore<SampleUser> store)
: base(store)
{
}
public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
{
var manager = new ApplicationUserManager(new UserStore<SampleUser>(context.Get<SampleDataContext>()));
// Configure validation logic for usernames
manager.UserValidator = new UserValidator<SampleUser>(manager)
{
AllowOnlyAlphanumericUserNames = false,
RequireUniqueEmail = true
};
// Configure validation logic for passwords
manager.PasswordValidator = new PasswordValidator
{
RequiredLength = 8,
RequireNonLetterOrDigit = false,
RequireDigit = false,
RequireLowercase = false,
RequireUppercase = false,
};
// Configure user lockout defaults
manager.UserLockoutEnabledByDefault = true;
manager.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5);
manager.MaxFailedAccessAttemptsBeforeLockout = 5;
// Register two factor authentication providers. This application uses Phone and Emails as a step of receiving a code for verifying the user
// You can write your own provider and plug it in here.
manager.RegisterTwoFactorProvider("Phone Code", new PhoneNumberTokenProvider<SampleUser>
{
MessageFormat = "Your security code is {0}"
});
manager.RegisterTwoFactorProvider("Email Code", new EmailTokenProvider<SampleUser>
{
Subject = "Security Code",
BodyFormat = "Your security code is {0}"
});
manager.EmailService = new EmailService();
manager.SmsService = new SmsService();
var provider = new DpapiDataProtectionProvider("Sample");
manager.UserTokenProvider = new DataProtectorTokenProvider<SampleUser>(
provider.Create("ASP.NET Identity"));
return manager;
}
}
Remove create() method in ApplicationUserManager.cs class and add that code in ApplicationUserManager class's constructor.
ApplicationUserManager.cs
public class ApplicationUserManager : UserManager<SampleUser>
{
public ApplicationUserManager(IUserStore<SampleUser> store, IDataProtectionProvider dataProtectionProvider)
: base(store)
{
// Configure validation logic for usernames
this.UserValidator = new UserValidator<SampleUser>(this)
{
AllowOnlyAlphanumericUserNames = false,
RequireUniqueEmail = true
};
// Configure validation logic for passwords
this.PasswordValidator = new PasswordValidator
{
RequiredLength = 6,
RequireNonLetterOrDigit = false,
RequireDigit = false,
RequireLowercase = false,
RequireUppercase = false,
};
// Configure user lockout defaults
this.UserLockoutEnabledByDefault = true;
this.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5);
this.MaxFailedAccessAttemptsBeforeLockout = 5;
// Register two factor authentication providers. This application uses Phone and Emails as a step of receiving a code for verifying the user
// You can write your own provider and plug it in here.
this.RegisterTwoFactorProvider("Phone Code", new PhoneNumberTokenProvider<SampleUser>
{
MessageFormat = "Your security code is {0}"
});
this.RegisterTwoFactorProvider("Email Code", new EmailTokenProvider<SampleUser>
{
Subject = "Security Code",
BodyFormat = "Your security code is {0}"
});
this.EmailService = new EmailService();
this.SmsService = new SmsService();
// var dataProtectionProvider = Startup.DataProtectionProvider;
if (dataProtectionProvider != null)
{
IDataProtector dataProtector = dataProtectionProvider.Create("ASP.NET Identity");
this.UserTokenProvider = new DataProtectorTokenProvider<SampleUser>(dataProtector);
}
}
}
register DataProtectionProvider in AutofacConfig.cs file
containerBuilder.Register<IDataProtectionProvider>(c => Startup.DataProtectionProvider).InstancePerRequest();
Resolve ApplicationUSerManager class in Startup.cs class
public partial class Startup
{
public static IDataProtectionProvider DataProtectionProvider { get; private set; }
public void ConfigureAuth(IAppBuilder app)
{
// add this assignment
DataProtectionProvider = app.GetDataProtectionProvider();
// Configure the db context, user manager and signin manager to use a single instance per request
app.CreatePerOwinContext(SampleDataContext.Create);
app.CreatePerOwinContext(() => DependencyResolver.Current.GetService<ApplicationUserManager>());
app.CreatePerOwinContext(() => DependencyResolver.Current.GetService<ApplicationSignInManager>());
}
}
just got solution from here
it is very helpful article

Always getting the "Authorization has been denied for this request." message

I'm able to successfully retrieve token, but when trying to authenticate using the token I always get the Authorization has been denied for this request message.
My Startup.cs file contains the following methods
public void Configuration(IAppBuilder app)
{
var config = new HttpConfiguration();
WebApiConfig.Register(config);
app.UseWebApi(config);
ConfigureOAuth(app);
var jsonFormatter = config.Formatters.OfType<JsonMediaTypeFormatter().First();
jsonFormatter.SerializerSettings
.ContractResolver = new CamelCasePropertyNamesContractResolver();
}
private void ConfigureOAuth(IAppBuilder app)
{
var oAuthServerOptions = new OAuthAuthorizationServerOptions()
{
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/Token"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
Provider = new DefaultAuthorizationServerProvider()
};
app.UseOAuthAuthorizationServer(oAuthServerOptions);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
}
The DefaultAuthorizationServerProvider.cs class contains the following
public class DefaultAuthorizationServerProvider : OAuthAuthorizationServerProvider
{
public override async Task ValidateClientAuthentication
(
OAuthValidateClientAuthenticationContext context
)
{
context.Validated();
}
public override async Task GrantResourceOwnerCredentials
(
OAuthGrantResourceOwnerCredentialsContext context
)
{
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });
var identityManager = new IdentityManager();
var identity = identityManager.Get(context.UserName, context.Password,
new IpAddressProvider().Provide(IpAddressType.Forwarding));
if (identity == null)
{
context.SetError("invalid_grant", "Authentication failed. Please make sure you provided the correct username and password.");
}
else
{
identity.AddClaim(new Claim(ClaimTypes.Role, "User"));
context.Validated(identity);
}
}
}
And the IdentityManager.cs class have the following
public class IdentityManager : IIdentityManager
{
public virtual ClaimsIdentity Get
(
string username,
string password,
string ipAddress
)
{
var authenticateUserWorkflowOutput = new AuthenticateUserWorkflowHelper().Execute
(
new AuthenticateUserWorkflowInput
{
Username = username,
Password = password,
IpAddress = ipAddress
},
new AuthenticateUserWorkflowState()
);
if (authenticateUserWorkflowOutput.Message.Exception != null)
{
return null;
}
if (!authenticateUserWorkflowOutput.Authenticated)
{
return null;
}
return authenticateUserWorkflowOutput.User != null ? new Infrastructure.Identity(new[]
{
new Claim(ClaimTypes.Name, authenticateUserWorkflowOutput.MasterUser.EmailAddress),
}, "ApplicationCookie") : null;
}
}
Using Fiddler I can successfully retrieve a token
But when I try to authenticate using the token I get the following response
Ok, I found the problem in my Startup class. I was missing the following
[assembly: OwinStartup(typeof(Yugasat.System.ServiceLayer.Startup))]
namespace Yugasat.System.ServiceLayer
and the ConfigureOAuth(app);call needed to be moved to the top of the Configuration method. Below is my new Startup.cs class.
[assembly: OwinStartup(typeof(Yugasat.System.ServiceLayer.Startup))]
namespace Yugasat.System.ServiceLayer
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
ConfigureOAuth(app);
var config = new HttpConfiguration();
WebApiConfig.Register(config);
app.UseWebApi(config);
var jsonFormatter = config.Formatters.OfType<JsonMediaTypeFormatter>().First();
jsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
}
private void ConfigureOAuth(IAppBuilder app)
{
var oAuthServerOptions = new OAuthAuthorizationServerOptions()
{
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/Token"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
Provider = new DefaultAuthorizationServerProvider()
};
app.UseOAuthAuthorizationServer(oAuthServerOptions);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
}
}
}

Using Autofac with Web Api 2 and Owin

Im new to DI libraries and trying to use Autofac in a WebApi 2 project with Owin. This is my Owin Startup class,
[assembly: OwinStartup(typeof(FMIS.SIGMA.WebApi.Startup))]
namespace FMIS.SIGMA.WebApi
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
var builder = new ContainerBuilder();
var config = new HttpConfiguration();
WebApiConfig.Register(config);
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
var container = builder.Build();
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
app.UseAutofacMiddleware(container);
app.UseAutofacWebApi(config);
app.UseWebApi(config);
ConfigureOAuth(app);
}
public void ConfigureOAuth(IAppBuilder app)
{
OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
{
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
Provider = new SimpleAuthorizationServerProvider()
};
// Token Generation
app.UseOAuthAuthorizationServer(OAuthServerOptions);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
}
}
}
When I call a Api method I get this error
An error occurred when trying to create a controller of type
'MyController'. Make sure that the controller has a
parameterless public constructor.
What am I missing here?
MyController code is something like this
public class MyController : ApiController
{
ISomeCommandHandler someCommanHandler;
public MyController(ISomeCommandHandler SomeCommandHandler)
{
this.someCommanHandler = SomeCommandHandler;
}
// POST: api/My
public void Post([FromBody]string value)
{
someCommanHandler.Execute(new MyCommand() {
Name = "some value"
});
}
// GET: api/My
public IEnumerable<string> Get()
{
}
// GET: api/My/5
public string Get(int id)
{
}
}
You have set DependencyResolver to AutofacWebApiDependencyResolver, so Autofac comes into play and instantiates dependencies for you. Now you have to explicitly tell Autofac which concrete implementations should be used when an instance of interface is required.
Your controller requires an instance of ISomeCommandHandler:
MyController(ISomeCommandHandler SomeCommandHandler)
So you need to configure types that expose that interface:
builder.RegisterType<CommandHandler>.As<ISomeCommandHandler>();
Have a look at this documentation section for more examples about Autofac registration concepts.

Categories

Resources