From de7e9e616fce030c8d70775ff1446daee19d64ed Mon Sep 17 00:00:00 2001 From: zznty <94796179+zznty@users.noreply.github.com> Date: Wed, 19 Oct 2022 15:45:37 +0700 Subject: [PATCH] fix bearer token validation add option to change listener mode --- TorchRemote.Plugin/Config.cs | 10 +++++++ .../Managers/ApiServerManager.cs | 16 ++++++----- .../Modules/BearerTokenModule.cs | 27 +++++++++++++++++++ TorchRemote.Plugin/TorchRemote.Plugin.csproj | 1 - TorchRemote.Plugin/manifest.xml | 2 +- 5 files changed, 47 insertions(+), 9 deletions(-) create mode 100644 TorchRemote.Plugin/Modules/BearerTokenModule.cs diff --git a/TorchRemote.Plugin/Config.cs b/TorchRemote.Plugin/Config.cs index ccad03f..8263af9 100644 --- a/TorchRemote.Plugin/Config.cs +++ b/TorchRemote.Plugin/Config.cs @@ -7,11 +7,21 @@ public class Config : ViewModel { [Display(Name = "Web Server Config", Description = "Basic configuration for serving web api.")] public ListenerConfig Listener { get; set; } = new(); + [Display(Name = "Security Token", Description = "The security token to use when accessing the web api.", ReadOnly = true)] public string SecurityKey { get; set; } = string.Empty; } +public enum WebListenerType +{ + HttpSys, + Internal +} + public class ListenerConfig : ViewModel { [Display(Name = "Url Prefix", Description = "Root url for all requests. If you want access server from remote replace + with your public ip or domain.")] public string UrlPrefix { get; set; } = "http://+:80/"; + + [Display(Name = "Listener Type", Description = "Type of listener to serve requests. If you want to run on wine use Internal otherwise default is better choice")] + public WebListenerType ListenerType { get; set; } = WebListenerType.HttpSys; } diff --git a/TorchRemote.Plugin/Managers/ApiServerManager.cs b/TorchRemote.Plugin/Managers/ApiServerManager.cs index 9eb2fc4..b73968e 100644 --- a/TorchRemote.Plugin/Managers/ApiServerManager.cs +++ b/TorchRemote.Plugin/Managers/ApiServerManager.cs @@ -1,18 +1,15 @@ using System.Security.Cryptography; using System.Text.Json; using EmbedIO; -using EmbedIO.BearerToken; using EmbedIO.WebApi; -using Microsoft.IdentityModel.Tokens; using NLog; using Torch.API; -using Torch.API.Managers; using Torch.Managers; using Torch.Server.Managers; using TorchRemote.Plugin.Controllers; using TorchRemote.Plugin.Modules; using TorchRemote.Plugin.Utils; -using VRage.Game.ModAPI; + namespace TorchRemote.Plugin.Managers; public class ApiServerManager : Manager @@ -52,9 +49,15 @@ public class ApiServerManager : Manager _server = new WebServer(o => o .WithUrlPrefix(_config.Listener.UrlPrefix) - .WithMicrosoftHttpListener()) + .WithMode(_config.Listener.ListenerType switch + { + WebListenerType.HttpSys => HttpListenerMode.Microsoft, + WebListenerType.Internal => HttpListenerMode.EmbedIO, + _ => throw new ArgumentOutOfRangeException() + })) .WithLocalSessionManager() .WithCors("/api", "*", "*", "*") + .WithModule(new BearerTokenModule("/api", _config.SecurityKey)) .WithModule(apiModule .WithController() .WithController() @@ -64,8 +67,7 @@ public class ApiServerManager : Manager .WithController() .WithController()) .WithModule(new LogsModule("/api/live/logs", true)) - .WithModule(chatModule) - .WithBearerToken("/api", new SymmetricSecurityKey(Convert.FromBase64String(_config.SecurityKey)), new BasicAuthorizationServerProvider()); + .WithModule(chatModule); } public override void Attach() diff --git a/TorchRemote.Plugin/Modules/BearerTokenModule.cs b/TorchRemote.Plugin/Modules/BearerTokenModule.cs new file mode 100644 index 0000000..1e8c58d --- /dev/null +++ b/TorchRemote.Plugin/Modules/BearerTokenModule.cs @@ -0,0 +1,27 @@ +using System.Net; +using EmbedIO; + +namespace TorchRemote.Plugin.Modules; + +internal class BearerTokenModule : WebModuleBase +{ + private readonly string _token; + + public BearerTokenModule(string baseRoute, string token) : base(baseRoute) + { + _token = token; + } + + protected override Task OnRequestAsync(IHttpContext context) + { + const string bearer = "Bearer "; + if (context.Request.Headers["Authorization"] is { } headerValue && + headerValue.StartsWith(bearer, StringComparison.OrdinalIgnoreCase) && + headerValue.Substring(bearer.Length) == _token) + return Task.CompletedTask; + + throw HttpException.Unauthorized(); + } + + public override bool IsFinalHandler => false; +} \ No newline at end of file diff --git a/TorchRemote.Plugin/TorchRemote.Plugin.csproj b/TorchRemote.Plugin/TorchRemote.Plugin.csproj index c1fa17d..9dc6dbd 100644 --- a/TorchRemote.Plugin/TorchRemote.Plugin.csproj +++ b/TorchRemote.Plugin/TorchRemote.Plugin.csproj @@ -20,7 +20,6 @@ - diff --git a/TorchRemote.Plugin/manifest.xml b/TorchRemote.Plugin/manifest.xml index 4075bf9..b5debc5 100644 --- a/TorchRemote.Plugin/manifest.xml +++ b/TorchRemote.Plugin/manifest.xml @@ -2,5 +2,5 @@ Torch Remote 284017F3-9682-4841-A544-EB04DB8CB9BA - v1.0.4 + v1.0.5 \ No newline at end of file