auth token endpoint finished
This commit is contained in:
@@ -10,13 +10,13 @@ public class AuthPasswordHandler : IRequestHandler<AuthPasswordCommand, AuthPass
|
||||
{
|
||||
private readonly DatabaseContext _databaseContext;
|
||||
private readonly IPasswordHasher _passwordHasher;
|
||||
private readonly IAccessTokenGenerator _accessTokenGenerator;
|
||||
private readonly ITokenHelper _tokenHelper;
|
||||
|
||||
public AuthPasswordHandler(DatabaseContext databaseContext, IPasswordHasher passwordHasher, IAccessTokenGenerator accessTokenGenerator)
|
||||
public AuthPasswordHandler(DatabaseContext databaseContext, IPasswordHasher passwordHasher, ITokenHelper tokenHelper)
|
||||
{
|
||||
_databaseContext = databaseContext;
|
||||
_passwordHasher = passwordHasher;
|
||||
_accessTokenGenerator = accessTokenGenerator;
|
||||
_tokenHelper = tokenHelper;
|
||||
}
|
||||
|
||||
public async Task<AuthPasswordResult> Handle(AuthPasswordCommand request, CancellationToken cancellationToken)
|
||||
@@ -33,10 +33,17 @@ public class AuthPasswordHandler : IRequestHandler<AuthPasswordCommand, AuthPass
|
||||
return AuthPasswordResult.Failure();
|
||||
}
|
||||
|
||||
string accessToken = _accessTokenGenerator.GenerateAccessToken(account);
|
||||
RefreshToken refreshToken = _accessTokenGenerator.GenerateRefreshToken(request.RememberMe);
|
||||
string accessToken = _tokenHelper.GenerateAccessToken(account.Id);
|
||||
|
||||
account.RefreshTokens.Add(refreshToken);
|
||||
RefreshToken refreshToken = new RefreshToken
|
||||
{
|
||||
Token = Guid.NewGuid(),
|
||||
IsExtendable = request.RememberMe,
|
||||
AccountId = account.Id,
|
||||
ExpirationDate = _tokenHelper.CalculateRefreshTokenExpirationDate(request.RememberMe),
|
||||
};
|
||||
|
||||
await _databaseContext.RefreshTokens.AddAsync(refreshToken, cancellationToken);
|
||||
await _databaseContext.SaveChangesAsync(cancellationToken);
|
||||
|
||||
return AuthPasswordResult.Success(accessToken, refreshToken.Token.ToString());
|
||||
|
||||
@@ -9,31 +9,32 @@ namespace TimetableDesigner.Backend.Services.Authentication.Core.Commands.AuthTo
|
||||
public class AuthTokenHandler : IRequestHandler<AuthTokenCommand, AuthTokenResult>
|
||||
{
|
||||
private readonly DatabaseContext _databaseContext;
|
||||
private readonly IAccessTokenGenerator _accessTokenGenerator;
|
||||
private readonly ITokenHelper _tokenHelper;
|
||||
|
||||
public AuthTokenHandler(DatabaseContext databaseContext, IAccessTokenGenerator accessTokenGenerator)
|
||||
public AuthTokenHandler(DatabaseContext databaseContext, ITokenHelper tokenHelper)
|
||||
{
|
||||
_databaseContext = databaseContext;
|
||||
_accessTokenGenerator = accessTokenGenerator;
|
||||
_tokenHelper = tokenHelper;
|
||||
}
|
||||
|
||||
public async Task<AuthTokenResult> Handle(AuthTokenCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
RefreshToken? token = await _databaseContext.RefreshTokens
|
||||
RefreshToken? refreshToken = await _databaseContext.RefreshTokens
|
||||
.Include(x => x.Account)
|
||||
.FirstOrDefaultAsync(x => x.Token == Guid.Parse(request.RefreshToken), cancellationToken);
|
||||
if (token is null || token.ExpirationDate < DateTimeOffset.UtcNow || !_accessTokenGenerator.ValidateExpiredAccessToken(request.AccessToken))
|
||||
if (refreshToken is null || refreshToken.ExpirationDate < DateTimeOffset.UtcNow || !_tokenHelper.ValidateExpiredAccessToken(request.AccessToken))
|
||||
{
|
||||
return AuthTokenResult.Failure();
|
||||
}
|
||||
|
||||
string accessToken = _accessTokenGenerator.GenerateAccessToken(token.Account);
|
||||
if (token.IsExtendable)
|
||||
{
|
||||
|
||||
}
|
||||
string accessToken = _tokenHelper.GenerateAccessToken(refreshToken.Account.Id);
|
||||
|
||||
if (refreshToken.IsExtendable)
|
||||
{
|
||||
refreshToken.ExpirationDate = _tokenHelper.CalculateRefreshTokenExpirationDate();
|
||||
await _databaseContext.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
|
||||
return AuthTokenResult.Success(refreshToken, accessToken);
|
||||
return AuthTokenResult.Success(accessToken, refreshToken.Token.ToString());
|
||||
}
|
||||
}
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
namespace TimetableDesigner.Backend.Services.Authentication.Core.Helpers;
|
||||
|
||||
public interface IAccessTokenGenerator
|
||||
public interface ITokenHelper
|
||||
{
|
||||
string GenerateAccessToken(Account account);
|
||||
RefreshToken GenerateRefreshToken(bool isExtendable);
|
||||
string GenerateAccessToken(long accountId);
|
||||
bool ValidateExpiredAccessToken(string accessToken);
|
||||
DateTimeOffset CalculateRefreshTokenExpirationDate(bool isExtendable = true);
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
namespace TimetableDesigner.Backend.Services.Authentication.Core.Helpers;
|
||||
|
||||
public record PasswordHashData(
|
||||
byte[] Hash,
|
||||
string Salt
|
||||
);
|
||||
@@ -36,4 +36,9 @@ public class PasswordHasher : IPasswordHasher
|
||||
byte[] hash = hashFunction.GetBytes(32);
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public record PasswordHashData(
|
||||
byte[] Hash,
|
||||
string Salt
|
||||
);
|
||||
@@ -9,18 +9,16 @@ using JwtRegisteredClaimNames = Microsoft.IdentityModel.JsonWebTokens.JwtRegiste
|
||||
|
||||
namespace TimetableDesigner.Backend.Services.Authentication.Core.Helpers;
|
||||
|
||||
public class AccessTokenGenerator : IAccessTokenGenerator
|
||||
public class TokenHelper : ITokenHelper
|
||||
{
|
||||
private readonly IConfiguration _configuration;
|
||||
private readonly DatabaseContext _databaseContext;
|
||||
|
||||
public AccessTokenGenerator(IConfiguration configuration, DatabaseContext databaseContext)
|
||||
public TokenHelper(IConfiguration configuration)
|
||||
{
|
||||
_configuration = configuration;
|
||||
_databaseContext = databaseContext;
|
||||
}
|
||||
|
||||
public string GenerateAccessToken(Account account)
|
||||
public string GenerateAccessToken(long accountId)
|
||||
{
|
||||
IConfigurationSection accessTokenSettings = _configuration.GetSection("Tokens")
|
||||
.GetSection("AccessToken");
|
||||
@@ -40,7 +38,7 @@ public class AccessTokenGenerator : IAccessTokenGenerator
|
||||
Subject = new ClaimsIdentity(
|
||||
[
|
||||
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
|
||||
new Claim(JwtRegisteredClaimNames.Sub, account.Id.ToString()),
|
||||
new Claim(JwtRegisteredClaimNames.Sub, accountId.ToString()),
|
||||
new Claim(JwtRegisteredClaimNames.Exp, expirationDate.UtcTicks.ToString())
|
||||
]),
|
||||
Issuer = accessTokenSettings.GetValue<string>("Issuer"),
|
||||
@@ -56,25 +54,6 @@ public class AccessTokenGenerator : IAccessTokenGenerator
|
||||
return handler.WriteToken(token);
|
||||
}
|
||||
|
||||
public RefreshToken GenerateRefreshToken(bool isExtendable)
|
||||
{
|
||||
string lifetimeSection = isExtendable ? "Extended" : "Normal";
|
||||
int lifetime = _configuration.GetSection("Tokens")
|
||||
.GetSection("RefreshToken")
|
||||
.GetSection("Lifetime")
|
||||
.GetValue<int>(lifetimeSection);
|
||||
|
||||
Guid guid = Guid.NewGuid();
|
||||
DateTimeOffset expirationDate = DateTimeOffset.UtcNow.AddMinutes(lifetime);
|
||||
|
||||
return new RefreshToken
|
||||
{
|
||||
Token = guid,
|
||||
ExpirationDate = expirationDate,
|
||||
IsExtendable = isExtendable,
|
||||
};
|
||||
}
|
||||
|
||||
public bool ValidateExpiredAccessToken(string accessToken)
|
||||
{
|
||||
IConfigurationSection accessTokenSettings = _configuration.GetSection("Tokens")
|
||||
@@ -104,4 +83,14 @@ public class AccessTokenGenerator : IAccessTokenGenerator
|
||||
|
||||
return jwtSecurityToken is not null && jwtSecurityToken.Header.Alg.Equals(algorithm, StringComparison.InvariantCultureIgnoreCase);
|
||||
}
|
||||
|
||||
public DateTimeOffset CalculateRefreshTokenExpirationDate(bool isExtendable = true)
|
||||
{
|
||||
string lifetimeSection = isExtendable ? "Extended" : "Normal";
|
||||
int lifetime = _configuration.GetSection("Tokens")
|
||||
.GetSection("RefreshToken")
|
||||
.GetSection("Lifetime")
|
||||
.GetValue<int>(lifetimeSection);
|
||||
return DateTimeOffset.UtcNow.AddMinutes(lifetime);
|
||||
}
|
||||
}
|
||||
@@ -52,7 +52,7 @@ public static class Program
|
||||
private static IServiceCollection AddHelpers(this IServiceCollection services)
|
||||
{
|
||||
services.AddSingleton<IPasswordHasher, PasswordHasher>();
|
||||
services.AddScoped<IAccessTokenGenerator, AccessTokenGenerator>();
|
||||
services.AddScoped<ITokenHelper, TokenHelper>();
|
||||
return services;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user