using Foxchat.Core; using Foxchat.Identity.Database; using Foxchat.Identity.Utils; using NodaTime; namespace Foxchat.Identity.Middleware; public class ClientAuthorizationMiddleware( IdentityContext db, IClock clock ) : IMiddleware { public async Task InvokeAsync(HttpContext ctx, RequestDelegate next) { var endpoint = ctx.GetEndpoint(); var attribute = endpoint?.Metadata.GetMetadata(); if (attribute == null) { await next(ctx); return; } var token = ctx.GetToken(); if (token == null || token.Expires < clock.GetCurrentInstant()) throw new ApiError.Unauthorized("This endpoint requires an authenticated user."); if (attribute.Scopes.Length > 0 && attribute.Scopes.Except(token.Scopes.ExpandScopes()).Any()) throw new ApiError.Forbidden("This endpoint requires ungranted scopes.", attribute.Scopes.Except(token.Scopes.ExpandScopes())); await next(ctx); } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] public class AuthorizeAttribute(params string[] scopes) : Attribute { public readonly string[] Scopes = scopes; }