Home > Back-end >  Migrating identity users from .NET 4.5 MVC to .NET 6 MVC project
Migrating identity users from .NET 4.5 MVC to .NET 6 MVC project

Time:04-05

As there are hashing differences for identity user passwords we need to keep old users without forcing them to renew their passwords. So I have to change hashing to old style. I am following this answer https://stackoverflow.com/a/57074910/1651298 but new hasher is not being used despite of the fact that PasswordHasher is replaced in service container.

Steps to reproduce the issue:

Create ASP Core MVC project for .NET 6 and choose Individual Accounts for authentication. Change Program.cs file:

using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Proofs.Data;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlServer(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();

builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
    .AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services.AddControllersWithViews();

var serviceDescriptor = builder.Services.FirstOrDefault(descriptor => descriptor.ServiceType == typeof(IPasswordHasher<IdentityUser>));
builder.Services.Remove(serviceDescriptor);
builder.Services.AddScoped<IPasswordHasher<IdentityUser>, OldMvcPasswordHasher>();

//builder.Services.Replace(new ServiceDescriptor(
//    serviceType: typeof(IPasswordHasher<IdentityUser>),
//    implementationType: typeof(OldMvcPasswordHasher),
//    ServiceLifetime.Scoped));

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseMigrationsEndPoint();
}
else
{
    app.UseExceptionHandler("/Home/Error");
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthentication();
app.UseAuthorization();

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");
app.MapRazorPages();

app.Run();


public class OldMvcPasswordHasher : PasswordHasher<IdentityUser>
{
    public override PasswordVerificationResult VerifyHashedPassword(IdentityUser user, string hashedPassword, string providedPassword)
    {
        return PasswordVerificationResult.SuccessRehashNeeded;
    }
}

I tried removing and adding new service, also replacing service, but new VerifyHashedPassword method is not being called when I try to log in.

CodePudding user response:

In one of my projects, I migrated existing users (with my own custom tables) into a .NET 6 project with .NET Core Identity. In the DataContext, I extended my user table by a legacy hash column from my old application.

Whenever a user tries to log in (with email password), I check if there is still a value in the legacy hash column. If that is the case,

  • I calculate the old hash based on the old mechanism and see if they match
  • If they match, I use .NET Core Identity to set the new password (based on what the user entered. The user doesn't know that I changed the underlying hash algorithm). I do this by creating a PasswordResetToken and then using the ResetPassword functionality.
  • Afterwards, I remove the legacy hash from the user row.

In your case, just set up .NET Core identity the way it should work for new users. Take care of migrating existing passwords during the login method.

  • Related