Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET Core Identity - UserManager and UserStore woes

I'm trying to implement the Identity system in an ASP.NET Core app (RC2 libraries) and there is a particular hangup that is driving me crazy.

First of all, I am not using EntityFramework. I'm not even using SQL. I'm backing up to RavenDB, so I need the implementation to be very specific to that; Which isn't a problem.

So I designed a RavenUserStore class, and it looks like this;

public class RavenUserStore<TUser> :
        IUserStore<TUser>,
        IUserLoginStore<TUser>,
        IUserPasswordStore<TUser>,
        IUserRoleStore<TUser>,
        IUserSecurityStampStore<TUser>,
        IUserClaimStore<TUser>,
        IUserLockoutStore<TUser>,
        IUserTwoFactorStore<TUser>,
        IUserEmailStore<TUser> {
    // ...
}

Works great on its own. I've implemented all the methods, etc. It's wonderful. Very clean and efficient.

Now, I go over to my web application and wire things up;

services.AddTransient<ILookupNormalizer>(s => new LowerInvariantLookupNormalizer());
services.AddTransient<IPasswordHasher<Member>>(s => new PasswordHasher<Member>());
services.AddTransient<IUserStore<Member>, RavenUserStore<Member>>();
services.AddIdentity<Member, Role>(o => {
    o.Password.RequiredLength = 6;
    o.Password.RequireDigit = true;
    o.Password.RequireLowercase = false;
    o.Password.RequireUppercase = false;
})
.AddUserStore<RavenUserStore<Member>>()
.AddRoleStore<RavenRoleStore<Role>>();

So I go make a controller to use this, per all the samples I've seen, and the very core sample from the Identity Framework Github Repository

//... [PROPERTIES]...//
public AccountController(UserManager<Member> userManager, SignInManager<Member> signInManager) {
    // ... [attach constructor parameters to properties] ...//
}

Alright, so I inspect the classes carefully.

UserManager<T> has a property Store,which is a type of IUserStore<T>.

So theoretically.. if the dependency injection resolves types of IUserStore<T> to RavenUserStore<T> when they are injected through a constructor.. shouldn't that mean that the UserManager<T> gets a RavenUserStore<T> as its Store property?

I thought it would too; But when I call methods on the UserManager, it DOES NOT call the ones on my RavenUserStore. Why is this? What can I do?

Do I really have to ALSO make a custom UserManager class and do all of those methods AGAIN?

like image 403
Ciel Avatar asked Apr 09 '16 20:04

Ciel


1 Answers

You need to add your own custom providers before calling services.AddIdentity(). Internally, AddIdentity uses TryAddScoped() which only adds the default items if they don't already exist in the services container.

So just putting the call to AddIdentity() after you registered all your custom implementations should mean that they will take precedence as you expect.

like image 199
Tim Long Avatar answered Nov 02 '22 15:11

Tim Long