Started testing oauth2 handler from mooncore
This commit is contained in:
@@ -1,19 +1,7 @@
|
|||||||
using System.Text.Json;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using MoonCore.Attributes;
|
using MoonCore.Attributes;
|
||||||
using MoonCore.Authentication;
|
using MoonCore.Authentication;
|
||||||
using MoonCore.Exceptions;
|
|
||||||
using MoonCore.Extended.Abstractions;
|
|
||||||
using MoonCore.Extended.Helpers;
|
|
||||||
using MoonCore.Extended.OAuth2.ApiServer;
|
|
||||||
using MoonCore.Extensions;
|
|
||||||
using MoonCore.Helpers;
|
|
||||||
using MoonCore.Services;
|
|
||||||
using Moonlight.ApiServer.Configuration;
|
|
||||||
using Moonlight.ApiServer.Database.Entities;
|
using Moonlight.ApiServer.Database.Entities;
|
||||||
using Moonlight.ApiServer.Interfaces.Auth;
|
|
||||||
using Moonlight.ApiServer.Interfaces.OAuth2;
|
|
||||||
using Moonlight.Shared.Http.Requests.Auth;
|
|
||||||
using Moonlight.Shared.Http.Responses.Auth;
|
using Moonlight.Shared.Http.Responses.Auth;
|
||||||
|
|
||||||
namespace Moonlight.ApiServer.Http.Controllers.Auth;
|
namespace Moonlight.ApiServer.Http.Controllers.Auth;
|
||||||
@@ -22,6 +10,7 @@ namespace Moonlight.ApiServer.Http.Controllers.Auth;
|
|||||||
[Route("api/auth")]
|
[Route("api/auth")]
|
||||||
public class AuthController : Controller
|
public class AuthController : Controller
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
private readonly OAuth2Service OAuth2Service;
|
private readonly OAuth2Service OAuth2Service;
|
||||||
private readonly TokenHelper TokenHelper;
|
private readonly TokenHelper TokenHelper;
|
||||||
private readonly DatabaseRepository<User> UserRepository;
|
private readonly DatabaseRepository<User> UserRepository;
|
||||||
@@ -205,7 +194,7 @@ public class AuthController : Controller
|
|||||||
// All checks have passed, allow refresh
|
// All checks have passed, allow refresh
|
||||||
newData.Add("userId", user.Id);
|
newData.Add("userId", user.Id);
|
||||||
return true;
|
return true;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
[HttpGet("check")]
|
[HttpGet("check")]
|
||||||
[RequirePermission("meta.authenticated")]
|
[RequirePermission("meta.authenticated")]
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ using Microsoft.AspNetCore.Components.Web;
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using MoonCore.Exceptions;
|
using MoonCore.Exceptions;
|
||||||
using MoonCore.Extended.Abstractions;
|
using MoonCore.Extended.Abstractions;
|
||||||
using MoonCore.Extended.OAuth2.AuthServer;
|
|
||||||
using MoonCore.Extended.OAuth2.Models;
|
using MoonCore.Extended.OAuth2.Models;
|
||||||
|
using MoonCore.Extended.OAuth2.Provider;
|
||||||
using Moonlight.ApiServer.Database.Entities;
|
using Moonlight.ApiServer.Database.Entities;
|
||||||
using Moonlight.ApiServer.Http.Controllers.OAuth2.Pages;
|
using Moonlight.ApiServer.Http.Controllers.OAuth2.Pages;
|
||||||
using Moonlight.ApiServer.Services;
|
using Moonlight.ApiServer.Services;
|
||||||
@@ -16,11 +16,11 @@ namespace Moonlight.ApiServer.Http.Controllers.OAuth2;
|
|||||||
[Microsoft.AspNetCore.Mvc.Route("oauth2")]
|
[Microsoft.AspNetCore.Mvc.Route("oauth2")]
|
||||||
public class OAuth2Controller : Controller
|
public class OAuth2Controller : Controller
|
||||||
{
|
{
|
||||||
private readonly OAuth2Service OAuth2Service;
|
private readonly OAuth2ProviderService OAuth2Service;
|
||||||
private readonly AuthService AuthService;
|
private readonly AuthService AuthService;
|
||||||
private readonly DatabaseRepository<User> UserRepository;
|
private readonly DatabaseRepository<User> UserRepository;
|
||||||
|
|
||||||
public OAuth2Controller(OAuth2Service oAuth2Service,
|
public OAuth2Controller(OAuth2ProviderService oAuth2Service,
|
||||||
AuthService authService, DatabaseRepository<User> userRepository)
|
AuthService authService, DatabaseRepository<User> userRepository)
|
||||||
{
|
{
|
||||||
OAuth2Service = oAuth2Service;
|
OAuth2Service = oAuth2Service;
|
||||||
|
|||||||
65
Moonlight.ApiServer/Implementations/TestyOuth2Provider.cs
Normal file
65
Moonlight.ApiServer/Implementations/TestyOuth2Provider.cs
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
using MoonCore.Extended.Abstractions;
|
||||||
|
using MoonCore.Extended.Interfaces;
|
||||||
|
using MoonCore.Extended.OAuth2.Models;
|
||||||
|
using MoonCore.Extensions;
|
||||||
|
using Moonlight.ApiServer.Configuration;
|
||||||
|
using Moonlight.ApiServer.Database.Entities;
|
||||||
|
using Moonlight.Shared.Http.Responses.OAuth2;
|
||||||
|
|
||||||
|
namespace Moonlight.ApiServer.Implementations;
|
||||||
|
|
||||||
|
public class TestyOuth2Provider : IOAuth2Provider
|
||||||
|
{
|
||||||
|
public async Task<Dictionary<string, object>> Sync(IServiceProvider provider, AccessData accessData)
|
||||||
|
{
|
||||||
|
var logger = provider.GetRequiredService<ILogger<TestyOuth2Provider>>();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var configuration = provider.GetRequiredService<AppConfiguration>();
|
||||||
|
|
||||||
|
using var httpClient = new HttpClient();
|
||||||
|
|
||||||
|
httpClient.DefaultRequestHeaders.Add("Authorization", accessData.AccessToken);
|
||||||
|
|
||||||
|
var response = await httpClient.GetAsync($"{configuration.PublicUrl}/oauth2/info");
|
||||||
|
await response.HandlePossibleApiError();
|
||||||
|
var info = await response.ParseAsJson<InfoResponse>();
|
||||||
|
|
||||||
|
var userRepo = provider.GetRequiredService<DatabaseRepository<User>>();
|
||||||
|
var user = userRepo.Get().FirstOrDefault(x => x.Email == info.Email);
|
||||||
|
|
||||||
|
if (user == null) // User not found, register a new one
|
||||||
|
{
|
||||||
|
user = userRepo.Add(new User()
|
||||||
|
{
|
||||||
|
Email = info.Email,
|
||||||
|
Username = info.Username
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if (user.Username != info.Username) // Username updated?
|
||||||
|
{
|
||||||
|
// Username not used by another user?
|
||||||
|
if (!userRepo.Get().Any(x => x.Username == info.Username))
|
||||||
|
{
|
||||||
|
// Update username
|
||||||
|
user.Username = info.Username;
|
||||||
|
userRepo.Update(user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
"userId",
|
||||||
|
user.Id
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
logger.LogCritical("Unable to sync user: {e}", e);
|
||||||
|
return new();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,13 +8,13 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="8.0.7"/>
|
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="8.0.10"/>
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.8">
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.8">
|
||||||
<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.7.1" />
|
<PackageReference Include="MoonCore" Version="1.7.3" />
|
||||||
<PackageReference Include="MoonCore.Extended" Version="1.1.3" />
|
<PackageReference Include="MoonCore.Extended" Version="1.1.4" />
|
||||||
<PackageReference Include="MoonCore.PluginFramework" Version="1.0.4" />
|
<PackageReference Include="MoonCore.PluginFramework" Version="1.0.4" />
|
||||||
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="8.0.2" />
|
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="8.0.2" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0"/>
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0"/>
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ using Moonlight.ApiServer;
|
|||||||
using Moonlight.ApiServer.Configuration;
|
using Moonlight.ApiServer.Configuration;
|
||||||
using Moonlight.ApiServer.Helpers;
|
using Moonlight.ApiServer.Helpers;
|
||||||
using Moonlight.ApiServer.Http.Middleware;
|
using Moonlight.ApiServer.Http.Middleware;
|
||||||
|
using Moonlight.ApiServer.Implementations;
|
||||||
using Moonlight.ApiServer.Interfaces.Auth;
|
using Moonlight.ApiServer.Interfaces.Auth;
|
||||||
using Moonlight.ApiServer.Interfaces.OAuth2;
|
using Moonlight.ApiServer.Interfaces.OAuth2;
|
||||||
using Moonlight.ApiServer.Interfaces.Startup;
|
using Moonlight.ApiServer.Interfaces.Startup;
|
||||||
@@ -112,7 +113,6 @@ foreach (var startupInterface in appStartupInterfaces)
|
|||||||
builder.Services.AddControllers();
|
builder.Services.AddControllers();
|
||||||
builder.Services.AddSingleton(config);
|
builder.Services.AddSingleton(config);
|
||||||
builder.Services.AutoAddServices<Program>();
|
builder.Services.AutoAddServices<Program>();
|
||||||
builder.Services.AddSingleton<TokenHelper>();
|
|
||||||
builder.Services.AddHttpClient();
|
builder.Services.AddHttpClient();
|
||||||
|
|
||||||
await Startup.ConfigureTokenAuthentication(builder, config);
|
await Startup.ConfigureTokenAuthentication(builder, config);
|
||||||
@@ -127,6 +127,8 @@ builder.Services.AddPlugins(configuration =>
|
|||||||
configuration.AddAssembly(Assembly.GetEntryAssembly()!);
|
configuration.AddAssembly(Assembly.GetEntryAssembly()!);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
builder.Services.AddSingleton<MoonCore.Extended.Interfaces.IOAuth2Provider>(new TestyOuth2Provider());
|
||||||
|
|
||||||
var app = builder.Build();
|
var app = builder.Build();
|
||||||
|
|
||||||
await Startup.PrepareDatabase(app);
|
await Startup.PrepareDatabase(app);
|
||||||
@@ -145,6 +147,7 @@ app.UseRouting();
|
|||||||
app.UseMiddleware<ApiErrorMiddleware>();
|
app.UseMiddleware<ApiErrorMiddleware>();
|
||||||
|
|
||||||
await Startup.UseTokenAuthentication(app);
|
await Startup.UseTokenAuthentication(app);
|
||||||
|
await Startup.UseOAuth2(app);
|
||||||
|
|
||||||
// Call interfaces
|
// Call interfaces
|
||||||
foreach (var startupInterface in appStartupInterfaces)
|
foreach (var startupInterface in appStartupInterfaces)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using MoonCore.Authentication;
|
using MoonCore.Authentication;
|
||||||
|
using MoonCore.Exceptions;
|
||||||
using MoonCore.Extended.Abstractions;
|
using MoonCore.Extended.Abstractions;
|
||||||
using MoonCore.Extended.Extensions;
|
using MoonCore.Extended.Extensions;
|
||||||
using MoonCore.Extended.Helpers;
|
using MoonCore.Extended.Helpers;
|
||||||
@@ -8,6 +9,7 @@ using MoonCore.Helpers;
|
|||||||
using Moonlight.ApiServer.Configuration;
|
using Moonlight.ApiServer.Configuration;
|
||||||
using Moonlight.ApiServer.Database.Entities;
|
using Moonlight.ApiServer.Database.Entities;
|
||||||
using Moonlight.ApiServer.Helpers;
|
using Moonlight.ApiServer.Helpers;
|
||||||
|
using Moonlight.ApiServer.Interfaces.OAuth2;
|
||||||
using Moonlight.ApiServer.Interfaces.Startup;
|
using Moonlight.ApiServer.Interfaces.Startup;
|
||||||
|
|
||||||
namespace Moonlight.ApiServer;
|
namespace Moonlight.ApiServer;
|
||||||
@@ -60,8 +62,9 @@ public static class Startup
|
|||||||
|
|
||||||
#region Token Authentication
|
#region Token Authentication
|
||||||
|
|
||||||
public static Task ConfigureTokenAuthentication(IHostApplicationBuilder builder, AppConfiguration config)
|
public static Task ConfigureTokenAuthentication(WebApplicationBuilder builder, AppConfiguration config)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
builder.Services.AddTokenAuthentication(configuration =>
|
builder.Services.AddTokenAuthentication(configuration =>
|
||||||
{
|
{
|
||||||
configuration.AccessSecret = config.Authentication.AccessSecret;
|
configuration.AccessSecret = config.Authentication.AccessSecret;
|
||||||
@@ -89,14 +92,123 @@ public static class Startup
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
});*/
|
||||||
|
|
||||||
|
builder.AddTokenAuthentication(authenticationConfig =>
|
||||||
|
{
|
||||||
|
authenticationConfig.AccessSecret = config.Authentication.AccessSecret;
|
||||||
|
authenticationConfig.RefreshSecret = config.Authentication.RefreshSecret;
|
||||||
|
|
||||||
|
authenticationConfig.AccessDuration = config.Authentication.AccessDuration;
|
||||||
|
authenticationConfig.RefreshDuration = config.Authentication.RefreshDuration;
|
||||||
|
|
||||||
|
authenticationConfig.ProcessAccess = (accessData, provider, httpContext) =>
|
||||||
|
{
|
||||||
|
if (!accessData.TryGetValue("userId", out var userIdStr) || !userIdStr.TryGetInt32(out var userId))
|
||||||
|
return Task.FromResult(false);
|
||||||
|
|
||||||
|
var userRepo = provider.GetRequiredService<DatabaseRepository<User>>();
|
||||||
|
var user = userRepo.Get().FirstOrDefault(x => x.Id == userId);
|
||||||
|
|
||||||
|
if (user == null)
|
||||||
|
return Task.FromResult(false);
|
||||||
|
|
||||||
|
// Load permissions, handle empty values
|
||||||
|
var permissions = JsonSerializer.Deserialize<string[]>(
|
||||||
|
string.IsNullOrEmpty(user.PermissionsJson) ? "[]" : user.PermissionsJson
|
||||||
|
) ?? [];
|
||||||
|
|
||||||
|
// Save permission state
|
||||||
|
httpContext.User = new PermClaimsPrinciple(permissions)
|
||||||
|
{
|
||||||
|
IdentityModel = user
|
||||||
|
};
|
||||||
|
|
||||||
|
return Task.FromResult(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
authenticationConfig.ProcessRefresh = (oldData, newData, serviceProvider) =>
|
||||||
|
{
|
||||||
|
var oauth2Providers = serviceProvider.GetRequiredService<IOAuth2Provider[]>();
|
||||||
|
|
||||||
|
// Find oauth2 provider
|
||||||
|
var provider = oauth2Providers.FirstOrDefault();
|
||||||
|
|
||||||
|
if (provider == null)
|
||||||
|
throw new HttpApiException("No oauth2 provider has been registered", 500);
|
||||||
|
|
||||||
|
// Check if the userId is present in the refresh token
|
||||||
|
if (!oldData.TryGetValue("userId", out var userIdStr) ||
|
||||||
|
!userIdStr.TryGetInt32(out var userId))
|
||||||
|
{
|
||||||
|
return Task.FromResult(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load user from database if existent
|
||||||
|
var userRepo = serviceProvider.GetRequiredService<DatabaseRepository<User>>();
|
||||||
|
|
||||||
|
var user = userRepo
|
||||||
|
.Get()
|
||||||
|
.FirstOrDefault(x => x.Id == userId);
|
||||||
|
|
||||||
|
if (user == null)
|
||||||
|
return Task.FromResult(false);
|
||||||
|
|
||||||
|
// Allow plugins to intercept the refresh call
|
||||||
|
//if (AuthInterceptors.Any(interceptor => !interceptor.AllowRefresh(user, serviceProvider)))
|
||||||
|
// return false;
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
// Check if it's time to resync with the oauth2 provider
|
||||||
|
if (DateTime.UtcNow >= user.RefreshTimestamp)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// It's time to refresh the access to the external oauth2 provider
|
||||||
|
var refreshData = OAuth2Service.RefreshAccess(user.RefreshToken).Result;
|
||||||
|
|
||||||
|
// Sync user with oauth2 provider
|
||||||
|
var syncedUser = provider.Sync(serviceProvider, refreshData.AccessToken).Result;
|
||||||
|
|
||||||
|
if (syncedUser == null) // User sync has failed. No refresh allowed
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Save oauth2 refresh and access tokens for later use (re-authentication etc.).
|
||||||
|
// Fetch user model in current db context, just in case the oauth2 provider
|
||||||
|
// uses a different db context or smth
|
||||||
|
|
||||||
|
var userModel = UserRepository
|
||||||
|
.Get()
|
||||||
|
.First(x => x.Id == syncedUser.Id);
|
||||||
|
|
||||||
|
userModel.AccessToken = refreshData.AccessToken;
|
||||||
|
userModel.RefreshToken = refreshData.RefreshToken;
|
||||||
|
userModel.RefreshTimestamp = DateTime.UtcNow.AddSeconds(refreshData.ExpiresIn);
|
||||||
|
|
||||||
|
UserRepository.Update(userModel);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
// We are handling this error more softly, because it will occur when a user hasn't logged in a long period of time
|
||||||
|
Logger.LogDebug("An error occured while refreshing external oauth2 access: {e}", e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
// All checks have passed, allow refresh
|
||||||
|
newData.Add("userId", user.Id);
|
||||||
|
return Task.FromResult(true);
|
||||||
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Task UseTokenAuthentication(IApplicationBuilder builder)
|
public static Task UseTokenAuthentication(WebApplication builder)
|
||||||
{
|
{
|
||||||
builder.UseTokenAuthentication();
|
builder.UseTokenAuthentication();
|
||||||
|
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,9 +252,9 @@ public static class Startup
|
|||||||
|
|
||||||
#region OAuth2
|
#region OAuth2
|
||||||
|
|
||||||
public static Task ConfigureOAuth2(IHostApplicationBuilder builder, ILogger logger, AppConfiguration config)
|
public static Task ConfigureOAuth2(WebApplicationBuilder builder, ILogger logger, AppConfiguration config)
|
||||||
{
|
{
|
||||||
builder.Services.AddOAuth2Consumer(configuration =>
|
builder.AddOAuth2Consumer(configuration =>
|
||||||
{
|
{
|
||||||
configuration.ClientId = config.Authentication.OAuth2.ClientId;
|
configuration.ClientId = config.Authentication.OAuth2.ClientId;
|
||||||
configuration.ClientSecret = config.Authentication.OAuth2.ClientSecret;
|
configuration.ClientSecret = config.Authentication.OAuth2.ClientSecret;
|
||||||
@@ -169,6 +281,34 @@ public static class Startup
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
|
builder.Services.AddOAuth2Consumer(configuration =>
|
||||||
|
{
|
||||||
|
configuration.ClientId = config.Authentication.OAuth2.ClientId;
|
||||||
|
configuration.ClientSecret = config.Authentication.OAuth2.ClientSecret;
|
||||||
|
configuration.AuthorizationRedirect =
|
||||||
|
config.Authentication.OAuth2.AuthorizationRedirect ?? $"{config.PublicUrl}/auth";
|
||||||
|
|
||||||
|
configuration.AccessEndpoint =
|
||||||
|
config.Authentication.OAuth2.AccessEndpoint ?? $"{config.PublicUrl}/oauth2/access";
|
||||||
|
configuration.RefreshEndpoint =
|
||||||
|
config.Authentication.OAuth2.RefreshEndpoint ?? $"{config.PublicUrl}/oauth2/refresh";
|
||||||
|
|
||||||
|
if (config.Authentication.UseLocalOAuth2)
|
||||||
|
{
|
||||||
|
configuration.AuthorizationEndpoint = config.Authentication.OAuth2.AuthorizationRedirect ??
|
||||||
|
$"{config.PublicUrl}/oauth2/authorize";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (config.Authentication.OAuth2.AuthorizationUri == null)
|
||||||
|
logger.LogWarning(
|
||||||
|
"The 'AuthorizationUri' for the oauth2 client is not set. If you want to use an external oauth2 provider, you need to specify this url. If you want to use the local oauth2 service, set 'UseLocalOAuth2Service' to true");
|
||||||
|
|
||||||
|
configuration.AuthorizationEndpoint = config.Authentication.OAuth2.AuthorizationUri!;
|
||||||
|
}
|
||||||
|
});*/
|
||||||
|
|
||||||
if (!config.Authentication.UseLocalOAuth2) return Task.CompletedTask;
|
if (!config.Authentication.UseLocalOAuth2) return Task.CompletedTask;
|
||||||
|
|
||||||
logger.LogInformation("Using local oauth2 provider");
|
logger.LogInformation("Using local oauth2 provider");
|
||||||
@@ -190,5 +330,11 @@ public static class Startup
|
|||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Task UseOAuth2(WebApplication application)
|
||||||
|
{
|
||||||
|
application.UseOAuth2Consumer();
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
@@ -12,6 +12,7 @@ public class AuthenticationUiHandler : IAppLoader, IAppScreen
|
|||||||
|
|
||||||
public Task<bool> ShouldRender(IServiceProvider serviceProvider)
|
public Task<bool> ShouldRender(IServiceProvider serviceProvider)
|
||||||
{
|
{
|
||||||
|
return Task.FromResult<bool>(false);
|
||||||
var identityService = serviceProvider.GetRequiredService<IdentityService>();
|
var identityService = serviceProvider.GetRequiredService<IdentityService>();
|
||||||
|
|
||||||
return Task.FromResult(!identityService.IsLoggedIn); // Only show the screen when we are not logged in
|
return Task.FromResult(!identityService.IsLoggedIn); // Only show the screen when we are not logged in
|
||||||
@@ -21,6 +22,7 @@ public class AuthenticationUiHandler : IAppLoader, IAppScreen
|
|||||||
|
|
||||||
public async Task Load(IServiceProvider serviceProvider)
|
public async Task Load(IServiceProvider serviceProvider)
|
||||||
{
|
{
|
||||||
|
return;
|
||||||
var identityService = serviceProvider.GetRequiredService<IdentityService>();
|
var identityService = serviceProvider.GetRequiredService<IdentityService>();
|
||||||
await identityService.Check();
|
await identityService.Check();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,12 +10,12 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Blazor-ApexCharts" Version="3.5.0" />
|
<PackageReference Include="Blazor-ApexCharts" Version="3.5.0" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="8.0.6"/>
|
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="8.0.10"/>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="8.0.6" PrivateAssets="all"/>
|
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="8.0.10" PrivateAssets="all"/>
|
||||||
<PackageReference Include="MoonCore" Version="1.7.1" />
|
<PackageReference Include="MoonCore" Version="1.7.3" />
|
||||||
<PackageReference Include="MoonCore.Blazor" Version="1.2.5" />
|
<PackageReference Include="MoonCore.Blazor" Version="1.2.6" />
|
||||||
<PackageReference Include="MoonCore.PluginFramework" Version="1.0.4" />
|
<PackageReference Include="MoonCore.PluginFramework" Version="1.0.4" />
|
||||||
<PackageReference Include="MoonCore.Blazor.Tailwind" Version="1.1.0" />
|
<PackageReference Include="MoonCore.Blazor.Tailwind" Version="1.1.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -56,6 +56,11 @@ builder.RootComponents.Add<App>("#app");
|
|||||||
builder.RootComponents.Add<HeadOutlet>("head::after");
|
builder.RootComponents.Add<HeadOutlet>("head::after");
|
||||||
|
|
||||||
builder.Services.AddScoped(_ => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
|
builder.Services.AddScoped(_ => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
|
||||||
|
|
||||||
|
builder.AddTokenAuthentication();
|
||||||
|
builder.AddOAuth2();
|
||||||
|
|
||||||
|
/*
|
||||||
builder.Services.AddScoped(sp =>
|
builder.Services.AddScoped(sp =>
|
||||||
{
|
{
|
||||||
var httpClient = sp.GetRequiredService<HttpClient>();
|
var httpClient = sp.GetRequiredService<HttpClient>();
|
||||||
@@ -93,7 +98,7 @@ builder.Services.AddScoped(sp =>
|
|||||||
});
|
});
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
});
|
});*/
|
||||||
|
|
||||||
builder.Services.AddMoonCoreBlazorTailwind();
|
builder.Services.AddMoonCoreBlazorTailwind();
|
||||||
builder.Services.AddScoped<WindowService>();
|
builder.Services.AddScoped<WindowService>();
|
||||||
|
|||||||
78
Moonlight.Client/UI/Components/TestyHmm.razor
Normal file
78
Moonlight.Client/UI/Components/TestyHmm.razor
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
@using Microsoft.AspNetCore.WebUtilities
|
||||||
|
@using MoonCore.Blazor.Services
|
||||||
|
@using MoonCore.Exceptions
|
||||||
|
@using MoonCore.Helpers
|
||||||
|
@inherits ErrorBoundaryBase
|
||||||
|
|
||||||
|
@inject NavigationManager Navigation
|
||||||
|
@inject OAuth2FrontendService OAuth2FrontendService
|
||||||
|
|
||||||
|
@if (IsCompleting)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
@ChildContent
|
||||||
|
}
|
||||||
|
|
||||||
|
@code
|
||||||
|
{
|
||||||
|
private bool IsCompleting = false;
|
||||||
|
private string Code;
|
||||||
|
|
||||||
|
protected override void OnInitialized()
|
||||||
|
{
|
||||||
|
var uri = new Uri(Navigation.Uri);
|
||||||
|
|
||||||
|
if (!QueryHelpers.ParseQuery(uri.Query).TryGetValue("code", out var codeSv))
|
||||||
|
return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (codeSv.Count == 0 || string.IsNullOrEmpty(codeSv.First()))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var code = codeSv.First();
|
||||||
|
|
||||||
|
Code = code!;
|
||||||
|
IsCompleting = true;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Console.WriteLine("FUUCK");
|
||||||
|
Console.WriteLine(e);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||||
|
{
|
||||||
|
if (!firstRender)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(!IsCompleting)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!await OAuth2FrontendService.Complete(Code))
|
||||||
|
await RedirectToAuth();
|
||||||
|
|
||||||
|
IsCompleting = false;
|
||||||
|
await InvokeAsync(StateHasChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async Task OnErrorAsync(Exception exception)
|
||||||
|
{
|
||||||
|
if (exception is not HttpApiException httpApiException || httpApiException.Status != 401)
|
||||||
|
throw exception;
|
||||||
|
|
||||||
|
// If we reach this point, we got a 401 unauthenticated, so we need to log in
|
||||||
|
await RedirectToAuth();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task RedirectToAuth()
|
||||||
|
{
|
||||||
|
var url = await OAuth2FrontendService.Start();
|
||||||
|
Navigation.NavigateTo(url, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,8 @@
|
|||||||
@using Moonlight.Client.Interfaces
|
@using Moonlight.Client.Interfaces
|
||||||
@using Moonlight.Client.Services
|
@using Moonlight.Client.Services
|
||||||
@using Moonlight.Client.UI.Partials
|
@using Moonlight.Client.UI.Partials
|
||||||
|
@using MoonCore.Blazor.Components
|
||||||
|
@using Moonlight.Client.UI.Components
|
||||||
|
|
||||||
@inherits LayoutComponentBase
|
@inherits LayoutComponentBase
|
||||||
|
|
||||||
@@ -35,11 +37,13 @@ else
|
|||||||
<div class="px-4 sm:px-6 lg:px-8">
|
<div class="px-4 sm:px-6 lg:px-8">
|
||||||
<ErrorHandler CustomHandler="HandleException">
|
<ErrorHandler CustomHandler="HandleException">
|
||||||
|
|
||||||
|
<TestyHmm>
|
||||||
<PermissionHandler CheckFunction="CheckPermission">
|
<PermissionHandler CheckFunction="CheckPermission">
|
||||||
<CascadingValue Value="this" IsFixed="true">
|
<CascadingValue Value="this" IsFixed="true">
|
||||||
@Body
|
@Body
|
||||||
</CascadingValue>
|
</CascadingValue>
|
||||||
</PermissionHandler>
|
</PermissionHandler>
|
||||||
|
</TestyHmm>
|
||||||
|
|
||||||
</ErrorHandler>
|
</ErrorHandler>
|
||||||
</div>
|
</div>
|
||||||
@@ -72,7 +76,7 @@ else
|
|||||||
|
|
||||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||||
{
|
{
|
||||||
if(!firstRender)
|
if (!firstRender)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
await Load();
|
await Load();
|
||||||
|
|||||||
Reference in New Issue
Block a user