Started implementing client and api server auth and the refresh endpoint
This commit is contained in:
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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" />
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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" />
|
||||||
|
|||||||
@@ -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();
|
||||||
@@ -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
|
||||||
|
|||||||
9
Moonlight.Shared/Http/Requests/Auth/RefreshRequest.cs
Normal file
9
Moonlight.Shared/Http/Requests/Auth/RefreshRequest.cs
Normal 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; }
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user