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

57 lines
2.2 KiB
C#

using System.Security.Cryptography;
using System.Text;
using LanguageExt.Common;
using MediatR;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;
using W542.GandalfReborn.Commands;
using W542.GandalfReborn.Data.Database.Repositories;
using W542.GandalfReborn.Data.Dto;
using W542.GandalfReborn.Extensions;
using W542.GandalfReborn.Handlers.Commands;
namespace W542.GandalfReborn.Handlers.Security;
public class GetTokensCommandHandler(IAuthCodeRepository authCodeRepository, TimeProvider timeProvider, IMediator mediator) : IGrCommandHandler<GetTokensCommand, Result<TokenDto>>
{
public async Task<Result<TokenDto>> Handle(GetTokensCommand command, CancellationToken cancellationToken)
{
var authCode = await authCodeRepository
.Query(q => q.Where(x => x.Code == command.AuthCode))
.SingleOrDefaultAsync(cancellationToken);
if (authCode is null)
{
return "Auth code could not be found.".AsErrorResult<TokenDto>();
}
if (authCode.Expiration <= timeProvider.GetUtcNow())
{
await authCodeRepository
.Query(q => q.Where(x => x.Id == authCode.Id))
.ExecuteDeleteAsync(cancellationToken);
return "Auth code is expired.".AsErrorResult<TokenDto>();
}
switch (authCode.Algorithm)
{
case "S256":
var proofKeyBytes = Encoding.UTF8.GetBytes(command.ProofKey);
var sha256Bytes = SHA256.HashData(proofKeyBytes);
var hexProofKey = BitConverter.ToString(sha256Bytes).Replace("-", string.Empty).ToLower();
if (authCode.Challenge != hexProofKey)
return "Code challenge failed.".AsErrorResult<TokenDto>();
break;
default:
return $"Algorithm '{authCode.Algorithm}' not supported".AsErrorResult<TokenDto>();
}
await authCodeRepository
.Query(q => q.Where(x => x.Id == authCode.Id))
.ExecuteDeleteAsync(cancellationToken);
return await mediator.Send(new CreateTokensCommand {SubjectId = authCode.SubjectId}, cancellationToken);
}
}