access token generation added

This commit is contained in:
2026-01-30 00:18:25 +01:00
Unverified
parent 236a7a0fe1
commit dc12ee75e5
8 changed files with 96 additions and 16 deletions

View File

@@ -10,11 +10,13 @@ public class AuthPasswordHandler : IRequestHandler<AuthPasswordCommand, AuthPass
{
private readonly DatabaseContext _databaseContext;
private readonly IPasswordHasher _passwordHasher;
private readonly ITokenGenerator _tokenGenerator;
public AuthPasswordHandler(DatabaseContext databaseContext, IPasswordHasher passwordHasher)
public AuthPasswordHandler(DatabaseContext databaseContext, IPasswordHasher passwordHasher, ITokenGenerator tokenGenerator)
{
_databaseContext = databaseContext;
_passwordHasher = passwordHasher;
_tokenGenerator = tokenGenerator;
}
public async Task<AuthPasswordResult> Handle(AuthPasswordCommand request, CancellationToken cancellationToken)
@@ -31,6 +33,8 @@ public class AuthPasswordHandler : IRequestHandler<AuthPasswordCommand, AuthPass
return AuthPasswordResult.Failure();
}
string accessToken = _tokenGenerator.GenerateAccessToken(account);
return null;
}
}

View File

@@ -1,4 +1,5 @@
using MediatR;
using Microsoft.EntityFrameworkCore.Storage;
using TimetableDesigner.Backend.Events.OutboxPattern;
using TimetableDesigner.Backend.Services.Authentication.Core.Helpers;
using TimetableDesigner.Backend.Services.Authentication.Database;
@@ -28,13 +29,18 @@ public class RegisterHandler : IRequestHandler<RegisterCommand, RegisterResult>
Password = hash.Hash,
PasswordSalt = hash.Salt,
};
await _databaseContext.Accounts.AddAsync(account, cancellationToken);
await _databaseContext.SaveChangesAsync(cancellationToken);
Event eventData = Event.Create(new RegisterEvent(account.Id, account.Email));
await _databaseContext.Events.AddAsync(eventData, cancellationToken);
await _databaseContext.SaveChangesAsync(cancellationToken);
await using (IDbContextTransaction transaction = await _databaseContext.Database.BeginTransactionAsync(cancellationToken))
{
await _databaseContext.Accounts.AddAsync(account, cancellationToken);
await _databaseContext.SaveChangesAsync(cancellationToken);
Event eventData = Event.Create(new RegisterEvent(account.Id, account.Email));
await _databaseContext.Events.AddAsync(eventData, cancellationToken);
await _databaseContext.SaveChangesAsync(cancellationToken);
await transaction.CommitAsync(cancellationToken);
}
return new RegisterResult(account.Id, account.Email);
}

View File

@@ -0,0 +1,10 @@
using TimetableDesigner.Backend.Services.Authentication.Database.Model;
namespace TimetableDesigner.Backend.Services.Authentication.Core.Helpers;
public interface ITokenGenerator
{
string GenerateAccessToken(Account account);
Task<string> GenerateRefreshTokenAsync(Account account);
Task<string> ExtendRefreshTokenAsync();
}

View File

@@ -1,27 +1,68 @@
using Microsoft.Extensions.Configuration;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.Tokens;
using TimetableDesigner.Backend.Services.Authentication.Database;
using TimetableDesigner.Backend.Services.Authentication.Database.Model;
using JwtRegisteredClaimNames = Microsoft.IdentityModel.JsonWebTokens.JwtRegisteredClaimNames;
namespace TimetableDesigner.Backend.Services.Authentication.Core.Helpers;
public class TokenGenerator
public class TokenGenerator : ITokenGenerator
{
/*
private readonly IConfiguration _configuration;
private readonly DatabaseContext _databaseContext;
public TokenGenerator(IConfiguration configuration, DatabaseContext databaseContext)
{
_configuration = configuration;
_databaseContext = databaseContext;
}
public string GenerateAccessToken(Account account)
{
IConfigurationSection accessTokenSettings = _configuration.GetSection("Tokens")
.GetSection("AccessToken");
int lifetime = accessTokenSettings.GetSection("Lifetime")
.GetValue<int>("Normal");
DateTimeOffset expirationDate = DateTimeOffset.UtcNow.AddMinutes(lifetime);
string stringKey = accessTokenSettings.GetValue<string>("Key")!;
byte[] encodedKey = Encoding.UTF8.GetBytes(stringKey);
SymmetricSecurityKey key = new SymmetricSecurityKey(encodedKey);
string algorithm = accessTokenSettings.GetValue<string>("Algorithm")!;
SecurityTokenDescriptor descriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(
[
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
new Claim(JwtRegisteredClaimNames.Sub, account.Id.ToString()),
new Claim(JwtRegisteredClaimNames.Exp, expirationDate.UtcTicks.ToString())
]),
Issuer = accessTokenSettings.GetValue<string>("Issuer"),
Audience = accessTokenSettings.GetValue<string>("Audience"),
SigningCredentials = new SigningCredentials(key, algorithm),
Expires = expirationDate.UtcDateTime,
};
JwtSecurityTokenHandler handler = new JwtSecurityTokenHandler();
handler.InboundClaimTypeMap.Clear();
SecurityToken token = handler.CreateToken(descriptor);
return handler.WriteToken(token);
}
public async Task<string> GenerateRefreshTokenAsync(Account account)
{
return null;
}
public async Task<string> ExtendRefreshTokenAsync()
{
}*/
return null;
}
}

View File

@@ -14,6 +14,7 @@
<ItemGroup>
<PackageReference Include="Konscious.Security.Cryptography.Argon2" Version="1.3.1" />
<PackageReference Include="MediatR" Version="14.0.0" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.15.0" />
</ItemGroup>
</Project>

View File

@@ -52,6 +52,7 @@ public static class Program
private static IServiceCollection AddHelpers(this IServiceCollection services)
{
services.AddSingleton<IPasswordHasher, PasswordHasher>();
services.AddScoped<ITokenGenerator, TokenGenerator>();
return services;
}

View File

@@ -19,7 +19,7 @@
</PackageReference>
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="10.0.0" />
<PackageReference Include="timetabledesigner.backend.events.extensions.aspnetcore.openapi" Version="1.0.2" />
<PackageReference Include="timetabledesigner.backend.events.outboxpattern" Version="1.1.2" />
<PackageReference Include="timetabledesigner.backend.events.outboxpattern" Version="1.1.3" />
<PackageReference Include="TimetableDesigner.Backend.Events.Providers.RabbitMQ" Version="1.0.5" />
</ItemGroup>

View File

@@ -9,5 +9,22 @@
"ConnectionStrings": {
"Database": "Host=localhost;Port=5433;Database=ttd_authentication;Username=postgres;Password=l4JxOIuSoyod86N;Include Error Detail=True",
"EventQueue": "Hostname=localhost;Port=5672;Username=user;Password=l4JxOIuSoyod86N;ExchangeName=events;QueuePrefix=authentication"
},
"Tokens": {
"AccessToken": {
"Lifetime": {
"Normal": 5
},
"Issuer": "auth.timetabledesigner.com",
"Audience": "timetabledesigner.com",
"Key": "testkeytestkeytestkeytestkeytestkeytestkeytestkeytestkeytestkeytestkeytestkeytestkeytestkeytestkeytest",
"Algorithm": "HS512"
},
"RefreshToken": {
"Lifetime": {
"Normal": 1440,
"Extended": 10080
}
}
}
}