.NET Core 3.0 (Preview 4) Web API Authentication from Scratch (Part 2): Password Hashing.

Repository Pattern, Password Hashing, Password Salting

Nishān Wickramarathna
6 min readMay 6, 2019
Salting at a glance (Image courtesy of Wordfence)

Note: This article is originally written for .NET Core 3.0 (Preview 4), so in some places you will see —- version flag when I install packages. Feel free to install the latest version by removing the —- version flag, newer versions should work as expected. As an example you can use dotnet add package System.IdentityModel.Tokens.Jwt instead of dotnet add package System.IdentityModel.Tokens.Jwt — version 5.4.0

Note 2: I have updated the project to .NET 5.0 can be accessed from following URL. It’s not a frustrating process, as mentioned earlier make sure packages are at latest version.

Previous article showed you how to configure .NET Core 3.0 with SQL Server, retrieve data from database etc. If you are not familiar with those things, give it a read. In this article, You will learn,

  1. How to store passwords in database (register users)
  2. The repository design pattern

Password Hashing

A hash is just a way to represent any data as a unique string of characters, It allows you to take an input of any length and turn it into a string of characters that is always the same length. Obviously, there are many methods (algorithms) to do this.

  • MD5 — Given any data will return a unique 32 character hash.
  • SHA1 — Given any data will return a unique 40 character hash.
  • SHA256 — Given any data will return a unique 64 character hash; designed by the National Security Agency.
  • SHA512 — Given any data will return a unique 128 character hash; designed by the National Security Agency.

Is Hashing Secure? Yes, kind of..

Yes, because hashing is a one way operation. They cannot be reversed. Given the string,

B109F3BBBC244EB82441917ED06D618B9008DD09B3BEFD1B5E07394C706A8BB980B1D7785E5976EC049B46DF5F1326AF5A2EA6D103FD07C95385FFAB0CACBC86

There’s no way we can get the word “password” from it. But we need to prepare for the worst case scenario. Obviously password is not a good password! because it is too easy to guess. Problem is, same set of characters will produce the same hash. If two people use the same password, the hashes generated will be the same.

So there are some databases available which contains decoded hashes. Take a look at this web site which contains more than 2.000.000.000 hashes (according to them). https://md5decrypt.net/en/Sha512/ Visit there and paste above hash, see it correctly identifies it is password

So weak passwords don’t stand a chance!. What can we do about it? In addition to hashing, we also will add a Salt to a password. A salt is randomly generated and added to the password before hashing. Then we apply the hashing function. Obviously this increases the security. Let’s quickly create User model and update the database.

In Models folder create the user class as follows. PasswordHash to store the hash and PasswordSalt to store the Salt.

Now we need to make Entity Framework aware our new model, so go to DataContext class and register our new model.

public DbSet<User> Users { get; set; }

Lets add migration and update the database. Save everything and run,

dotnet ef migrations add AddedUserModel

Take a look at the Migrations folder, and check if AddedUserModel is created and it has relevant content similar to this. If everything looks ok, update the database.

dotnet ef database update

Take a look at the database and verify everything is created as intended.

Repository Pattern

The Repository Design Pattern in C# Mediates between the domain and the data mapping layers using a collection-like interface for accessing the domain objects. In other words, we can say that a Repository Design Pattern acts as a middleman or middle layer between the rest of the application and the data access logic.

Let’s try to understand it. We already have one level of abstraction between database and controllers right?, which is the Entity Framework. We query entity framework and it takes care of the data retrieval. Entity Framework translates our requests to SQL queries. But there’s a problem with this approach, In the future if we want to remove this ORM (Object Relational Mapper, which is the Entity Framework in this case), to another ORM, we have to re write all the controllers.

Look at this diagram, on left you will see that without repository we have direct access to DbContext, with repository (on right) you have a custom abstraction layer between database context and controller.

Repository interface exposes methods that the controller can utilize. Controller does not need to know how these methods are utilized, only needs to know what methods are available.

.

  • It centralizes data logic or business logic and service logic.
  • It gives a substitution point for the unit tests.
  • Provides a flexible architecture.
In the future if you want to change the logic in repository, it is safe to do it, since it doesn’t affect controllers. If you have same logic duplicated in the controller, with repository pattern, those code get moved to repository implementation reducing code re-use.

Now let’s create repository for authentication.

Let’s create IAuthRepository interface inside Data folder. It has 3 methods. One for registering users, login users and another to check if the user exists. don’t forget using statements on top.

Next we’ll look at how to implement these methods. Again in Data folder create AuthRepository class and implement the interface.

Now let’s inject DataContext to AuthRepository

We will look at the register method first. We are not going to save the password as it is, we are hashing it, in case you forgot!. Let’s go ahead and write the algorithm to hash passwords and generate salts.

When we call the method CreatePasswordHash(password, out passwordHash, out passwordSalt); notice the out keyword. This is because when we declare passwordHash and passwordSalt we haven’t initialized it with any values. Because simply we don’t know them yet. But when we call CreatePasswordHash(...); we need to pass values. So what we are doing is passing a reference to those local variables, not the values, that’s what the out does.

var hmac = System.Security.Cryptography.HMACSHA512() initializes a new instance of System.Security.Cryptography.HMACSHA512() class with a randomly generated key. This key is going to be our password salt. We use using keyword because hash algorithm classes implements IDisposable interface, meaning that once the work is done this method will be disposed, not waiting for the garbage collector, without consuming more memory.

Next we’ll implement login method. It is self explanatory because what we need to do is create the hash using the password which the user entered with the help of password salt, and then compare those to hashes to check if they match. We’ll use a for loop to cycle through the byte array to check there is any mismatch.

One method remains. UserExists() Which is straight forward. If there is any user with a given username, return true.

Full code for AuthRepository.cs

Auth Repository is complete. Now we need to register it in our startup class. Don’t forget,

using JWTAuth.API.Data;
using Microsoft.EntityFrameworkCore;

For every http request we want a new instance of AuthRepository That is why we say AddScoped Take a look at this if you want to know AddTransient, AddScoped and AddSingleton services differences.

In the next article, we will implement the controller logic to accept requests to login and register users. Happy coding!

Consider helping me out!

--

--

Responses (2)