You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
OidcToken - Reworked configuration so that its built into our shared library, and allows for configuration in more traditional ways with Engine, Game and Restricted folders being supported.
Ugs - Updated ugs to read the configuration via the shared library, thus removing the support to read it from UnrealGameSync.ini. Added a ini setting to allow which providers to use though, so that we can have more providers listed in the configuration then UGS will want to care about but also to allow us to control opt in of this feature per project. #preflight none [CL 20911818 by Joakim Lindqvist in ue5-main branch]
This commit is contained in:
@@ -5,12 +5,9 @@ using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using EpicGames.OIDC;
|
||||
|
||||
namespace OidcToken
|
||||
@@ -31,22 +28,34 @@ namespace OidcToken
|
||||
Console.WriteLine(" --ResultToConsole [true/false] - If true the resulting json file is output to stdout (and logs are not created)");
|
||||
Console.WriteLine(" --Unattended [true/false] - If true we assume no user is present and thus can not rely on their input");
|
||||
Console.WriteLine(" --Zen [true/false] - If true the resulting refresh token is posted to Zens token endpoints");
|
||||
Console.WriteLine(" --Project <path> - Project can be used to tell oidc token which game its working in to allow us to read game specific settings");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
string ueRoot = LocateRoot();
|
||||
string optionalConfigPath = Path.Combine(ueRoot, "Engine", "Restricted", "NotForLicensees", "Build", "OidcToken", "appsettings.json");
|
||||
|
||||
ConfigurationBuilder configBuilder = new();
|
||||
configBuilder.SetBasePath(AppContext.BaseDirectory)
|
||||
.AddJsonFile("appsettings.json", false, false)
|
||||
.AddJsonFile(
|
||||
optionalConfigPath,
|
||||
true)
|
||||
.AddCommandLine(args);
|
||||
|
||||
IConfiguration config = configBuilder.Build();
|
||||
|
||||
TokenServiceOptions options = new();
|
||||
config.Bind(options);
|
||||
|
||||
// guess where the engine directory is based on the assumption that we are running out of Engine\Binaries\DotNET\OidcToken\<platform>
|
||||
DirectoryInfo engineDir = new DirectoryInfo(Path.Combine(AppContext.BaseDirectory, "../../../../../Engine"));
|
||||
if (!engineDir.Exists)
|
||||
{
|
||||
// try to see if engine dir can be found from the current code path Engine\Source\Programs\OidcToken\bin\<Configuration>\<.net-version>
|
||||
engineDir = new DirectoryInfo(Path.Combine(AppContext.BaseDirectory, "../../../../../../../Engine"));
|
||||
|
||||
if (!engineDir.Exists)
|
||||
{
|
||||
throw new Exception($"Unable to guess engine directory so unable to continue running. Starting directory was: {AppContext.BaseDirectory}");
|
||||
}
|
||||
}
|
||||
|
||||
await Host.CreateDefaultBuilder(args)
|
||||
.ConfigureAppConfiguration(builder =>
|
||||
{
|
||||
@@ -56,9 +65,6 @@ namespace OidcToken
|
||||
{
|
||||
loggingBuilder.ClearProviders();
|
||||
|
||||
TokenServiceOptions options = new();
|
||||
IConfigurationRoot configRoot = configBuilder.Build();
|
||||
configRoot.Bind(options);
|
||||
if (!options.ResultToConsole)
|
||||
{
|
||||
loggingBuilder.AddConsole();
|
||||
@@ -69,8 +75,7 @@ namespace OidcToken
|
||||
{
|
||||
IConfiguration configuration = content.Configuration;
|
||||
services.AddOptions<TokenServiceOptions>().Bind(configuration).ValidateDataAnnotations();
|
||||
services.AddOptions<OidcTokenOptions>().Bind(configuration.GetSection("OidcToken"))
|
||||
.ValidateDataAnnotations();
|
||||
services.AddOptions<OidcTokenOptions>().Bind(ProviderConfigurationFactory.ReadConfiguration(engineDir, !string.IsNullOrEmpty(options.Project) ? new DirectoryInfo(options.Project) : null)).ValidateDataAnnotations();
|
||||
|
||||
services.AddSingleton<OidcTokenManager>();
|
||||
services.AddTransient<ITokenStore>(TokenStoreFactory.CreateTokenStore);
|
||||
@@ -79,36 +84,5 @@ namespace OidcToken
|
||||
})
|
||||
.RunConsoleAsync();
|
||||
}
|
||||
|
||||
static string LocateRoot()
|
||||
{
|
||||
string? exeLocation = Assembly.GetEntryAssembly()?.Location;
|
||||
|
||||
if (string.IsNullOrEmpty(exeLocation))
|
||||
{
|
||||
exeLocation = Environment.CurrentDirectory;
|
||||
}
|
||||
|
||||
FileInfo exeInfo = new(exeLocation);
|
||||
DirectoryInfo? di = exeInfo.Directory;
|
||||
DirectoryInfo? root = null;
|
||||
while (di != null)
|
||||
{
|
||||
if (di.EnumerateFiles("GenerateProjectFiles.bat").Any())
|
||||
{
|
||||
root = di;
|
||||
break;
|
||||
}
|
||||
|
||||
di = di.Parent!;
|
||||
}
|
||||
|
||||
if (root == null)
|
||||
{
|
||||
throw new Exception($"Unable to find unreal root under: {exeInfo.Directory!.FullName}");
|
||||
}
|
||||
|
||||
return root.FullName;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -255,5 +255,10 @@ namespace OidcToken
|
||||
/// The url to the zen server that we should share a token with (if Zen flag is set)
|
||||
/// </summary>
|
||||
public string ZenUrl { get; set; } = "http://localhost:1337";
|
||||
|
||||
/// <summary>
|
||||
/// Path to the game root directory
|
||||
/// </summary>
|
||||
public string? Project { get; set; } = string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,9 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="IdentityModel.OidcClient" Version="4.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="5.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,50 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
namespace EpicGames.OIDC
|
||||
{
|
||||
public class ProviderConfigurationFactory
|
||||
{
|
||||
public static IConfiguration ReadConfiguration(DirectoryInfo engineDir, DirectoryInfo? gameDir)
|
||||
{
|
||||
string configFileName = "oidc-configuration.json";
|
||||
|
||||
if (!engineDir.Exists)
|
||||
{
|
||||
throw new Exception($"Failed to locate engine dir at {engineDir}");
|
||||
}
|
||||
|
||||
ConfigurationBuilder configBuilder = new ConfigurationBuilder();
|
||||
configBuilder
|
||||
.AddJsonFile($"{engineDir}/Programs/OidcToken/{configFileName}", true, false)
|
||||
.AddJsonFile($"{engineDir}/Restricted/NoRedist/Programs/OidcToken/{configFileName}", true, false)
|
||||
.AddJsonFile($"{engineDir}/Restricted/NotForLicensees/Programs/OidcToken/{configFileName}", true, false);
|
||||
|
||||
if (gameDir?.Exists ?? false)
|
||||
{
|
||||
configBuilder.AddJsonFile($"{gameDir}/Programs/OidcToken/{configFileName}", true, false)
|
||||
.AddJsonFile($"{gameDir}/Restricted/NoRedist/Programs/OidcToken/{configFileName}", true, false)
|
||||
.AddJsonFile($"{gameDir}/Restricted/NotForLicensees/Programs/OidcToken/{configFileName}", true, false);
|
||||
}
|
||||
|
||||
IConfiguration config = configBuilder.Build();
|
||||
return config.GetSection("OidcToken");
|
||||
}
|
||||
|
||||
public static IConfiguration MergeConfiguration(IEnumerable<(DirectoryInfo, DirectoryInfo?)> configurationPaths)
|
||||
{
|
||||
ConfigurationBuilder builder = new ConfigurationBuilder();
|
||||
foreach ((DirectoryInfo engineDir, DirectoryInfo? gameDir) in configurationPaths)
|
||||
{
|
||||
IConfiguration newConfiguration = ReadConfiguration(engineDir, gameDir);
|
||||
builder.AddConfiguration(newConfiguration);
|
||||
}
|
||||
|
||||
return builder.Build();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,6 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
|
||||
@@ -258,8 +258,50 @@ namespace UnrealGameSync
|
||||
// Clear out the cache folder
|
||||
Utility.ClearPrintCache(_cacheFolder);
|
||||
|
||||
OpenProjectInfo firstProject = startupTasks.FirstOrDefault().Item2.Result;
|
||||
|
||||
_tokenStore = TokenStoreFactory.CreateTokenStore();
|
||||
_oidcTokenManager = CreateTokenManagerFromConfigFile(_settings, _tokenStore, startupTasks.Where(x => x.Item2.Succeeded).Select(x => x.Item2.Result).ToList());
|
||||
List<(DirectoryInfo, DirectoryInfo?)> configurationLocations = new List<(DirectoryInfo, DirectoryInfo?)>();
|
||||
List<string> allowedProviders = new List<string>();
|
||||
foreach ((UserSelectedProjectSettings, ModalTask<OpenProjectInfo>) StartupTask in startupTasks)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
ConfigFile ConfigFile = StartupTask.Item2.Result.LatestProjectConfigFile;
|
||||
if (ConfigFile == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ConfigSection ProviderSection = ConfigFile.FindSection("OIDCProvider");
|
||||
if (ProviderSection == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
string[] oidcAllowedProviders = ProviderSection.GetValues("OidcProviderAllowList", Array.Empty<string>());
|
||||
if (oidcAllowedProviders.Length == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
allowedProviders.AddRange(oidcAllowedProviders);
|
||||
|
||||
ProjectInfo projectInfo = StartupTask.Item2.Result.ProjectInfo;
|
||||
configurationLocations.Add((projectInfo.EngineDir.ToDirectoryInfo(), projectInfo.ProjectDir?.ToDirectoryInfo()));
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// ignore any projects that failed to load
|
||||
}
|
||||
}
|
||||
|
||||
_oidcTokenManager = OidcTokenManager.CreateTokenManager(
|
||||
ProviderConfigurationFactory.MergeConfiguration(configurationLocations),
|
||||
_tokenStore,
|
||||
allowedProviders
|
||||
);
|
||||
// Verify that none of the projects we are opening needs a OIDC login, if they do prompt for the login
|
||||
if (_oidcTokenManager?.HasUnfinishedLogin() ?? false)
|
||||
{
|
||||
@@ -293,71 +335,6 @@ namespace UnrealGameSync
|
||||
_mainWindowInstance.FormClosed += MainWindowInstance_FormClosed;
|
||||
}
|
||||
|
||||
static OidcTokenManager? CreateTokenManagerFromConfigFile(UserSettings settings, ITokenStore tokenStore, List<OpenProjectInfo> configFiles)
|
||||
{
|
||||
// join the provider configuration from all projects
|
||||
Dictionary<string, ProviderInfo> Providers = new Dictionary<string, ProviderInfo>();
|
||||
foreach (OpenProjectInfo DetectProjectSettingsTask in configFiles)
|
||||
{
|
||||
if (DetectProjectSettingsTask == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ConfigFile ConfigFile = DetectProjectSettingsTask.LatestProjectConfigFile;
|
||||
if (ConfigFile == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ConfigSection ProviderSection = ConfigFile.FindSection("OIDCProvider");
|
||||
if (ProviderSection == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
string[] ProviderValues = ProviderSection.GetValues("Provider", Array.Empty<string>());
|
||||
foreach (ConfigObject Provider in ProviderValues.Select(s => new ConfigObject(s)).ToList())
|
||||
{
|
||||
string? Identifier = Provider.GetValue("Identifier");
|
||||
string? ServerUri = Provider.GetValue("ServerUri");
|
||||
string? ClientId = Provider.GetValue("ClientId");
|
||||
string? DisplayName = Provider.GetValue("DisplayName");
|
||||
string? RedirectUri = Provider.GetValue("RedirectUri");
|
||||
string? Scopes = Provider.GetValue("Scopes");
|
||||
|
||||
if (string.IsNullOrEmpty(Identifier))
|
||||
continue;
|
||||
|
||||
if (string.IsNullOrEmpty(ClientId))
|
||||
continue;
|
||||
|
||||
if (string.IsNullOrEmpty(RedirectUri))
|
||||
continue;
|
||||
|
||||
if (string.IsNullOrEmpty(ServerUri))
|
||||
continue;
|
||||
|
||||
ProviderInfo info = new ProviderInfo
|
||||
{
|
||||
ClientId = ClientId,
|
||||
DisplayName = DisplayName ?? Identifier,
|
||||
RedirectUri = new Uri(RedirectUri),
|
||||
ServerUri = new Uri(ServerUri),
|
||||
};
|
||||
if (Scopes != null)
|
||||
info.Scopes = Scopes;
|
||||
|
||||
// we might get a provider with the same identifier from another project, in which case we only keep the first one
|
||||
Providers.TryAdd(Identifier, info);
|
||||
}
|
||||
}
|
||||
|
||||
if (Providers.Count == 0)
|
||||
return null;
|
||||
return new OidcTokenManager(Providers, tokenStore);
|
||||
}
|
||||
|
||||
private void MainWindowInstance_FormClosed(object sender, FormClosedEventArgs e)
|
||||
{
|
||||
ExitThread();
|
||||
|
||||
Reference in New Issue
Block a user