# 2.3: Adding Auth Service

## Add Authentication Interface

Add an interface to your `.Contracts` project by right clicking on the folder name and selecting "New C# Interface" called `IAuthService.cs`.

Add method signatures for register, login, and checking whether the user already exists in the database.

```csharp
using System.Threading.Tasks;
using EFConnect.Data.Entities;

namespace EFConnect.Contracts
{
    public interface IAuthService
    {
         Task<User> Register(User user, string password);
         Task<User> Login(string username, string password);
         Task<bool> UserExists(string username);
    }
}
```

## Add Concrete AuthService

In the `.Services` project - create a new C# class called `AuthService.cs` that implements `IAuthService`.

Start by adding a constructor to inject our `DbContext`:

```csharp
public AuthService(EFConnectContext context)
{
}
```

`Ctrl + .` on the context parameter and choose `Generate field from parameter`.

```csharp
private readonly EFConnectContext _context;
public AuthService(EFConnectContext context)
{
    _context = context;
}
```

Now, `ctrl + .` on `IAuthRepository` and select `Implement interface`

```csharp
public class AuthService : IAuthService
{
    private readonly EFConnectContext _context;
    public AuthService(EFConnectContext context)
    {
        _context = context;
    }

    public Task<User> Login(string username, string password)
    {
        throw new System.NotImplementedException();
    }

    public Task<User> Register(User user, string password)
    {
        throw new System.NotImplementedException();
    }

    public Task<bool> UserExists(string username)
    {
        throw new System.NotImplementedException();
    }
}
```

## Add CreatePasswordHash Method

We'll add a private method below the public methods to create a password hash.

It will take three parameters: one will be passed by value: `password`, and two will be passed by reference: `passwordHash` and `passwordSalt` - this will allow our method to directly alter the values held by the `passwordHash` and `passwordSalt` variables.

```csharp
private void CreatePasswordHash(string password, out byte[] passwordHash, out byte[] passwordSalt)
{
    using (var hmac = new System.Security.Cryptography.HMACSHA512())    //  hmac will generate salt key
    {
        passwordSalt = hmac.Key;
        passwordHash = hmac.ComputeHash(System.Text.Encoding.UTF8.GetBytes(password));
    }
}
```

## Implement Register Method

Now that we have a method to create our salted hash, we can implement our register method.

```csharp
public async Task<User> Register(User user, string password)
{
    byte[] passwordHash, passwordSalt;
    CreatePasswordHash(password, out passwordHash, out passwordSalt);

    user.PasswordHash = passwordHash;
    user.PasswordSalt = passwordSalt;

    await _context.Users.AddAsync(user);
    await _context.SaveChangesAsync();

    return user;
}
```

## Add VerifyPasswordHash Method

Next, we need another private helper method to check the password a user enters against the hashed password saved to the database in order to implement our `Login()` method.

This method will work in the opposite direction of our `CreatePasswordHash()` method.

We'll loop through the computed hash and compare each byte against what's stored in our database. If anything doesn't match, we'll return false - otherwise, we'll return true.

```csharp
private bool VerifyPasswordHash(string password, byte[] passwordHash, byte[] passwordSalt)
{
    using (var hmac = new System.Security.Cryptography.HMACSHA512(passwordSalt))
    {
        var computedHash = hmac.ComputeHash(System.Text.Encoding.UTF8.GetBytes(password));

        for (int i = 0; i < computedHash.Length; i++)
        {
            if (computedHash[i] != passwordHash[i]) return false;
        }

        return true;
    }
}
```

## Implement Login Method

In this method, we need to compare what's stored in our database to what is entered by the user using our `VerifyPasswordHash()` method.

```csharp
public async Task<User> Login(string username, string password)
{
    var user = await _context.Users.FirstOrDefaultAsync(x => x.Username == username);

    if (user == null)
        return null;

    if (!VerifyPasswordHash(password, user.PasswordHash, user.PasswordSalt))
        return null;

    return user;
}
```

## Implement UserExists() method

```csharp
public async Task<bool> UserExists(string username)
{
    if (await _context.Users.AnyAsync(x => x.Username == username))
        return true;

    return false;
}
```
