From ee397809282415ed79c8f659f47b970dd2df5010 Mon Sep 17 00:00:00 2001 From: chylex Date: Sat, 23 Dec 2023 11:28:51 +0100 Subject: [PATCH] Rewrite token authorization checks in integrated server --- app/Server/Endpoints/BaseEndpoint.cs | 22 +--------- app/Server/Endpoints/GetAttachmentEndpoint.cs | 3 +- .../Endpoints/GetTrackingScriptEndpoint.cs | 10 +++-- app/Server/Endpoints/TrackChannelEndpoint.cs | 3 +- app/Server/Endpoints/TrackMessagesEndpoint.cs | 3 +- app/Server/Endpoints/TrackUsersEndpoint.cs | 3 +- .../ServerAuthorizationMiddleware.cs | 44 +++++++++++++++++++ app/Server/Service/ServerStartup.cs | 23 ++++------ 8 files changed, 65 insertions(+), 46 deletions(-) create mode 100644 app/Server/Service/Middlewares/ServerAuthorizationMiddleware.cs diff --git a/app/Server/Endpoints/BaseEndpoint.cs b/app/Server/Endpoints/BaseEndpoint.cs index 77cfb72..a1335f2 100644 --- a/app/Server/Endpoints/BaseEndpoint.cs +++ b/app/Server/Endpoints/BaseEndpoint.cs @@ -3,11 +3,9 @@ using System.Net; using System.Text.Json; using System.Threading.Tasks; using DHT.Server.Database; -using DHT.Server.Service; using DHT.Utils.Http; using DHT.Utils.Logging; using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.Primitives; namespace DHT.Server.Endpoints; @@ -15,22 +13,14 @@ abstract class BaseEndpoint { private static readonly Log Log = Log.ForType(); protected IDatabaseFile Db { get; } - protected ServerParameters Parameters { get; } - protected BaseEndpoint(IDatabaseFile db, ServerParameters parameters) { + protected BaseEndpoint(IDatabaseFile db) { this.Db = db; - this.Parameters = parameters; } - private async Task Handle(HttpContext ctx, StringValues token) { + public async Task Handle(HttpContext ctx) { var response = ctx.Response; - if (token.Count != 1 || token[0] != Parameters.Token) { - Log.Error("Token: " + (token.Count == 1 ? token[0] : "")); - response.StatusCode = (int) HttpStatusCode.Forbidden; - return; - } - try { response.StatusCode = (int) HttpStatusCode.OK; var output = await Respond(ctx); @@ -45,14 +35,6 @@ abstract class BaseEndpoint { } } - public async Task HandleGet(HttpContext ctx) { - await Handle(ctx, ctx.Request.Query["token"]); - } - - public async Task HandlePost(HttpContext ctx) { - await Handle(ctx, ctx.Request.Headers["X-DHT-Token"]); - } - protected abstract Task Respond(HttpContext ctx); protected static async Task ReadJson(HttpContext ctx) { diff --git a/app/Server/Endpoints/GetAttachmentEndpoint.cs b/app/Server/Endpoints/GetAttachmentEndpoint.cs index 476eca4..c888fc3 100644 --- a/app/Server/Endpoints/GetAttachmentEndpoint.cs +++ b/app/Server/Endpoints/GetAttachmentEndpoint.cs @@ -2,14 +2,13 @@ using System.Net; using System.Threading.Tasks; using DHT.Server.Data; using DHT.Server.Database; -using DHT.Server.Service; using DHT.Utils.Http; using Microsoft.AspNetCore.Http; namespace DHT.Server.Endpoints; sealed class GetAttachmentEndpoint : BaseEndpoint { - public GetAttachmentEndpoint(IDatabaseFile db, ServerParameters parameters) : base(db, parameters) {} + public GetAttachmentEndpoint(IDatabaseFile db) : base(db) {} protected override Task Respond(HttpContext ctx) { string attachmentUrl = WebUtility.UrlDecode((string) ctx.Request.RouteValues["url"]!); diff --git a/app/Server/Endpoints/GetTrackingScriptEndpoint.cs b/app/Server/Endpoints/GetTrackingScriptEndpoint.cs index 20df2d6..116305e 100644 --- a/app/Server/Endpoints/GetTrackingScriptEndpoint.cs +++ b/app/Server/Endpoints/GetTrackingScriptEndpoint.cs @@ -13,12 +13,16 @@ namespace DHT.Server.Endpoints; sealed class GetTrackingScriptEndpoint : BaseEndpoint { private static ResourceLoader Resources { get; } = new (Assembly.GetExecutingAssembly()); - public GetTrackingScriptEndpoint(IDatabaseFile db, ServerParameters parameters) : base(db, parameters) {} + private readonly ServerParameters serverParameters; + + public GetTrackingScriptEndpoint(IDatabaseFile db, ServerParameters parameters) : base(db) { + serverParameters = parameters; + } protected override async Task Respond(HttpContext ctx) { string bootstrap = await Resources.ReadTextAsync("Tracker/bootstrap.js"); - string script = bootstrap.Replace("= 0; /*[PORT]*/", "= " + Parameters.Port + ";") - .Replace("/*[TOKEN]*/", HttpUtility.JavaScriptStringEncode(Parameters.Token)) + string script = bootstrap.Replace("= 0; /*[PORT]*/", "= " + serverParameters.Port + ";") + .Replace("/*[TOKEN]*/", HttpUtility.JavaScriptStringEncode(serverParameters.Token)) .Replace("/*[IMPORTS]*/", await Resources.ReadJoinedAsync("Tracker/scripts/", '\n')) .Replace("/*[CSS-CONTROLLER]*/", await Resources.ReadTextAsync("Tracker/styles/controller.css")) .Replace("/*[CSS-SETTINGS]*/", await Resources.ReadTextAsync("Tracker/styles/settings.css")) diff --git a/app/Server/Endpoints/TrackChannelEndpoint.cs b/app/Server/Endpoints/TrackChannelEndpoint.cs index 82747f5..a6de19d 100644 --- a/app/Server/Endpoints/TrackChannelEndpoint.cs +++ b/app/Server/Endpoints/TrackChannelEndpoint.cs @@ -3,14 +3,13 @@ using System.Text.Json; using System.Threading.Tasks; using DHT.Server.Data; using DHT.Server.Database; -using DHT.Server.Service; using DHT.Utils.Http; using Microsoft.AspNetCore.Http; namespace DHT.Server.Endpoints; sealed class TrackChannelEndpoint : BaseEndpoint { - public TrackChannelEndpoint(IDatabaseFile db, ServerParameters parameters) : base(db, parameters) {} + public TrackChannelEndpoint(IDatabaseFile db) : base(db) {} protected override async Task Respond(HttpContext ctx) { var root = await ReadJson(ctx); diff --git a/app/Server/Endpoints/TrackMessagesEndpoint.cs b/app/Server/Endpoints/TrackMessagesEndpoint.cs index a55e878..bd7f719 100644 --- a/app/Server/Endpoints/TrackMessagesEndpoint.cs +++ b/app/Server/Endpoints/TrackMessagesEndpoint.cs @@ -9,7 +9,6 @@ using DHT.Server.Data; using DHT.Server.Data.Filters; using DHT.Server.Database; using DHT.Server.Download; -using DHT.Server.Service; using DHT.Utils.Collections; using DHT.Utils.Http; using Microsoft.AspNetCore.Http; @@ -20,7 +19,7 @@ sealed class TrackMessagesEndpoint : BaseEndpoint { private const string HasNewMessages = "1"; private const string NoNewMessages = "0"; - public TrackMessagesEndpoint(IDatabaseFile db, ServerParameters parameters) : base(db, parameters) {} + public TrackMessagesEndpoint(IDatabaseFile db) : base(db) {} protected override async Task Respond(HttpContext ctx) { var root = await ReadJson(ctx); diff --git a/app/Server/Endpoints/TrackUsersEndpoint.cs b/app/Server/Endpoints/TrackUsersEndpoint.cs index d27ff37..ebc4817 100644 --- a/app/Server/Endpoints/TrackUsersEndpoint.cs +++ b/app/Server/Endpoints/TrackUsersEndpoint.cs @@ -3,14 +3,13 @@ using System.Text.Json; using System.Threading.Tasks; using DHT.Server.Data; using DHT.Server.Database; -using DHT.Server.Service; using DHT.Utils.Http; using Microsoft.AspNetCore.Http; namespace DHT.Server.Endpoints; sealed class TrackUsersEndpoint : BaseEndpoint { - public TrackUsersEndpoint(IDatabaseFile db, ServerParameters parameters) : base(db, parameters) {} + public TrackUsersEndpoint(IDatabaseFile db) : base(db) {} protected override async Task Respond(HttpContext ctx) { var root = await ReadJson(ctx); diff --git a/app/Server/Service/Middlewares/ServerAuthorizationMiddleware.cs b/app/Server/Service/Middlewares/ServerAuthorizationMiddleware.cs new file mode 100644 index 0000000..23da196 --- /dev/null +++ b/app/Server/Service/Middlewares/ServerAuthorizationMiddleware.cs @@ -0,0 +1,44 @@ +using System.Net; +using System.Threading.Tasks; +using DHT.Utils.Logging; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Primitives; + +namespace DHT.Server.Service.Middlewares; + +sealed class ServerAuthorizationMiddleware { + private static readonly Log Log = Log.ForType(); + + private readonly RequestDelegate next; + private readonly ServerParameters serverParameters; + + public ServerAuthorizationMiddleware(RequestDelegate next, ServerParameters serverParameters) { + this.next = next; + this.serverParameters = serverParameters; + } + + public async Task InvokeAsync(HttpContext context) { + var request = context.Request; + + bool success = HttpMethods.IsGet(request.Method) + ? CheckToken(request.Query["token"]) + : CheckToken(request.Headers["X-DHT-Token"]); + + if (success) { + await next(context); + } + else { + context.Response.StatusCode = (int) HttpStatusCode.Forbidden; + } + } + + private bool CheckToken(StringValues token) { + if (token.Count == 1 && token[0] == serverParameters.Token) { + return true; + } + else { + Log.Error("Invalid token: " + (token.Count == 1 ? token[0] : "")); + return false; + } + } +} diff --git a/app/Server/Service/ServerStartup.cs b/app/Server/Service/ServerStartup.cs index 1ef60ae..cf31876 100644 --- a/app/Server/Service/ServerStartup.cs +++ b/app/Server/Service/ServerStartup.cs @@ -38,23 +38,16 @@ sealed class Startup { [SuppressMessage("ReSharper", "UnusedMember.Global")] public void Configure(IApplicationBuilder app, IHostApplicationLifetime lifetime, IDatabaseFile db, ServerParameters parameters) { app.UseMiddleware(); - app.UseRouting(); app.UseCors(); + app.UseMiddleware(); + app.UseRouting(); + app.UseEndpoints(endpoints => { - GetTrackingScriptEndpoint getTrackingScript = new (db, parameters); - endpoints.MapGet("/get-tracking-script", context => getTrackingScript.HandleGet(context)); - - TrackChannelEndpoint trackChannel = new (db, parameters); - endpoints.MapPost("/track-channel", context => trackChannel.HandlePost(context)); - - TrackUsersEndpoint trackUsers = new (db, parameters); - endpoints.MapPost("/track-users", context => trackUsers.HandlePost(context)); - - TrackMessagesEndpoint trackMessages = new (db, parameters); - endpoints.MapPost("/track-messages", context => trackMessages.HandlePost(context)); - - GetAttachmentEndpoint getAttachment = new (db, parameters); - endpoints.MapGet("/get-attachment/{url}", context => getAttachment.HandleGet(context)); + endpoints.MapGet("/get-tracking-script", new GetTrackingScriptEndpoint(db, parameters).Handle); + endpoints.MapGet("/get-attachment/{url}", new GetAttachmentEndpoint(db).Handle); + endpoints.MapPost("/track-channel", new TrackChannelEndpoint(db).Handle); + endpoints.MapPost("/track-users", new TrackUsersEndpoint(db).Handle); + endpoints.MapPost("/track-messages", new TrackMessagesEndpoint(db).Handle); }); } }