.NET Zone is brought to you in partnership with:

Imran is a DZone MVB and is not an employee of DZone and has posted 31 posts at DZone. View Full User Profile

A Simple Implementation of Microsoft.AspNet.Identity

12.19.2013
| 5511 views |
  • submit to reddit

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 andNHibernate.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.

Published at DZone with permission of Imran Baloch, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)