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 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;
|
||||
}
|
||||
}
|
||||
@@ -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,6 +29,9 @@ public class RegisterHandler : IRequestHandler<RegisterCommand, RegisterResult>
|
||||
Password = hash.Hash,
|
||||
PasswordSalt = hash.Salt,
|
||||
};
|
||||
|
||||
await using (IDbContextTransaction transaction = await _databaseContext.Database.BeginTransactionAsync(cancellationToken))
|
||||
{
|
||||
await _databaseContext.Accounts.AddAsync(account, cancellationToken);
|
||||
await _databaseContext.SaveChangesAsync(cancellationToken);
|
||||
|
||||
@@ -35,6 +39,8 @@ public class RegisterHandler : IRequestHandler<RegisterCommand, RegisterResult>
|
||||
await _databaseContext.Events.AddAsync(eventData, cancellationToken);
|
||||
await _databaseContext.SaveChangesAsync(cancellationToken);
|
||||
|
||||
await transaction.CommitAsync(cancellationToken);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user