In this post, I will look at how to extend the ASP .NET Core Identity membership system to use a custom class for hashing passwords. ASP .NET Core Identity is very extendable and extending it is a good way to get a better understanding of how the system works. We can customize it by providing new implementations to its interfaces. This code is not production ready and any custom security implementation should be done with care and be backed by good reasons. That being said, lets have some fun. This tutorial requires Visual Studio 2017, dotnet core 2.0, and LocalDb, which should be installed with Visual Studio depending on which components were picked at the time of install. The entire sample project is available on Github.
.NET Core and
ASP.NET Core 2.0 from the dropdowns at the top. Select
Web Application (Model-View-Controller) for the template and select Change Authentication and pick
Individual User Accounts.
The first time an error will appear. This is because we haven’t created the database yet. Click on Apply Migrations. This will create the database using Entity Framework. All the required database stuff is defined by the template and the defaults will work for this demonstration.
Once that is done, the button text changes to Migrations Applied. Refresh the page and click yes at any browser prompts about resubmitting the form. The home page will reload and the top menu bar will show the test user logged in.
If you get an error starting with
SqlException: A network-related or instance-specific error occurred while establishing a connection to SQL Server... check the server in the app settings connection string. This can be found in the
appsettings.json file. The Visual Studio
Sql Server Object Explorer will tell you the server path to LocalDb. Make sure the connection string matches this path. If not, change it and then stop and restart debugging.
After the page reloads with the user logged in, a record is also created in the database for this user. To see that, open the
SQL Server Object Explorder in Visual Studio. It should auto-connect to LocalDb. The database name will contain the project name. Once you find it, query the AspNetUsers table like this
SELECT * FROM dbo.AspNetUsers. There is 1 row with the registered user.
As this point, we have a working default MVC template with Individual User Accounts. We will now supplement this with a class to do our own password hashing. This is to demonstrate how different components of the Identity membership system can be customized. Create a new class named
CustomPasswordHasher and have it implement
IPasswordHasher<ApplicationUser>. There are 2 methods we need to implement,
string HashPassword(TUser user, string password) and
PasswordVerificationResult VerifyHashedPassword(TUser user, string hashedPassword, string providedPassword). Our custom class will reverse the original password string. This is to demonstrate how the methods will be used. In a real application, this would contain a secure, well planned, and well tested implementation. The full class is below. This should not be used in a real application.
public class CustomPasswordHasher : IPasswordHasher<ApplicationUser>
public string HashPassword(ApplicationUser user, string password)
public PasswordVerificationResult VerifyHashedPassword(ApplicationUser user, string hashedPassword, string providedPassword)
if (hashedPassword == ReversePassword(providedPassword))
private string ReversePassword(string value)
// This is not a secure way to store a password!
char charArray = value.ToCharArray();
return new string(charArray);
The final thing to do is register our new implementation with the dependency injection system. This happens in the
ConfigureServices method of the
Startup class. Copy/Paste the following line as the first line of the method:
services.AddTransient<IPasswordHasher<ApplicationUser>, CustomPasswordHasher>();. To learn more about Dependency injection in ASP .NET Core, check out my post "ASP .NET Core MVC Dependency Injection Overview". The full
ConfigureServices method is below.
public void ConfigureServices(IServiceCollection services)
// Add application services.
The only thing left to do is test it. Place a breakpoint in both the HashPassword and VerifyHashedPassword methods. Start debugging and register a new user, like we did above. On registration, the HashPassword breakpoint will be hit and on login the VerifyHashedPassword method will be hit. In both cases, the user will be logged in. If you got this far, it means you have successfully created a custom password hasher for ASP .NET Core Identity!
In conclusion, this post shows 1 example of overriding a feature of ASP .NET Core Identity. The complete code can be found in this Github repository. This code is for educational purposes only and is not meant for production environments. Thought, planning, and good reasons need to be involved for authentication code meant for a production environment. That being said, it is possible to customize many parts of the ASP .NET Core Identity system. In my next post, I will expand on this with an example of customizing the user store component to allow user accounts to be stored in memory instead of a database.