access token generation added
This commit is contained in:
@@ -10,11 +10,13 @@ public class AuthPasswordHandler : IRequestHandler<AuthPasswordCommand, AuthPass
|
|||||||
{
|
{
|
||||||
private readonly DatabaseContext _databaseContext;
|
private readonly DatabaseContext _databaseContext;
|
||||||
private readonly IPasswordHasher _passwordHasher;
|
private readonly IPasswordHasher _passwordHasher;
|
||||||
|
private readonly ITokenGenerator _tokenGenerator;
|
||||||
|
|
||||||
public AuthPasswordHandler(DatabaseContext databaseContext, IPasswordHasher passwordHasher)
|
public AuthPasswordHandler(DatabaseContext databaseContext, IPasswordHasher passwordHasher, ITokenGenerator tokenGenerator)
|
||||||
{
|
{
|
||||||
_databaseContext = databaseContext;
|
_databaseContext = databaseContext;
|
||||||
_passwordHasher = passwordHasher;
|
_passwordHasher = passwordHasher;
|
||||||
|
_tokenGenerator = tokenGenerator;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<AuthPasswordResult> Handle(AuthPasswordCommand request, CancellationToken cancellationToken)
|
public async Task<AuthPasswordResult> Handle(AuthPasswordCommand request, CancellationToken cancellationToken)
|
||||||
@@ -31,6 +33,8 @@ public class AuthPasswordHandler : IRequestHandler<AuthPasswordCommand, AuthPass
|
|||||||
return AuthPasswordResult.Failure();
|
return AuthPasswordResult.Failure();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string accessToken = _tokenGenerator.GenerateAccessToken(account);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using MediatR;
|
using MediatR;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage;
|
||||||
using TimetableDesigner.Backend.Events.OutboxPattern;
|
using TimetableDesigner.Backend.Events.OutboxPattern;
|
||||||
using TimetableDesigner.Backend.Services.Authentication.Core.Helpers;
|
using TimetableDesigner.Backend.Services.Authentication.Core.Helpers;
|
||||||
using TimetableDesigner.Backend.Services.Authentication.Database;
|
using TimetableDesigner.Backend.Services.Authentication.Database;
|
||||||
@@ -28,6 +29,9 @@ public class RegisterHandler : IRequestHandler<RegisterCommand, RegisterResult>
|
|||||||
Password = hash.Hash,
|
Password = hash.Hash,
|
||||||
PasswordSalt = hash.Salt,
|
PasswordSalt = hash.Salt,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
await using (IDbContextTransaction transaction = await _databaseContext.Database.BeginTransactionAsync(cancellationToken))
|
||||||
|
{
|
||||||
await _databaseContext.Accounts.AddAsync(account, cancellationToken);
|
await _databaseContext.Accounts.AddAsync(account, cancellationToken);
|
||||||
await _databaseContext.SaveChangesAsync(cancellationToken);
|
await _databaseContext.SaveChangesAsync(cancellationToken);
|
||||||
|
|
||||||
@@ -35,6 +39,8 @@ public class RegisterHandler : IRequestHandler<RegisterCommand, RegisterResult>
|
|||||||
await _databaseContext.Events.AddAsync(eventData, cancellationToken);
|
await _databaseContext.Events.AddAsync(eventData, cancellationToken);
|
||||||
await _databaseContext.SaveChangesAsync(cancellationToken);
|
await _databaseContext.SaveChangesAsync(cancellationToken);
|
||||||
|
|
||||||
|
await transaction.CommitAsync(cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
return new RegisterResult(account.Id, account.Email);
|
return new RegisterResult(account.Id, account.Email);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
|
}
|
||||||
@@ -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;
|
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)
|
public TokenGenerator(IConfiguration configuration, DatabaseContext databaseContext)
|
||||||
{
|
{
|
||||||
|
_configuration = configuration;
|
||||||
|
_databaseContext = databaseContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GenerateAccessToken(Account account)
|
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)
|
public async Task<string> GenerateRefreshTokenAsync(Account account)
|
||||||
{
|
{
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<string> ExtendRefreshTokenAsync()
|
public async Task<string> ExtendRefreshTokenAsync()
|
||||||
{
|
{
|
||||||
|
return null;
|
||||||
}*/
|
}
|
||||||
}
|
}
|
||||||
@@ -14,6 +14,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Konscious.Security.Cryptography.Argon2" Version="1.3.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="System.IdentityModel.Tokens.Jwt" Version="8.15.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ public static class Program
|
|||||||
private static IServiceCollection AddHelpers(this IServiceCollection services)
|
private static IServiceCollection AddHelpers(this IServiceCollection services)
|
||||||
{
|
{
|
||||||
services.AddSingleton<IPasswordHasher, PasswordHasher>();
|
services.AddSingleton<IPasswordHasher, PasswordHasher>();
|
||||||
|
services.AddScoped<ITokenGenerator, TokenGenerator>();
|
||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="10.0.0" />
|
<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.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" />
|
<PackageReference Include="TimetableDesigner.Backend.Events.Providers.RabbitMQ" Version="1.0.5" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|||||||
@@ -9,5 +9,22 @@
|
|||||||
"ConnectionStrings": {
|
"ConnectionStrings": {
|
||||||
"Database": "Host=localhost;Port=5433;Database=ttd_authentication;Username=postgres;Password=l4JxOIuSoyod86N;Include Error Detail=True",
|
"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"
|
"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
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user