Identity 2.0 with custom tables Identity 2.0 with custom tables asp.net asp.net

Identity 2.0 with custom tables


In your examples, you seem to want to replace the DbContext with something else but I believe that actually, you need to focus your efforts one level higher.

The framework has a class UserManager which has the responsibility for managing, but not storing, the users and their related information. When it wants to store the users (or their related information) the default is to use the provided UserStore<IdentityUser> which knows how to store IdentityUser instances in a database using a DbContext.

In the 2.0 framework, the various bits of the identity storing were broken into several interfaces. The default implementation provided, UserStore<IdentityUser> implements several of these interfaces and stores the data for them all in the database using a DBContext.

If you look at the defnition of the default provided entity framework based UserStore you can see that it implements many of these small interfaces:

public class UserStore<TUser, TRole, TKey, TUserLogin, TUserRole, TUserClaim> : IUserLoginStore<TUser, TKey>, IUserClaimStore<TUser, TKey>, IUserRoleStore<TUser, TKey>, IUserPasswordStore<TUser, TKey>, IUserSecurityStampStore<TUser, TKey>, IQueryableUserStore<TUser, TKey>, IUserEmailStore<TUser, TKey>, IUserPhoneNumberStore<TUser, TKey>, IUserTwoFactorStore<TUser, TKey>, IUserLockoutStore<TUser, TKey>, IUserStore<TUser, TKey>, IDisposable where TUser : IdentityUser<TKey, TUserLogin, TUserRole, TUserClaim>where TRole : IdentityRole<TKey, TUserRole>where TKey : Object, IEquatable<TKey>where TUserLogin : new(), IdentityUserLogin<TKey>where TUserRole : new(), IdentityUserRole<TKey>where TUserClaim : new(), IdentityUserClaim<TKey>

As you don't want to use Entity Framework at all, you need to provide your own implementations of some of these key interfaces which will store that data in the places you want the data to be stored. The main interface is IUserStore<Tuser,TKey>. this defines the contract for storing users which have a key of a particular type. If you only want to store users and no other information then you can implement this interface and then pass your implementation to the UserManager and you should be good to go.

It's unlikely that this will be enough though as likely you will want passwords, roles, logins etc for your users. If so then you need to make your class which implements IUserStore<Tuser,TKey> also implement IUserPasswordStore<TUser, TKey>, IRoleStore<TRole, TKey> and IUserClaimStore<TUser, TKey>.

You can find a list of all the interfaces on MSDN here

Depending on the bits you want to use you need to implement those interfaces.

You will probably also need to define your own versions of the Identity* classes which exist for the Entity framework already out of the box. So you will need your own IdentityUser class which represents the users you want to store, and IdentityUserClaim for the users claims. I haven't done this myself so I'm not exactly sure, but my feeling is that you will have to do this.

Scott Allen has a good article on the various bits of the model which might be useful.

As for your issues with this line:

AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, await user.GenerateUserIdentityAsync(UserManager));

There is a method called GenerateUserIdentityAsync which is defined on Applicationuser which extends IdentityUser. It is defined in the template project I believe and looks something like this:

public class ApplicationUser : IdentityUser {    public async Task<ClaimsIdentity> GenerateUserIdentityAsync(    UserManager<ApplicationUser> manager) {    // Note the authenticationType must match the one     // defined in CookieAuthenticationOptions.AuthenticationType    var userIdentity =         await manager.CreateIdentityAsync(this,             DefaultAuthenticationTypes.ApplicationCookie);    // Add custom user claims here    return userIdentity;    }}

As you are not using the entity framework IdentityUser any more then you either need to define a similar method or your own User class or implement the same functionality some other way (like just calling await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie) instead)


I am pretty new to Identity myself. Does your User entity implement the IUser interface? e.g.

public partial class User : IUser<Guid> //Whatever your key is{    public Task<ClaimsIdentity> GenerateUserIdentityAsync(ApplicationUserManager manager)    {        return Task.FromResult(GenerateUserIdentity(manager));    }    public ClaimsIdentity GenerateUserIdentity(ApplicationUserManager manager)    {        // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType        var userIdentity = manager.CreateIdentity<User, Guid>(this, DefaultAuthenticationTypes.ApplicationCookie);        // Add custom user claims here        return userIdentity;    }}

Then to sign in you can call the above:

public async Task SignInAsync(User user, bool isPersistent)    {        var userIdentity = await user.GenerateUserIdentityAsync(UserManager);        AuthenticationManager.SignIn(            new AuthenticationProperties            {                IsPersistent = isPersistent            },            userIdentity        );    }   


I think this has been updated recently to this in ApplicationUser:

public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager, string authenticationType){    // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType    var userIdentity = await manager.CreateIdentityAsync(this, authenticationType);    // Add custom user claims here    return userIdentity;}

It is called like this from AccountController -> GetExternalLogin

ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(UserManager,    OAuthDefaults.AuthenticationType);ClaimsIdentity cookieIdentity = await user.GenerateUserIdentityAsync(UserManager,    CookieAuthenticationDefaults.AuthenticationType);