Completed adjustments for the new configuration of oauth2 and token auth

This commit is contained in:
Masu Baumgartner
2024-11-06 20:03:18 +01:00
parent f2d653563c
commit f9c4ec1d31
3 changed files with 54 additions and 110 deletions

View File

@@ -4,6 +4,7 @@ using MoonCore.Exceptions;
using MoonCore.Extended.Abstractions;
using MoonCore.Extended.Extensions;
using MoonCore.Extended.Helpers;
using MoonCore.Extended.OAuth2.Consumer;
using MoonCore.Extensions;
using MoonCore.Helpers;
using Moonlight.ApiServer.Configuration;
@@ -11,6 +12,7 @@ using Moonlight.ApiServer.Database.Entities;
using Moonlight.ApiServer.Helpers;
using Moonlight.ApiServer.Interfaces.OAuth2;
using Moonlight.ApiServer.Interfaces.Startup;
using Moonlight.Shared.Http.Responses.OAuth2;
namespace Moonlight.ApiServer;
@@ -127,7 +129,7 @@ public static class Startup
return Task.FromResult(true);
};
authenticationConfig.ProcessRefresh = (oldData, newData, serviceProvider) =>
authenticationConfig.ProcessRefresh = async (oldData, newData, serviceProvider) =>
{
var oauth2Providers = serviceProvider.GetRequiredService<IOAuth2Provider[]>();
@@ -141,7 +143,7 @@ public static class Startup
if (!oldData.TryGetValue("userId", out var userIdStr) ||
!userIdStr.TryGetInt32(out var userId))
{
return Task.FromResult(false);
return false;
}
// Load user from database if existent
@@ -152,24 +154,24 @@ public static class Startup
.FirstOrDefault(x => x.Id == userId);
if (user == null)
return Task.FromResult(false);
return 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)
{
var oAuth2Service = serviceProvider.GetRequiredService<OAuth2ConsumerService>();
try
{
// It's time to refresh the access to the external oauth2 provider
var refreshData = OAuth2Service.RefreshAccess(user.RefreshToken).Result;
var refreshData = oAuth2Service.RefreshAccess(user.RefreshToken).Result;
// Sync user with oauth2 provider
var syncedUser = provider.Sync(serviceProvider, refreshData.AccessToken).Result;
var syncedUser = await provider.Sync(serviceProvider, refreshData.AccessToken);
if (syncedUser == null) // User sync has failed. No refresh allowed
return false;
@@ -178,7 +180,7 @@ public static class Startup
// Fetch user model in current db context, just in case the oauth2 provider
// uses a different db context or smth
var userModel = UserRepository
var userModel = userRepo
.Get()
.First(x => x.Id == syncedUser.Id);
@@ -186,19 +188,22 @@ public static class Startup
userModel.RefreshToken = refreshData.RefreshToken;
userModel.RefreshTimestamp = DateTime.UtcNow.AddSeconds(refreshData.ExpiresIn);
UserRepository.Update(userModel);
userRepo.Update(userModel);
}
catch (Exception e)
{
var loggerFactory = serviceProvider.GetRequiredService<ILoggerFactory>();
var logger = loggerFactory.CreateLogger("OAuth2 Refresh");
// 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);
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 true;
};
});
@@ -259,7 +264,7 @@ public static class Startup
configuration.ClientId = config.Authentication.OAuth2.ClientId;
configuration.ClientSecret = config.Authentication.OAuth2.ClientSecret;
configuration.AuthorizationRedirect =
config.Authentication.OAuth2.AuthorizationRedirect ?? $"{config.PublicUrl}/auth";
config.Authentication.OAuth2.AuthorizationRedirect ?? $"{config.PublicUrl}/";
configuration.AccessEndpoint =
config.Authentication.OAuth2.AccessEndpoint ?? $"{config.PublicUrl}/oauth2/access";
@@ -279,41 +284,46 @@ public static class Startup
configuration.AuthorizationEndpoint = config.Authentication.OAuth2.AuthorizationUri!;
}
// TODO: Make modular
configuration.ProcessComplete = async (serviceProvider, accessData) =>
{
var loggerFactory = serviceProvider.GetRequiredService<ILoggerFactory>();
var logger = loggerFactory.CreateLogger("OAuth2 Handler");
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);
try
{
var user = await provider.Sync(serviceProvider, accessData.AccessToken);
if (user == null)
throw new HttpApiException("OAuth2 provider returned empty user", 500);
return new Dictionary<string, object>()
{
{"userId", user.Id}
};
}
catch (Exception e)
{
logger.LogTrace("An error occured while syncing user with oauth2 provider: {e}", e);
throw new HttpApiException("Unable to synchronize with oauth2 provider", 400);
}
};
});
/*
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;
logger.LogInformation("Using local oauth2 provider");
builder.Services.AddOAuth2Provider(configuration =>
builder.AddOAuth2Provider(configuration =>
{
configuration.AccessSecret = config.Authentication.LocalOAuth2.AccessSecret;
configuration.RefreshSecret = config.Authentication.LocalOAuth2.RefreshSecret;
@@ -322,7 +332,7 @@ public static class Startup
configuration.ClientSecret = config.Authentication.OAuth2.ClientSecret;
configuration.CodeSecret = config.Authentication.LocalOAuth2.CodeSecret;
configuration.AuthorizationRedirect =
config.Authentication.OAuth2.AuthorizationRedirect ?? $"{config.PublicUrl}/auth";
config.Authentication.OAuth2.AuthorizationRedirect ?? $"{config.PublicUrl}/";
configuration.AccessTokenDuration = 60;
configuration.RefreshTokenDuration = 3600;
});
@@ -333,6 +343,7 @@ public static class Startup
public static Task UseOAuth2(WebApplication application)
{
application.UseOAuth2Consumer();
return Task.CompletedTask;
}