Implemented proper node authentication

This commit is contained in:
2025-04-11 22:58:00 +02:00
parent f0948960b7
commit ec0c336825
13 changed files with 174 additions and 165 deletions

View File

@@ -0,0 +1,8 @@
using Microsoft.AspNetCore.Authentication;
namespace MoonlightServers.Daemon.Helpers;
public class TokenAuthOptions : AuthenticationSchemeOptions
{
public string Token { get; set; }
}

View File

@@ -0,0 +1,49 @@
using System.Security.Claims;
using System.Text.Encodings.Web;
using Microsoft.AspNetCore.Authentication;
using Microsoft.Extensions.Options;
namespace MoonlightServers.Daemon.Helpers;
public class TokenAuthScheme : AuthenticationHandler<TokenAuthOptions>
{
public TokenAuthScheme(IOptionsMonitor<TokenAuthOptions> options, ILoggerFactory logger, UrlEncoder encoder,
ISystemClock clock) : base(options, logger, encoder, clock)
{
}
public TokenAuthScheme(IOptionsMonitor<TokenAuthOptions> options, ILoggerFactory logger, UrlEncoder encoder) : base(
options, logger, encoder)
{
}
protected override Task<AuthenticateResult> HandleAuthenticateAsync()
{
if (!Request.Headers.ContainsKey("Authorization"))
return Task.FromResult(AuthenticateResult.NoResult());
var authHeaderValue = Request.Headers["Authorization"].FirstOrDefault();
if (string.IsNullOrEmpty(authHeaderValue))
return Task.FromResult(AuthenticateResult.NoResult());
if (!authHeaderValue.Contains("Bearer "))
return Task.FromResult(AuthenticateResult.NoResult());
var providedToken = authHeaderValue
.Replace("Bearer ", "")
.Trim();
if (providedToken != Options.Token)
return Task.FromResult(AuthenticateResult.NoResult());
return Task.FromResult(AuthenticateResult.Success(
new AuthenticationTicket(
new ClaimsPrincipal(
new ClaimsIdentity("token")
),
"token"
)
));
}
}

View File

@@ -58,37 +58,13 @@ public class RemoteService
BaseAddress = new Uri(formattedUrl)
};
var jwt = GenerateJwt(configuration);
httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {jwt}");
httpClient.DefaultRequestHeaders.Add(
"Authorization",
$"Bearer {configuration.Security.TokenId}.{configuration.Security.Token}"
);
return new HttpApiClient(httpClient);
}
private string GenerateJwt(AppConfiguration configuration)
{
var jwtSecurityTokenHandler = new JwtSecurityTokenHandler();
var securityTokenDesc = new SecurityTokenDescriptor()
{
Expires = DateTime.UtcNow.AddYears(1), // TODO: Document somewhere
IssuedAt = DateTime.UtcNow,
Issuer = configuration.Security.TokenId,
Audience = configuration.Remote.Url,
NotBefore = DateTime.UtcNow.AddSeconds(-1),
SigningCredentials = new SigningCredentials(
new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(configuration.Security.Token)
),
SecurityAlgorithms.HmacSha256
)
};
var securityToken = jwtSecurityTokenHandler.CreateJwtSecurityToken(securityTokenDesc);
securityToken.Header.Add("kid", configuration.Security.TokenId);
return jwtSecurityTokenHandler.WriteToken(securityToken);
}
#endregion
}

View File

@@ -1,15 +1,11 @@
using System.Text;
using System.Text.Json;
using Docker.DotNet;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using MoonCore.Configuration;
using MoonCore.EnvConfiguration;
using MoonCore.Extended.Extensions;
using MoonCore.Extensions;
using MoonCore.Helpers;
using MoonCore.Services;
using MoonlightServers.Daemon.Configuration;
using MoonlightServers.Daemon.Helpers;
using MoonlightServers.Daemon.Http.Hubs;
using MoonlightServers.Daemon.Services;
@@ -91,7 +87,7 @@ public class Startup
{
options.Limits.MaxRequestBodySize = ByteConverter.FromMegaBytes(Configuration.Files.UploadLimit).Bytes;
});
return Task.CompletedTask;
}
@@ -137,7 +133,7 @@ public class Startup
private async Task SetupAppConfiguration()
{
var configurationBuilder = new ConfigurationBuilder();
// Ensure configuration file exists
var jsonFilePath = PathBuilder.File(Directory.GetCurrentDirectory(), "storage", "app.json");
@@ -147,7 +143,7 @@ public class Startup
configurationBuilder.AddJsonFile(
jsonFilePath
);
configurationBuilder.AddEnvironmentVariables(prefix: "MOONLIGHT_", separator: "_");
var configurationRoot = configurationBuilder.Build();
@@ -311,32 +307,22 @@ public class Startup
private Task RegisterAuth()
{
WebApplicationBuilder.Services
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
.AddAuthentication("token")
.AddScheme<TokenAuthOptions, TokenAuthScheme>("token", options =>
{
options.TokenValidationParameters = new()
{
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(
Configuration.Security.Token
)),
ValidateIssuerSigningKey = true,
ValidateLifetime = true,
ValidateAudience = false,
ValidateIssuer = false,
ClockSkew = TimeSpan.Zero
};
options.Token = Configuration.Security.Token;
});
WebApplicationBuilder.Services.AddAuthorization();
return Task.CompletedTask;
}
private Task UseAuth()
{
WebApplication.UseAuthentication();
WebApplication.UseAuthorization();
return Task.CompletedTask;
}