PasswordHasher added
This commit is contained in:
@@ -19,18 +19,19 @@ public static class Endpoints
|
||||
return app;
|
||||
}
|
||||
|
||||
public static async Task<Results<Created<RegisterResponse>, ProblemHttpResult>> Register(RegisterCommand command, IMediator mediator)
|
||||
public static async Task<Results<Created<RegisterResponse>, InternalServerError>> Register(RegisterRequest request, CancellationToken cancellationToken, IMediator mediator)
|
||||
{
|
||||
await mediator.Send(command);
|
||||
return Results.Created($"accounts/0", null);
|
||||
RegisterCommand registerCommand = request.ToCommand();
|
||||
RegisterData data = await mediator.Send(registerCommand, cancellationToken);
|
||||
return Results.Created<RegisterResponse>($"accounts/0", null);
|
||||
}
|
||||
|
||||
public static async Task<Results<Ok<AuthenticateResponse>, ProblemHttpResult>> AuthenticatePassword(AuthenticatePasswordRequest request)
|
||||
public static async Task<Results<Ok<AuthenticateResponse>, ProblemHttpResult>> AuthenticatePassword(AuthenticatePasswordRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public static async Task<Results<Ok<AuthenticateResponse>, ProblemHttpResult>> AuthenticateToken(AuthenticateTokenRequest request)
|
||||
public static async Task<Results<Ok<AuthenticateResponse>, ProblemHttpResult>> AuthenticateToken(AuthenticateTokenRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ using Microsoft.EntityFrameworkCore;
|
||||
using TimetableDesigner.Backend.Services.Authentication.Database;
|
||||
using TimetableDesigner.Backend.Services.Authentication.DTO.API;
|
||||
|
||||
namespace TimetableDesigner.Backend.Services.Authentication.DTO.Validators;
|
||||
namespace TimetableDesigner.Backend.Services.Authentication.API.Validators;
|
||||
|
||||
public class RegisterRequestValidator : AbstractValidator<RegisterRequest>
|
||||
{
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
|
||||
namespace TimetableDesigner.Backend.Services.Authentication.Application.Commands.Register;
|
||||
|
||||
public record RegisterCommand(string Email, string Password) : IRequest;
|
||||
public record RegisterCommand(string Email, string Password) : IRequest<RegisterData>;
|
||||
@@ -1,6 +1,6 @@
|
||||
namespace TimetableDesigner.Backend.Services.Authentication.Application.Commands.Register;
|
||||
|
||||
public class RegisterDto
|
||||
public class RegisterData
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,19 +1,23 @@
|
||||
using MediatR;
|
||||
using TimetableDesigner.Backend.Services.Authentication.Application.Helpers;
|
||||
using TimetableDesigner.Backend.Services.Authentication.Database;
|
||||
|
||||
namespace TimetableDesigner.Backend.Services.Authentication.Application.Commands.Register;
|
||||
|
||||
public class RegisterHandler : IRequestHandler<RegisterCommand>
|
||||
public class RegisterHandler : IRequestHandler<RegisterCommand, RegisterData>
|
||||
{
|
||||
private readonly DatabaseContext _databaseContext;
|
||||
private readonly IPasswordHasher _passwordHasher;
|
||||
|
||||
public RegisterHandler(DatabaseContext databaseContext)
|
||||
public RegisterHandler(DatabaseContext databaseContext, IPasswordHasher passwordHasher)
|
||||
{
|
||||
_databaseContext = databaseContext;
|
||||
_passwordHasher = passwordHasher;
|
||||
}
|
||||
|
||||
public async Task Handle(RegisterCommand command, CancellationToken cancellationToken)
|
||||
public async Task<RegisterData> Handle(RegisterCommand command, CancellationToken cancellationToken)
|
||||
{
|
||||
PasswordHashData hash = _passwordHasher.CreateHash(command.Password);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
using TimetableDesigner.Backend.Services.Authentication.Application.Commands.Register;
|
||||
using TimetableDesigner.Backend.Services.Authentication.DTO.API;
|
||||
using TimetableDesigner.Backend.Services.Authentication.DTO.API;
|
||||
|
||||
namespace TimetableDesigner.Backend.Services.Authentication.DTO.Mappers;
|
||||
namespace TimetableDesigner.Backend.Services.Authentication.Application.Commands.Register;
|
||||
|
||||
public static class RegisterMappers
|
||||
{
|
||||
|
||||
@@ -3,5 +3,5 @@
|
||||
public interface IPasswordHasher
|
||||
{
|
||||
PasswordHashData CreateHash(string password);
|
||||
byte[] ComputeHash(string password, string salt);
|
||||
bool ValidatePassword(PasswordHashData hash, string password);
|
||||
}
|
||||
@@ -2,6 +2,5 @@
|
||||
|
||||
public record PasswordHashData(
|
||||
byte[] Hash,
|
||||
string LeftSalt,
|
||||
string RightSalt
|
||||
string Salt
|
||||
);
|
||||
@@ -1,6 +1,39 @@
|
||||
namespace TimetableDesigner.Backend.Services.Authentication.Application.Helpers;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using Konscious.Security.Cryptography;
|
||||
|
||||
public class PasswordHasher
|
||||
namespace TimetableDesigner.Backend.Services.Authentication.Application.Helpers;
|
||||
|
||||
public class PasswordHasher : IPasswordHasher
|
||||
{
|
||||
|
||||
private const string RandomPasswordCharacters = "QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm1234567890!@#$%^&*()-_=+[{]};:'\"\\|,<.>/?";
|
||||
|
||||
public PasswordHashData CreateHash(string password)
|
||||
{
|
||||
string salt = RandomNumberGenerator.GetString(RandomPasswordCharacters, 20);
|
||||
byte[] hash = ComputeHash(password, salt);
|
||||
PasswordHashData data = new PasswordHashData(hash, salt);
|
||||
return data;
|
||||
}
|
||||
|
||||
public bool ValidatePassword(PasswordHashData hash, string password)
|
||||
{
|
||||
byte[] actualHash = hash.Hash;
|
||||
byte[] checkedHash = ComputeHash(password, hash.Salt);
|
||||
bool checkResult = checkedHash.SequenceEqual(actualHash);
|
||||
return checkResult;
|
||||
}
|
||||
|
||||
protected byte[] ComputeHash(string password, string salt)
|
||||
{
|
||||
Argon2id hashFunction = new Argon2id(Encoding.UTF8.GetBytes(password))
|
||||
{
|
||||
Salt = Encoding.UTF8.GetBytes(salt),
|
||||
DegreeOfParallelism = 8,
|
||||
MemorySize = 65536,
|
||||
Iterations = 4
|
||||
};
|
||||
byte[] hash = hashFunction.GetBytes(32);
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
@@ -3,8 +3,9 @@ using FluentValidation;
|
||||
using Microsoft.AspNetCore.Identity.Data;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using TimetableDesigner.Backend.Services.Authentication.API;
|
||||
using TimetableDesigner.Backend.Services.Authentication.API.Validators;
|
||||
using TimetableDesigner.Backend.Services.Authentication.Application.Helpers;
|
||||
using TimetableDesigner.Backend.Services.Authentication.Database;
|
||||
using TimetableDesigner.Backend.Services.Authentication.DTO.Validators;
|
||||
|
||||
namespace TimetableDesigner.Backend.Services.Authentication;
|
||||
|
||||
@@ -16,6 +17,7 @@ public static class Program
|
||||
.SetupOpenApi()
|
||||
.SetupSecurity()
|
||||
.SetupDatabase()
|
||||
.SetupHelpers()
|
||||
.SetupValidation()
|
||||
.SetupMediatR()
|
||||
.Build();
|
||||
@@ -46,6 +48,12 @@ public static class Program
|
||||
builder.Services.AddDbContext<DatabaseContext>(x => x.UseNpgsql(builder.Configuration.GetConnectionString("Database")), ServiceLifetime.Transient);
|
||||
return builder;
|
||||
}
|
||||
|
||||
private static WebApplicationBuilder SetupHelpers(this WebApplicationBuilder builder)
|
||||
{
|
||||
builder.Services.AddSingleton<IPasswordHasher, PasswordHasher>();
|
||||
return builder;
|
||||
}
|
||||
|
||||
private static WebApplicationBuilder SetupValidation(this WebApplicationBuilder builder)
|
||||
{
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="FluentValidation" Version="12.1.1" />
|
||||
<PackageReference Include="Konscious.Security.Cryptography.Argon2" Version="1.3.1" />
|
||||
<PackageReference Include="MediatR" Version="14.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.9" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="9.0.9">
|
||||
@@ -19,10 +20,6 @@
|
||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.4" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="DTO\Mappers\" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\TimetableDesigner.Backend.Services.Authentication.DTO\TimetableDesigner.Backend.Services.Authentication.DTO.API\TimetableDesigner.Backend.Services.Authentication.DTO.API.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
Reference in New Issue
Block a user