PasswordHasher added
This commit is contained in:
@@ -19,18 +19,19 @@ public static class Endpoints
|
|||||||
return app;
|
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);
|
RegisterCommand registerCommand = request.ToCommand();
|
||||||
return Results.Created($"accounts/0", null);
|
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;
|
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;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ using Microsoft.EntityFrameworkCore;
|
|||||||
using TimetableDesigner.Backend.Services.Authentication.Database;
|
using TimetableDesigner.Backend.Services.Authentication.Database;
|
||||||
using TimetableDesigner.Backend.Services.Authentication.DTO.API;
|
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>
|
public class RegisterRequestValidator : AbstractValidator<RegisterRequest>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,4 +2,4 @@
|
|||||||
|
|
||||||
namespace TimetableDesigner.Backend.Services.Authentication.Application.Commands.Register;
|
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;
|
namespace TimetableDesigner.Backend.Services.Authentication.Application.Commands.Register;
|
||||||
|
|
||||||
public class RegisterDto
|
public class RegisterData
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,19 +1,23 @@
|
|||||||
using MediatR;
|
using MediatR;
|
||||||
|
using TimetableDesigner.Backend.Services.Authentication.Application.Helpers;
|
||||||
using TimetableDesigner.Backend.Services.Authentication.Database;
|
using TimetableDesigner.Backend.Services.Authentication.Database;
|
||||||
|
|
||||||
namespace TimetableDesigner.Backend.Services.Authentication.Application.Commands.Register;
|
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 DatabaseContext _databaseContext;
|
||||||
|
private readonly IPasswordHasher _passwordHasher;
|
||||||
|
|
||||||
public RegisterHandler(DatabaseContext databaseContext)
|
public RegisterHandler(DatabaseContext databaseContext, IPasswordHasher passwordHasher)
|
||||||
{
|
{
|
||||||
_databaseContext = databaseContext;
|
_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
|
public static class RegisterMappers
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,5 +3,5 @@
|
|||||||
public interface IPasswordHasher
|
public interface IPasswordHasher
|
||||||
{
|
{
|
||||||
PasswordHashData CreateHash(string password);
|
PasswordHashData CreateHash(string password);
|
||||||
byte[] ComputeHash(string password, string salt);
|
bool ValidatePassword(PasswordHashData hash, string password);
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,5 @@
|
|||||||
|
|
||||||
public record PasswordHashData(
|
public record PasswordHashData(
|
||||||
byte[] Hash,
|
byte[] Hash,
|
||||||
string LeftSalt,
|
string Salt
|
||||||
string RightSalt
|
|
||||||
);
|
);
|
||||||
@@ -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.AspNetCore.Identity.Data;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using TimetableDesigner.Backend.Services.Authentication.API;
|
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.Database;
|
||||||
using TimetableDesigner.Backend.Services.Authentication.DTO.Validators;
|
|
||||||
|
|
||||||
namespace TimetableDesigner.Backend.Services.Authentication;
|
namespace TimetableDesigner.Backend.Services.Authentication;
|
||||||
|
|
||||||
@@ -16,6 +17,7 @@ public static class Program
|
|||||||
.SetupOpenApi()
|
.SetupOpenApi()
|
||||||
.SetupSecurity()
|
.SetupSecurity()
|
||||||
.SetupDatabase()
|
.SetupDatabase()
|
||||||
|
.SetupHelpers()
|
||||||
.SetupValidation()
|
.SetupValidation()
|
||||||
.SetupMediatR()
|
.SetupMediatR()
|
||||||
.Build();
|
.Build();
|
||||||
@@ -46,6 +48,12 @@ public static class Program
|
|||||||
builder.Services.AddDbContext<DatabaseContext>(x => x.UseNpgsql(builder.Configuration.GetConnectionString("Database")), ServiceLifetime.Transient);
|
builder.Services.AddDbContext<DatabaseContext>(x => x.UseNpgsql(builder.Configuration.GetConnectionString("Database")), ServiceLifetime.Transient);
|
||||||
return builder;
|
return builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static WebApplicationBuilder SetupHelpers(this WebApplicationBuilder builder)
|
||||||
|
{
|
||||||
|
builder.Services.AddSingleton<IPasswordHasher, PasswordHasher>();
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
private static WebApplicationBuilder SetupValidation(this WebApplicationBuilder builder)
|
private static WebApplicationBuilder SetupValidation(this WebApplicationBuilder builder)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="FluentValidation" Version="12.1.1" />
|
<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="MediatR" Version="14.0.0" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.9" />
|
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.9" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" 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" />
|
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.4" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Folder Include="DTO\Mappers\" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\TimetableDesigner.Backend.Services.Authentication.DTO\TimetableDesigner.Backend.Services.Authentication.DTO.API\TimetableDesigner.Backend.Services.Authentication.DTO.API.csproj" />
|
<ProjectReference Include="..\TimetableDesigner.Backend.Services.Authentication.DTO\TimetableDesigner.Backend.Services.Authentication.DTO.API\TimetableDesigner.Backend.Services.Authentication.DTO.API.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
Reference in New Issue
Block a user