Added hotkey service. Modified jwt service to use jwt types

This commit is contained in:
Marcel Baumgartner 2024-02-05 22:39:09 +01:00
parent 955946d0a6
commit dfc2b5af17
5 changed files with 88 additions and 8 deletions

View file

@ -1,6 +1,7 @@
using System.ComponentModel; using System.ComponentModel;
using MoonCore.Helpers; using MoonCore.Helpers;
using Moonlight.Features.Advertisement.Configuration; using Moonlight.Features.Advertisement.Configuration;
using Moonlight.Features.FileManager.Configuration;
using Moonlight.Features.StoreSystem.Configuration; using Moonlight.Features.StoreSystem.Configuration;
using Moonlight.Features.Theming.Configuration; using Moonlight.Features.Theming.Configuration;
using Newtonsoft.Json; using Newtonsoft.Json;
@ -22,6 +23,17 @@ public class ConfigV1
[JsonProperty("Theme")] public ThemeData Theme { get; set; } = new(); [JsonProperty("Theme")] public ThemeData Theme { get; set; } = new();
[JsonProperty("Advertisement")] public AdvertisementData Advertisement { get; set; } = new(); [JsonProperty("Advertisement")] public AdvertisementData Advertisement { get; set; } = new();
[JsonProperty("FileManager")] public FileManagerData FileManager { get; set; } = new();
[JsonProperty("WebServer")] public WebServerData WebServer { get; set; } = new();
public class WebServerData
{
[JsonProperty("HttpUploadLimit")]
[Description("This sets the kestrel upload limit in megabytes. Changing this will need an restart")]
public int HttpUploadLimit { get; set; } = 100 * 1024;
}
public class SecurityData public class SecurityData
{ {
[JsonProperty("Token")] [JsonProperty("Token")]

View file

@ -0,0 +1,39 @@
using Microsoft.JSInterop;
using MoonCore.Attributes;
using MoonCore.Helpers;
namespace Moonlight.Core.Services;
[Scoped]
public class HotKeyService : IAsyncDisposable
{
private readonly IJSRuntime JsRuntime;
public SmartEventHandler<string> HotKeyPressed { get; set; } = new();
public HotKeyService(IJSRuntime jsRuntime)
{
JsRuntime = jsRuntime;
}
public async Task Initialize()
{
var reference = DotNetObjectReference.Create(this);
await JsRuntime.InvokeVoidAsync("moonlight.hotkeys.registerListener", reference);
}
[JSInvokable]
public async void OnHotkeyPressed(string hotKey)
{
await HotKeyPressed.Invoke(hotKey);
}
public async ValueTask DisposeAsync()
{
try
{
await JsRuntime.InvokeVoidAsync("moonlight.keyListener.unregisterListener");
}
catch (Exception) { /* ignored */}
}
}

View file

@ -152,7 +152,7 @@ public class IdentityService
{ {
data.Add("userId", user.Id.ToString()); data.Add("userId", user.Id.ToString());
data.Add("issuedAt", DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString()); data.Add("issuedAt", DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString());
}, TimeSpan.FromDays(10)); }, "User", TimeSpan.FromDays(10));
return token; return token;
} }

View file

@ -101,7 +101,10 @@ public class UserAuthService
public async Task SendVerification(User user) public async Task SendVerification(User user)
{ {
var jwt = await JwtService.Create(data => { data.Add("mailToVerify", user.Email); }, TimeSpan.FromMinutes(10)); var jwt = await JwtService.Create(data =>
{
data.Add("mailToVerify", user.Email);
}, "EmailVerification", TimeSpan.FromMinutes(10));
await MailService.Send(user, "Verify your account", "verifyMail", user, new MailVerify() await MailService.Send(user, "Verify your account", "verifyMail", user, new MailVerify()
{ {
@ -118,7 +121,10 @@ public class UserAuthService
if (user == null) if (user == null)
throw new DisplayException("An account with that email was not found"); throw new DisplayException("An account with that email was not found");
var jwt = await JwtService.Create(data => { data.Add("accountToReset", user.Id.ToString()); }); var jwt = await JwtService.Create(data =>
{
data.Add("accountToReset", user.Id.ToString());
}, "PasswordReset", TimeSpan.FromHours(1));
await MailService.Send(user, "Password reset for your account", "passwordReset", user, new ResetPassword() await MailService.Send(user, "Password reset for your account", "passwordReset", user, new ResetPassword()
{ {

View file

@ -19,11 +19,12 @@ public class JwtService
ConfigService = configService; ConfigService = configService;
} }
public Task<string> Create(Action<Dictionary<string, string>> data, TimeSpan? validDuration = null) public Task<string> Create(Action<Dictionary<string, string>> data, string type, TimeSpan? validDuration = null)
{ {
var builder = new JwtBuilder() var builder = new JwtBuilder()
.WithSecret(ConfigService.Get().Security.Token) .WithSecret(ConfigService.Get().Security.Token)
.IssuedAt(DateTime.UtcNow) .IssuedAt(DateTime.UtcNow)
.AddHeader("Type", type)
.ExpirationTime(DateTime.UtcNow.Add(validDuration ?? DefaultDuration)) .ExpirationTime(DateTime.UtcNow.Add(validDuration ?? DefaultDuration))
.WithAlgorithm(new HMACSHA512Algorithm()); .WithAlgorithm(new HMACSHA512Algorithm());
@ -38,17 +39,39 @@ public class JwtService
return Task.FromResult(jwt); return Task.FromResult(jwt);
} }
public Task<bool> Validate(string token) public Task<bool> Validate(string token, params string[] allowedJwtTypes)
{ {
try try
{ {
_ = new JwtBuilder() var headerJson = new JwtBuilder()
.WithSecret(ConfigService.Get().Security.Token) .WithSecret(ConfigService.Get().Security.Token)
.WithAlgorithm(new HMACSHA512Algorithm()) .WithAlgorithm(new HMACSHA512Algorithm())
.MustVerifySignature() .MustVerifySignature()
.Decode(token); .DecodeHeader(token);
if (headerJson == null)
return Task.FromResult(false);
// Jwt type validation
if(allowedJwtTypes.Length == 0)
return Task.FromResult(true); return Task.FromResult(true);
var headerData = JsonConvert.DeserializeObject<Dictionary<string, string>>(headerJson);
if(headerData == null) // => Invalid header
return Task.FromResult(false);
if(!headerData.ContainsKey("Type")) // => Invalid header, Type is missing
return Task.FromResult(false);
foreach (var name in allowedJwtTypes)
{
if(headerData["Type"] == name) // => Correct type found
return Task.FromResult(true);
}
// None found? Invalid type!
return Task.FromResult(false);
} }
catch (Exception e) catch (Exception e)
{ {