gandalf-reborn/Api/Handlers/Security/CreateTokensCommandHandler.cs
2025-03-02 12:51:02 +01:00

79 lines
2.7 KiB
C#

using HashidsNet;
using JWT.Algorithms;
using JWT.Builder;
using JWT.Serializers;
using LanguageExt.Common;
using Security.Scheme;
using W542.GandalfReborn.Commands;
using W542.GandalfReborn.Data.Database.Repositories;
using W542.GandalfReborn.Data.Dto;
using W542.GandalfReborn.Data.Entities.Security;
using W542.GandalfReborn.Extensions;
using W542.GandalfReborn.Handlers.Commands;
namespace W542.GandalfReborn.Handlers.Security;
public class CreateTokensCommandHandler(TimeProvider timeProvider, IConfiguration configuration, IHashids hashids, ITokenMetadataRepository tokenMetadataRepository) : IGrCommandHandler<CreateTokensCommand, Result<TokenDto>>
{
public async Task<Result<TokenDto>> Handle(CreateTokensCommand command, CancellationToken cancellationToken)
{
var iat = timeProvider.GetUtcNow();
var accessExp = iat.AddMinutes(5);
var refreshExp = iat.AddDays(7);
var builder = JwtBuilder.Create()
.WithAlgorithm(new HMACSHA512Algorithm())
.WithSecret(configuration.GetValue<string>("JwtSecret"))
.WithJsonSerializer(new JsonNetSerializer());
var accessTokenMetadata = new TokenMetadataEntity
{
Expiration = accessExp,
IsRevoked = false,
TokenType = TokenType.User,
UsedBy = command.SubjectId
};
var refreshTokenMetadata = new TokenMetadataEntity
{
Expiration = refreshExp,
IsRevoked = false,
TokenType = TokenType.User,
UsedBy = command.SubjectId
};
var entities = await tokenMetadataRepository.Upsert([accessTokenMetadata, refreshTokenMetadata]);
if (entities.IsFaulted)
return entities.AsErrorResult<TokenDto, ICollection<TokenMetadataEntity>>();
var baseUrl = configuration.GetValue<string>("BaseUrl") ?? "https://localhost:7269";
var accessToken = builder.Encode(new GandalfRebornJwtBody
{
Id = hashids.EncodeLong(accessTokenMetadata.Id!.Value),
Sub = hashids.EncodeLong(command.SubjectId),
Iat = iat,
Exp = accessExp,
Iss = baseUrl,
Aud = baseUrl
});
var refreshToken = builder.Encode(new GandalfRebornJwtBody
{
Id = hashids.EncodeLong(refreshTokenMetadata.Id!.Value),
Sub = hashids.EncodeLong(command.SubjectId),
Iat = iat,
Exp = refreshExp,
Iss = baseUrl,
Aud = baseUrl
});
return new Result<TokenDto>(new TokenDto
{
AccessToken = accessToken,
RefreshToken = refreshToken
});
}
}