fullstackproltd / AspNetCoreSpa

Asp.Net 7.0 & Angular 15 SPA Fullstack application with plenty of examples. Live demo:
https://aspnetcorespa.fullstackpro.co.uk
MIT License
1.48k stars 465 forks source link

Migrate from SimpleMembershipProvider to ASP.NET Core Identity #231

Closed Daeamon closed 6 years ago

Daeamon commented 6 years ago

I plan to move the old project from Asp.net MVC to angular +.NET Core))) In old project i used SimpleMembershipProvider. And can i use SimpleMembershipProvider with this project?

Daeamon commented 6 years ago

I found a solution. I'm using this code for check if a password hash is being verified by hashing function from SimpleMembershipProvider, and then i reset password by asp.net identity function

Hashing Function

using System;
using System.Runtime.CompilerServices;
using System.Security.Cryptography;
using Microsoft.AspNetCore.Identity;

namespace AspNetCoreSpa.Web.Extensions
{
    public class CustomPasswordHasher : PasswordHasher<IdentityUser>
    {
        public override PasswordVerificationResult VerifyHashedPassword(IdentityUser user, string hashedPassword,
            string providedPassword)
        {
            var isValidPasswordWithLegacyHash = VerifyHashedPassword(hashedPassword, providedPassword);
            return isValidPasswordWithLegacyHash
                ? PasswordVerificationResult.SuccessRehashNeeded
                : base.VerifyHashedPassword(user, hashedPassword, providedPassword);
        }

        private const int _pbkdf2IterCount = 1000;
        private const int _pbkdf2SubkeyLength = 256 / 8;
        private const int _saltSize = 128 / 8;

        public static string HashPassword(string password)
        {
            byte[] salt;
            byte[] buffer2;
            if (password == null)
            {
                throw new ArgumentNullException("password");
            }
            using (Rfc2898DeriveBytes bytes = new Rfc2898DeriveBytes(password, 0x10, 0x3e8))
            {
                salt = bytes.Salt;
                buffer2 = bytes.GetBytes(0x20);
            }
            byte[] dst = new byte[0x31];
            Buffer.BlockCopy(salt, 0, dst, 1, 0x10);
            Buffer.BlockCopy(buffer2, 0, dst, 0x11, 0x20);
            return Convert.ToBase64String(dst);
        }

        public static bool VerifyHashedPassword(string hashedPassword, string password)
        {
            //Checks password using legacy hashing from System.Web.Helpers.Crypto
            var hashedPasswordBytes = Convert.FromBase64String(hashedPassword);
            if (hashedPasswordBytes.Length != (1 + _saltSize + _pbkdf2SubkeyLength) || hashedPasswordBytes[0] != 0x00)
            {
                return false;
            }
            var salt = new byte[_saltSize];
            Buffer.BlockCopy(hashedPasswordBytes, 1, salt, 0, _saltSize);
            var storedSubkey = new byte[_pbkdf2SubkeyLength];
            Buffer.BlockCopy(hashedPasswordBytes, 1 + _saltSize, storedSubkey, 0, _pbkdf2SubkeyLength);
            byte[] generatedSubkey;
            using (var deriveBytes = new Rfc2898DeriveBytes(password, salt, _pbkdf2IterCount))
            {
                generatedSubkey = deriveBytes.GetBytes(_pbkdf2SubkeyLength);
            }
            return ByteArraysEqual(storedSubkey, generatedSubkey);
        }

        internal static string BinaryToHex(byte[] data)
        {
            var hex = new char[data.Length * 2];
            for (var iter = 0; iter < data.Length; iter++)
            {
                var hexChar = (byte) (data[iter] >> 4);
                hex[iter * 2] = (char) (hexChar > 9 ? hexChar + 0x37 : hexChar + 0x30);
                hexChar = (byte) (data[iter] & 0xF);
                hex[iter * 2 + 1] = (char) (hexChar > 9 ? hexChar + 0x37 : hexChar + 0x30);
            }
            return new string(hex);
        }

        [MethodImpl(MethodImplOptions.NoOptimization)]
        private static bool ByteArraysEqual(byte[] a, byte[] b)
        {
            if (ReferenceEquals(a, b))
            {
                return true;
            }
            if (a == null || b == null || a.Length != b.Length)
            {
                return false;
            }
            var areSame = true;
            for (var i = 0; i < a.Length; i++)
            {
                areSame &= (a[i] == b[i]);
            }
            return areSame;
        }
    }
}

AuthorisationController before var result = await _signInManager.CheckPasswordSignInAsync(user, request.Password, lockoutOnFailure: true);

var passwordIsOld = CustomPasswordHasher.VerifyHashedPassword(user.PasswordHash,request.Password);
if(passwordIsOld){
    var newPassword = CustomPasswordHasher.HashPassword(request.Password);
    var ResetToken = await _userManager.GeneratePasswordResetTokenAsync(user);
    await _userManager.ResetPasswordAsync(user,ResetToken,request.Password);
}
asadsahi commented 6 years ago

@Daeamon sounds like you are at the right path. Have you managed to upgrade?

Daeamon commented 6 years ago

Yes all work properly. But i need a ssr for my application)))