fix bearer token validation

add option to change listener mode
This commit is contained in:
zznty
2022-10-19 15:45:37 +07:00
parent e1175ea6db
commit de7e9e616f
5 changed files with 47 additions and 9 deletions

View File

@@ -7,11 +7,21 @@ public class Config : ViewModel
{ {
[Display(Name = "Web Server Config", Description = "Basic configuration for serving web api.")] [Display(Name = "Web Server Config", Description = "Basic configuration for serving web api.")]
public ListenerConfig Listener { get; set; } = new(); 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 string SecurityKey { get; set; } = string.Empty;
} }
public enum WebListenerType
{
HttpSys,
Internal
}
public class ListenerConfig : ViewModel 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.")] [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/"; 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;
} }

View File

@@ -1,18 +1,15 @@
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Text.Json; using System.Text.Json;
using EmbedIO; using EmbedIO;
using EmbedIO.BearerToken;
using EmbedIO.WebApi; using EmbedIO.WebApi;
using Microsoft.IdentityModel.Tokens;
using NLog; using NLog;
using Torch.API; using Torch.API;
using Torch.API.Managers;
using Torch.Managers; using Torch.Managers;
using Torch.Server.Managers; using Torch.Server.Managers;
using TorchRemote.Plugin.Controllers; using TorchRemote.Plugin.Controllers;
using TorchRemote.Plugin.Modules; using TorchRemote.Plugin.Modules;
using TorchRemote.Plugin.Utils; using TorchRemote.Plugin.Utils;
using VRage.Game.ModAPI;
namespace TorchRemote.Plugin.Managers; namespace TorchRemote.Plugin.Managers;
public class ApiServerManager : Manager public class ApiServerManager : Manager
@@ -52,9 +49,15 @@ public class ApiServerManager : Manager
_server = new WebServer(o => o _server = new WebServer(o => o
.WithUrlPrefix(_config.Listener.UrlPrefix) .WithUrlPrefix(_config.Listener.UrlPrefix)
.WithMicrosoftHttpListener()) .WithMode(_config.Listener.ListenerType switch
{
WebListenerType.HttpSys => HttpListenerMode.Microsoft,
WebListenerType.Internal => HttpListenerMode.EmbedIO,
_ => throw new ArgumentOutOfRangeException()
}))
.WithLocalSessionManager() .WithLocalSessionManager()
.WithCors("/api", "*", "*", "*") .WithCors("/api", "*", "*", "*")
.WithModule(new BearerTokenModule("/api", _config.SecurityKey))
.WithModule(apiModule .WithModule(apiModule
.WithController<ServerController>() .WithController<ServerController>()
.WithController<SettingsController>() .WithController<SettingsController>()
@@ -64,8 +67,7 @@ public class ApiServerManager : Manager
.WithController<PluginDownloadsController>() .WithController<PluginDownloadsController>()
.WithController<PlayersController>()) .WithController<PlayersController>())
.WithModule(new LogsModule("/api/live/logs", true)) .WithModule(new LogsModule("/api/live/logs", true))
.WithModule(chatModule) .WithModule(chatModule);
.WithBearerToken("/api", new SymmetricSecurityKey(Convert.FromBase64String(_config.SecurityKey)), new BasicAuthorizationServerProvider());
} }
public override void Attach() public override void Attach()

View File

@@ -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;
}

View File

@@ -20,7 +20,6 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="EmbedIO" Version="3.4.3" /> <PackageReference Include="EmbedIO" Version="3.4.3" />
<PackageReference Include="EmbedIO.BearerToken" Version="3.4.2" />
<PackageReference Include="HttpMultipartParser" Version="7.0.0" /> <PackageReference Include="HttpMultipartParser" Version="7.0.0" />
<PackageReference Include="Json.More.Net" Version="1.7.1" /> <PackageReference Include="Json.More.Net" Version="1.7.1" />
<PackageReference Include="JsonPointer.Net" Version="2.2.2" /> <PackageReference Include="JsonPointer.Net" Version="2.2.2" />

View File

@@ -2,5 +2,5 @@
<PluginManifest xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <PluginManifest xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Name>Torch Remote</Name> <Name>Torch Remote</Name>
<Guid>284017F3-9682-4841-A544-EB04DB8CB9BA</Guid> <Guid>284017F3-9682-4841-A544-EB04DB8CB9BA</Guid>
<Version>v1.0.4</Version> <Version>v1.0.5</Version>
</PluginManifest> </PluginManifest>