A simple implementation of Microsoft.AspNet.Identity
Introduction:
Microsoft.AspNet.Identity (famously known as ASP.NET Identity) is a brand new library for asp.net membership system that allows you to build modern ASP.NET web applications. The beauty of ASP.NET Identity is that it allows you to use any storage system. There is an implementation of Microsoft.AspNet.Identity in EF provided by Microsoft. You can also find some implementation of Microsoft.AspNet.Identity by community. For example, AspNet.Identity.RavenDB and NHibernate.AspNet.Identity. Currently, the EF implementation include Roles and Claims. But sometimes, you don't need any Claims and Roles. In this article, I will show you how to implement an implementation of Microsoft.AspNet.Identity without using Claims and Roles.
Description:
First of all create a MVC 5 application. Then implement IUser,
public class ApplicationUser : IUser { public ApplicationUser() { this.Id = Guid.NewGuid().ToString(); } public ApplicationUser(string userName): this() { UserName = userName; } public virtual string Id { get; set; } public virtual string PasswordHash { get; set; } public virtual string SecurityStamp { get; set; } public virtual string UserName { get; set; } }
Next we need a DbContet to store the Users,
public class ApplicationDbContext : DbContext { public ApplicationDbContext() : base("DefaultConnection") { } public virtual IDbSet<ApplicationUser> Users { get; set; } }
and then we need to implement IUserStore, IUserPasswordStore and IUserSecurityStampStore,
public class MyUserStore : IUserStore<ApplicationUser>, IUserPasswordStore<ApplicationUser>, IUserSecurityStampStore<ApplicationUser> { UserStore<IdentityUser> userStore = new UserStore<IdentityUser>(new ApplicationDbContext()); public MyUserStore() { } public Task CreateAsync(ApplicationUser user) { var context = userStore.Context as ApplicationDbContext; context.Users.Add(user); context.Configuration.ValidateOnSaveEnabled = false; return context.SaveChangesAsync(); } public Task DeleteAsync(ApplicationUser user) { var context = userStore.Context as ApplicationDbContext; context.Users.Remove(user); context.Configuration.ValidateOnSaveEnabled = false; return context.SaveChangesAsync(); } public Task<ApplicationUser> FindByIdAsync(string userId) { var context = userStore.Context as ApplicationDbContext; return context.Users.Where(u => u.Id.ToLower() == userId.ToLower()).FirstOrDefaultAsync(); } public Task<ApplicationUser> FindByNameAsync(string userName) { var context = userStore.Context as ApplicationDbContext; return context.Users.Where(u => u.UserName.ToLower() == userName.ToLower()).FirstOrDefaultAsync(); } public Task UpdateAsync(ApplicationUser user) { var context = userStore.Context as ApplicationDbContext; context.Users.Attach(user); context.Entry(user).State = EntityState.Modified; context.Configuration.ValidateOnSaveEnabled = false; return context.SaveChangesAsync(); } public void Dispose() { userStore.Dispose(); } public Task<string> GetPasswordHashAsync(ApplicationUser user) { var identityUser = ToIdentityUser(user); var task = userStore.GetPasswordHashAsync(identityUser); SetApplicationUser(user, identityUser); return task; } public Task<bool> HasPasswordAsync(ApplicationUser user) { var identityUser = ToIdentityUser(user); var task = userStore.HasPasswordAsync(identityUser); SetApplicationUser(user, identityUser); return task; } public Task SetPasswordHashAsync(ApplicationUser user, string passwordHash) { var identityUser = ToIdentityUser(user); var task = userStore.SetPasswordHashAsync(identityUser, passwordHash); SetApplicationUser(user, identityUser); return task; } public Task<string> GetSecurityStampAsync(ApplicationUser user) { var identityUser = ToIdentityUser(user); var task = userStore.GetSecurityStampAsync(identityUser); SetApplicationUser(user, identityUser); return task; } public Task SetSecurityStampAsync(ApplicationUser user, string stamp) { var identityUser = ToIdentityUser(user); var task = userStore.SetSecurityStampAsync(identityUser, stamp); SetApplicationUser(user, identityUser); return task; } private static void SetApplicationUser(ApplicationUser user, IdentityUser identityUser) { user.PasswordHash = identityUser.PasswordHash; user.SecurityStamp = identityUser.SecurityStamp; user.Id = identityUser.Id; user.UserName = identityUser.UserName; } private IdentityUser ToIdentityUser(ApplicationUser user) { return new IdentityUser { Id = user.Id, PasswordHash = user.PasswordHash, SecurityStamp = user.SecurityStamp, UserName = user.UserName }; } }
For password hash and security stamp, I am using the UserStore's implementation for making thing simpler. Finally we just need to change AccountController's constructor to leverage our MyUserStore implementation,
public AccountController() : this(new UserManager<ApplicationUser>(new MyUserStore())) { } public AccountController(UserManager<ApplicationUser> userManager) { UserManager = userManager; }
Summary:
The new Microsoft.AspNet.Identity make it very easy to extend the storage system. In this article, I showed you how to implement a simple implementation of Microsoft.AspNet.Identity. Hopefully you enjoyed my this article too.