Started implementing client and api server auth and the refresh endpoint

This commit is contained in:
Masu Baumgartner
2024-10-19 16:37:37 +02:00
parent 6be3b8338d
commit 8883b521e9
7 changed files with 94 additions and 9 deletions

View File

@@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using MoonCore.Exceptions;
using MoonCore.Extended.Abstractions; using MoonCore.Extended.Abstractions;
using MoonCore.Extended.Helpers; using MoonCore.Extended.Helpers;
using MoonCore.Extended.OAuth2.ApiServer; using MoonCore.Extended.OAuth2.ApiServer;
@@ -39,6 +40,40 @@ public class AuthController : Controller
return Mapper.Map<AuthStartResponse>(data); return Mapper.Map<AuthStartResponse>(data);
} }
[HttpPost("refresh")]
public async Task Refresh([FromBody] RefreshRequest request)
{
var authConfig = ConfigService.Get().Authentication;
var tokenPair = await TokenHelper.RefreshPair(
request.RefreshToken,
authConfig.MlAccessSecret,
authConfig.MlRefreshSecret,
(refreshTokenData, newTokenData) =>
{
if (!refreshTokenData.TryGetValue("userId", out var userIdStr) || !int.TryParse(userIdStr, out var userId))
return false;
var user = UserRepository.Get().FirstOrDefault(x => x.Id == userId);
if (user == null)
return false;
//TODO: External check
newTokenData.Add("userId", user.Id.ToString());
return true;
}
);
if (!tokenPair.HasValue)
throw new HttpApiException("Unable to refresh token", 401);
Response.Cookies.Append("ml-access", tokenPair.Value.AccessToken);
Response.Cookies.Append("ml-refresh", tokenPair.Value.RefreshToken);
Response.Cookies.Append("ml-timestamp", DateTimeOffset.UtcNow.AddSeconds(3600).ToUnixTimeSeconds().ToString());
}
[HttpGet("handle")] [HttpGet("handle")]
public async Task Handle([FromQuery(Name = "code")] string code) public async Task Handle([FromQuery(Name = "code")] string code)
{ {

View File

@@ -12,7 +12,7 @@
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="MoonCore" Version="1.6.1" /> <PackageReference Include="MoonCore" Version="1.6.2" />
<PackageReference Include="MoonCore.Extended" Version="1.1.0" /> <PackageReference Include="MoonCore.Extended" Version="1.1.0" />
<PackageReference Include="MoonCore.PluginFramework" Version="1.0.0" /> <PackageReference Include="MoonCore.PluginFramework" Version="1.0.0" />
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="8.0.2" /> <PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="8.0.2" />

View File

@@ -135,7 +135,7 @@ if (config.Authentication.UseLocalOAuth2Service)
builder.Services.AddTokenAuthentication(configuration => builder.Services.AddTokenAuthentication(configuration =>
{ {
configuration.AccessSecret = config.Authentication.AccessSecret; configuration.AccessSecret = config.Authentication.MlAccessSecret;
configuration.DataLoader = async (data, provider, context) => configuration.DataLoader = async (data, provider, context) =>
{ {
if (!data.TryGetValue("userId", out var userIdStr) || !int.TryParse(userIdStr, out var userId)) if (!data.TryGetValue("userId", out var userIdStr) || !int.TryParse(userIdStr, out var userId))
@@ -148,7 +148,7 @@ builder.Services.AddTokenAuthentication(configuration =>
return false; return false;
// OAuth2 - Check external // OAuth2 - Check external
if (DateTime.UtcNow > user.RefreshTimestamp) if (false && DateTime.UtcNow > user.RefreshTimestamp)
{ {
var tokenConsumer = new TokenConsumer(user.AccessToken, user.RefreshToken, user.RefreshTimestamp, var tokenConsumer = new TokenConsumer(user.AccessToken, user.RefreshToken, user.RefreshTimestamp,
async refreshToken => async refreshToken =>
@@ -170,7 +170,7 @@ builder.Services.AddTokenAuthentication(configuration =>
}; };
}); });
await tokenConsumer.GetAccessToken(); //await tokenConsumer.GetAccessToken();
//TODO: API CALL (modular) //TODO: API CALL (modular)
} }

View File

@@ -10,7 +10,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="8.0.6"/> <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="8.0.6"/>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="8.0.6" PrivateAssets="all"/> <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="8.0.6" PrivateAssets="all"/>
<PackageReference Include="MoonCore" Version="1.6.1" /> <PackageReference Include="MoonCore" Version="1.6.2" />
<PackageReference Include="MoonCore.Blazor" Version="1.2.1" /> <PackageReference Include="MoonCore.Blazor" Version="1.2.1" />
<PackageReference Include="MoonCore.PluginFramework" Version="1.0.0" /> <PackageReference Include="MoonCore.PluginFramework" Version="1.0.0" />
<PackageReference Include="MoonCore.Blazor.Tailwind" Version="1.0.6" /> <PackageReference Include="MoonCore.Blazor.Tailwind" Version="1.0.6" />

View File

@@ -1,14 +1,20 @@
using System.Net.Http.Headers;
using System.Net.Http.Json;
using System.Text.Json;
using Microsoft.AspNetCore.Components.Web; using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting; using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using MoonCore.Blazor.Tailwind.Extensions; using MoonCore.Blazor.Tailwind.Extensions;
using MoonCore.Blazor.Tailwind.Forms; using MoonCore.Blazor.Tailwind.Forms;
using MoonCore.Blazor.Tailwind.Forms.Components; using MoonCore.Blazor.Tailwind.Forms.Components;
using MoonCore.Blazor.Tailwind.Services;
using MoonCore.Extensions; using MoonCore.Extensions;
using MoonCore.Helpers; using MoonCore.Helpers;
using MoonCore.Models;
using MoonCore.PluginFramework.Services; using MoonCore.PluginFramework.Services;
using Moonlight.Client.Implementations; using Moonlight.Client.Implementations;
using Moonlight.Client.Interfaces; using Moonlight.Client.Interfaces;
using Moonlight.Client.UI; using Moonlight.Client.UI;
using Moonlight.Shared.Http.Requests.Auth;
// Build pre run logger // Build pre run logger
var providers = LoggerBuildHelper.BuildFromConfiguration(configuration => var providers = LoggerBuildHelper.BuildFromConfiguration(configuration =>
@@ -48,12 +54,44 @@ builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after"); builder.RootComponents.Add<HeadOutlet>("head::after");
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) }); builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
builder.Services.AddScoped(sp => new HttpApiClient(sp.GetRequiredService<HttpClient>())); builder.Services.AddScoped(sp =>
{
var httpClient = sp.GetRequiredService<HttpClient>();
var result = new HttpApiClient(httpClient);
builder.Services.AutoAddServices<Program>(); result.UseBearerTokenConsumer(async () =>
{
var cookieService = sp.GetRequiredService<CookieService>();
return new TokenConsumer(
await cookieService.GetValue("ml-access"),
await cookieService.GetValue("ml-refresh"),
DateTimeOffset.FromUnixTimeSeconds(long.Parse(await cookieService.GetValue("ml-timestamp"))).UtcDateTime,
async refreshToken =>
{
await httpClient.PostAsync("api/auth/refresh", new StringContent(
JsonSerializer.Serialize(new RefreshRequest()
{
RefreshToken = refreshToken
}), new MediaTypeHeaderValue("application/json")
));
return new TokenPair()
{
AccessToken = await cookieService.GetValue("ml-access"),
RefreshToken = await cookieService.GetValue("ml-refresh")
};
}
);
});
return result;
});
builder.Services.AddMoonCoreBlazorTailwind(); builder.Services.AddMoonCoreBlazorTailwind();
builder.Services.AutoAddServices<Program>();
FormComponentRepository.Set<string, StringComponent>(); FormComponentRepository.Set<string, StringComponent>();
FormComponentRepository.Set<int, IntComponent>(); FormComponentRepository.Set<int, IntComponent>();
@@ -68,4 +106,6 @@ implementationService.Register<IAppLoader>(authUiHandler);
builder.Services.AddSingleton(implementationService); builder.Services.AddSingleton(implementationService);
await builder.Build().RunAsync(); var app = builder.Build();
await app.RunAsync();

View File

@@ -1,4 +1,5 @@
@using MoonCore.Exceptions @using MoonCore.Exceptions
@using MoonCore.Extensions
@using MoonCore.Helpers @using MoonCore.Helpers
@using MoonCore.PluginFramework.Services @using MoonCore.PluginFramework.Services
@using Moonlight.Client.Interfaces @using Moonlight.Client.Interfaces
@@ -75,7 +76,7 @@ else
{ {
if(!firstRender) if(!firstRender)
return; return;
await Load(); await Load();
} }

View File

@@ -0,0 +1,9 @@
using System.ComponentModel.DataAnnotations;
namespace Moonlight.Shared.Http.Requests.Auth;
public class RefreshRequest
{
[Required(ErrorMessage = "You need to provide a refresh token")]
public string RefreshToken { get; set; }
}