Open Closed

How to override IPasswordHasher<> #855


User avatar
0
tim created

We are migrating a lagacy app to ABP framework. The existing user password was encryted with MD5 encrytion.

I am following the post below trying to override the IPasswordHasher<>:

https://andrewlock.net/safely-migrating-passwords-in-asp-net-core-identity-with-a-custom-passwordhasher/

I am updating the Startup.cs file under xxx.HttpApi.Host project:

using ApplicationHelpers;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Logging;
using System;
using System.Text;
using Volo.Abp.Identity;

namespace Bookstore
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddApplication<BookstoreHttpApiHostModule>();

            // Replace the existing scoped IPasswordHasher<> implementation
            services.Replace(new ServiceDescriptor(
                serviceType: typeof(IPasswordHasher<Microsoft.AspNetCore.Identity.IdentityUser>),
                implementationType: typeof(Md5PasswordHasher<Microsoft.AspNetCore.Identity.IdentityUser>),
                ServiceLifetime.Scoped));
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory)
        {
            app.InitializeApplication();
        }
    }

    /// <summary>
    /// A drop-in replacement for the standard Identity hasher to be backwards compatible with existing MD5 hashes
    /// New passwords will be hashed with Identity V3
    /// </summary>
    public class Md5PasswordHasher<TUser> : PasswordHasher<TUser> where TUser : class
    {
        public override PasswordVerificationResult VerifyHashedPassword(TUser user, string hashedPassword, string providedPassword)
        {
            byte[] decodedHashedPassword = Convert.FromBase64String(hashedPassword);

            // read the format marker from the hashed password
            if (decodedHashedPassword.Length == 0)
            {
                return PasswordVerificationResult.Failed;
            }

            // ASP.NET Core uses 0x00 and 0x01 for v2 and v3
            if (decodedHashedPassword[0] == 0xFF)
            {
                //convert back to string for MD5 encrypt, ignoring first byte
                var storedHash = Encoding.UTF8.GetString(decodedHashedPassword, 1, decodedHashedPassword.Length - 1);

                // md5 hash the provided password
                var md5ProvidedPassword = Cryptography.GeneratePassword(providedPassword);

                if (md5ProvidedPassword == storedHash)
                {
                    // This is an old password hash format - the caller needs to rehash if we're not running in an older compat mode.
                    return PasswordVerificationResult.Success;
                }
                else
                {
                    return PasswordVerificationResult.Failed;
                }
            }

            return base.VerifyHashedPassword(user, hashedPassword, providedPassword);
        }

    }
}

It does not seem like the implimentation gets overrode.

Please let me know how to override IPasswordHasher<>

Thanks, Tim

Markdown supported.
Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)

9 Answer(s)
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    You need use the Volo.Abp.Identity.IdentityUser as TUser.

    public override void PreConfigureServices(ServiceConfigurationContext context)
    {
        context.Services.PreConfigure<IdentityBuilder>(options =>
        {
            options.Services.Replace(ServiceDescriptor
                .Scoped<IPasswordHasher<Volo.Abp.Identity.IdentityUser>,
                    Md5PasswordHasher<Volo.Abp.Identity.IdentityUser>>());
        });
    }
    
    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    tim created

    Hi Thanks for getting back to you.

    Is this what you meant:

    1. Remove this funtion call from startup.cs // Replace the existing scoped IPasswordHasher<> implementation services.Replace(new ServiceDescriptor( serviceType: typeof(IPasswordHasher<Microsoft.AspNetCore.Identity.IdentityUser>), implementationType: typeof(Md5PasswordHasher<Microsoft.AspNetCore.Identity.IdentityUser>), ServiceLifetime.Scoped));
    2. which project/class to put this method in public override void PreConfigureServices(ServiceConfigurationContext context) { context.Services.PreConfigure<IdentityBuilder>(options => { options.Services.Replace(ServiceDescriptor .Scoped<IPasswordHasher<Volo.Abp.Identity.IdentityUser>, Md5PasswordHasher<Volo.Abp.Identity.IdentityUser>>()); }); }
    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer
    1. Remove this funtion call from startup.cs

    Yes.

    2.which project/class to put this method in

    Projects that depend on AbpAccountWebModule, such as web.

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    tim created

    I just tried on the start-up template (bookstore) and put the code in the Bookstore.Application project and still did not work?

    public class BookstoreApplicationModule : AbpModule
    {
        public override void ConfigureServices(ServiceConfigurationContext context)
        {
            Configure<AbpAutoMapperOptions>(options =>
            {
                options.AddMaps<CROMS3ApplicationModule>();
            });
        }
    
        public override void PreConfigureServices(ServiceConfigurationContext context)
        {
            context.Services.PreConfigure<IdentityBuilder>(options =>
            {
                options.Services.Replace(ServiceDescriptor
                    .Scoped<IPasswordHasher<Volo.Abp.Identity.IdentityUser>,
                        Md5PasswordHasher<Volo.Abp.Identity.IdentityUser>>());
            });
        }
    
        ```
    
    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    tim created

    BTW, my solution is an Angular font end with .NET core API backend.

    I did a full text search and I did not find any project that depends on AbpAccountWebModule?

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    Can you share your Bookstore project to me? liming.ma@volosoft.com

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    tim created

    It actually worked. Thanks very much!

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    : )

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    ServiceBot created
    Support Team Automatic process manager

    This question has been automatically marked as stale because it has not had recent activity.

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
Boost Your Development
ABP Live Training
Packages
See Trainings
Mastering ABP Framework Book
The Official Guide
Mastering
ABP Framework
Learn More
Mastering ABP Framework Book
Made with ❤️ on ABP v10.8.0-preview. Updated on September 16, 2026, 14:50
1
ABP Assistant
🔐 You need to be logged in to use the chatbot. Please log in first.