Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Migrating existing users from MVC 4 SimpleMembership to MVC 5 ASP.NET Identity

I have an MVC 4 site that currently implements SimpleMembership. In the next iteration of the site I would like to upgrade to MVC 5 and ASP.NET Identity. Both sites have the same machine key in web.config. The SimpleMembership SQL tables have a column for Password and PaswordSalt the ASP.NET Identity tables have a column for PasswordHash which seems to be a combination of Password + PasswordSalt.

I tried concatenating the Password and PasswordSlat together from the old site but this doesn’t work.

My question is,

how do I migrate my existing user’s passwords from the old site to the new site?

like image 536
Alex Avatar asked Oct 30 '13 16:10

Alex


People also ask

How can add migration in ASP NET MVC?

Open the Package Manager Console. Select Tools > NuGet Package Manager > Package Manager Console. The Enable-Migration command creates the Migrations folder, which contains a script to initialize the database. Open the Configuration.

How do I log into MVC identity with email instead of UserName?

cs change the property Email to UserName , remove the [EmailAddress] annotation from there and change the [Display(Name = "Email")] to [Display(Name = "Login")] or something you want to display. If you want to keep Email property, then add UserName property to the same view model and make it as required.

What is Aspnet core identity?

ASP.NET Core Identity: Is an API that supports user interface (UI) login functionality. Manages users, passwords, profile data, roles, claims, tokens, email confirmation, and more.


1 Answers

According to http://www.asp.net/identity/overview/migrations/migrating-an-existing-website-from-sql-membership-to-aspnet-identity :

The passwords of the users of the application are encrypted and stored in the database. The crypto algorithm used in SQL membership is different from the one in the new Identity system. To reuse old passwords we need to selectively decrypt passwords when old users log in using the SQL memberships algorithm while using the crypto algorithm in Identity for the new users.

The UserManager class has a property 'PasswordHasher' which stores an instance of a class that implements the 'IPasswordHasher' interface. This is used to encrypt/decrypt passwords during user authentication transactions. In the UserManager class defined in step 3, create a new class SQLPasswordHasher and copy the below code.

So you have to create new hasher class with the folowing code:

public class SQLPasswordHasher : PasswordHasher
  {
    public override string HashPassword(string password)
    {
        return base.HashPassword(password);
    }

public override PasswordVerificationResult VerifyHashedPassword(string  hashedPassword, string providedPassword)
    {
        string[] passwordProperties = hashedPassword.Split('|');
        if (passwordProperties.Length != 3)
        {
            return base.VerifyHashedPassword(hashedPassword, providedPassword);
        }
        else
        {
            string passwordHash = passwordProperties[0];
            int passwordformat = 1;
            string salt = passwordProperties[2];
            if (String.Equals(EncryptPassword(providedPassword, passwordformat, salt), passwordHash, StringComparison.CurrentCultureIgnoreCase))
            {
                return PasswordVerificationResult.SuccessRehashNeeded;
            }
            else
            {
                return PasswordVerificationResult.Failed;
            }
        }
    }

//This is copied from the existing SQL providers and is provided only for back-compat.
    private string EncryptPassword(string pass, int passwordFormat, string salt)
    {
        if (passwordFormat == 0) // MembershipPasswordFormat.Clear
            return pass;

        byte[] bIn = Encoding.Unicode.GetBytes(pass);
        byte[] bSalt = Convert.FromBase64String(salt);
        byte[] bRet = null;

        if (passwordFormat == 1)
        { // MembershipPasswordFormat.Hashed 
            HashAlgorithm hm = HashAlgorithm.Create("SHA1");
            if (hm is KeyedHashAlgorithm)
            {
                KeyedHashAlgorithm kha = (KeyedHashAlgorithm)hm;
                if (kha.Key.Length == bSalt.Length)
                {
                    kha.Key = bSalt;
                }
                else if (kha.Key.Length < bSalt.Length)
                {
                    byte[] bKey = new byte[kha.Key.Length];
                    Buffer.BlockCopy(bSalt, 0, bKey, 0, bKey.Length);
                    kha.Key = bKey;
                }
                else
                {
                    byte[] bKey = new byte[kha.Key.Length];
                    for (int iter = 0; iter < bKey.Length; )
                    {
                        int len = Math.Min(bSalt.Length, bKey.Length - iter);
                        Buffer.BlockCopy(bSalt, 0, bKey, iter, len);
                        iter += len;
                    }
                    kha.Key = bKey;
                }
                bRet = kha.ComputeHash(bIn);
            }
            else
            {
                byte[] bAll = new byte[bSalt.Length + bIn.Length];
                Buffer.BlockCopy(bSalt, 0, bAll, 0, bSalt.Length);
                Buffer.BlockCopy(bIn, 0, bAll, bSalt.Length, bIn.Length);
                bRet = hm.ComputeHash(bAll);
            }
        }

        return Convert.ToBase64String(bRet);
    }

Then declare in your Identity UserManager class a contructor to use this hasher, for example:

public UserManager()
        : base(new UserStore<User>(new ApplicationDbContext()))
    {
        this.PasswordHasher = new SQLPasswordHasher();
}
like image 81
Alexander Pavlenko Avatar answered Nov 01 '22 18:11

Alexander Pavlenko