using System.Security.Cryptography; using System.Text.Encodings.Web; using Foxchat.Core; using Foxchat.Core.Utils; using Foxchat.Identity.Database; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.BearerToken; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Options; using NodaTime; namespace Foxchat.Identity.Authorization; public static class AuthenticationHandlerExtensions { public static void AddAuthenticationHandler(this IServiceCollection services) { } } public class FoxchatAuthenticationHandler( IOptionsMonitor options, ILoggerFactory logger, UrlEncoder encoder, IdentityContext context, IClock clock ) : AuthenticationHandler(options, logger, encoder) { protected override async Task HandleAuthenticateAsync() { var header = Request.Headers.Authorization.ToString(); if (!header.StartsWith("bearer ", StringComparison.InvariantCultureIgnoreCase)) return AuthenticateResult.NoResult(); var token = header[7..]; if (!CryptoUtils.TryFromBase64String(token, out var rawToken)) return AuthenticateResult.Fail(new FoxchatError.BadRequest("Invalid token format")); var hash = SHA512.HashData(rawToken); var oauthToken = await context.Tokens .Include(t => t.Account) .Include(t => t.Application) .FirstOrDefaultAsync(t => t.Hash == hash && t.Expires > clock.GetCurrentInstant()); if (oauthToken == null) return AuthenticateResult.NoResult(); throw new NotImplementedException(); } }