57 lines
2.2 KiB
C#
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);
|
|
}
|
|
} |