diff --git a/identity-server/aspire/AppHosts/All/All.csproj b/identity-server/aspire/AppHosts/All/All.csproj index 59260731c..3ab38c47e 100644 --- a/identity-server/aspire/AppHosts/All/All.csproj +++ b/identity-server/aspire/AppHosts/All/All.csproj @@ -60,6 +60,12 @@ + + + + + + diff --git a/identity-server/aspire/AppHosts/All/Program.cs b/identity-server/aspire/AppHosts/All/Program.cs index fbf53fe58..06048654b 100644 --- a/identity-server/aspire/AppHosts/All/Program.cs +++ b/identity-server/aspire/AppHosts/All/Program.cs @@ -163,6 +163,11 @@ void ConfigureWebClients() RegisterClientIfEnabled("mvc-jar-jwt"); RegisterClientIfEnabled("mvc-jar-uri-jwt"); RegisterClientIfEnabled("web"); + RegisterTemplateIfEnabled("template-is", 7001); + RegisterTemplateIfEnabled("template-is-empty", 7002); + RegisterTemplateIfEnabled("template-is-inmem", 7003); + RegisterTemplateIfEnabled("template-is-aspid", 7004); + RegisterTemplateIfEnabled("template-is-ef", 7005); } void ConfigureConsoleClients() @@ -224,15 +229,24 @@ bool ApiIsEnabled(string name) return appConfig.UseApis.TryGetValue(name, out var enabled) && enabled; } -void RegisterClientIfEnabled(string name, bool explicitStart = false) where T : IProjectMetadata, new() +IResourceBuilder? RegisterTemplateIfEnabled(string name, int port) where T : IProjectMetadata, new() => + RegisterClientIfEnabled(name, useLaunchProfile: false)?.WithHttpsEndpoint(port: port, name: name); + +IResourceBuilder? RegisterClientIfEnabled(string name, bool explicitStart = false, bool useLaunchProfile = true) where T : IProjectMetadata, new() { if (ClientIsEnabled(typeof(T).Name)) { - var resourceBuilder = builder.AddProject(name) - .AddIdentityAndApiReferences(projectRegistry); + var resourceBuilder = useLaunchProfile ? + builder.AddProject(name) : + builder.AddProject(name, launchProfileName: null); + resourceBuilder.AddIdentityAndApiReferences(projectRegistry); if (explicitStart) { resourceBuilder.WithExplicitStart(); } + + return resourceBuilder; } + + return null; } diff --git a/identity-server/aspire/AppHosts/All/appsettings.json b/identity-server/aspire/AppHosts/All/appsettings.json index 2b025dcd8..b0c269c4d 100644 --- a/identity-server/aspire/AppHosts/All/appsettings.json +++ b/identity-server/aspire/AppHosts/All/appsettings.json @@ -30,6 +30,11 @@ "ConsoleResourceOwnerFlowRefreshToken": false, "ConsoleResourceOwnerFlowUserInfo": false, "ConsoleScopesResources": false, + "IdentityServerTemplate": true, + "IdentityServerEmpty": true, + "IdentityServerInMem": true, + "IdentityServerAspNetIdentity": true, + "IdentityServerEntityFramework": true, "JsOidc": false, "MvcAutomaticTokenManagement": true, "MvcCode": true, diff --git a/identity-server/aspire/ServiceDefaults/IdentityServerAppHostRoutes.cs b/identity-server/aspire/ServiceDefaults/IdentityServerAppHostRoutes.cs index cf13312e2..65099c2fb 100644 --- a/identity-server/aspire/ServiceDefaults/IdentityServerAppHostRoutes.cs +++ b/identity-server/aspire/ServiceDefaults/IdentityServerAppHostRoutes.cs @@ -24,6 +24,11 @@ public class IdentityServerAppHostRoutes : IAppHostServiceRoutes AppHostServices.MvcJarJwt => "https://localhost:44304", AppHostServices.MvcJarUriJwt => "https://localhost:44305", AppHostServices.Web => "https://localhost:44306", + AppHostServices.TemplateIs => "https://localhost:7001", + AppHostServices.TemplateIsEmpty => "https://localhost:7002", + AppHostServices.TemplateIsInMem => "https://localhost:7003", + AppHostServices.TemplateIsAspid => "https://localhost:7004", + AppHostServices.TemplateIsEF => "https://localhost:7005", _ => throw new InvalidOperationException("client not configured") }; return new Uri(url); @@ -40,4 +45,9 @@ public class AppHostServices public const string MvcJarJwt = "mvc-jar-jwt"; public const string MvcJarUriJwt = "mvc-jar-uri-jwt"; public const string Web = "web"; + public const string TemplateIs = "template-is"; + public const string TemplateIsEmpty = "template-is-empty"; + public const string TemplateIsInMem = "template-is-inmem"; + public const string TemplateIsAspid = "template-is-aspid"; + public const string TemplateIsEF = "template-is-ef"; } diff --git a/identity-server/test/IdentityServer.EndToEndTests/IdentityServerTests.cs b/identity-server/test/IdentityServer.EndToEndTests/IdentityServerTests.cs index 5f58aee6d..786de6519 100644 --- a/identity-server/test/IdentityServer.EndToEndTests/IdentityServerTests.cs +++ b/identity-server/test/IdentityServer.EndToEndTests/IdentityServerTests.cs @@ -10,17 +10,9 @@ using Xunit.Abstractions; namespace Duende.IdentityServer.EndToEndTests; [Collection(IdentityServerAppHostCollection.CollectionName)] -public class IdentityServerTests : PlaywrightTestBase +public class IdentityServerTests(ITestOutputHelper output, IdentityServerHostTestFixture fixture) + : PlaywrightTestBase(output, fixture) { - private readonly HttpClient _identityServerClient; - private readonly HttpClient _webClient; - - public IdentityServerTests(ITestOutputHelper output, IdentityServerHostTestFixture fixture) : base(output, fixture) - { - _identityServerClient = CreateHttpClient(AppHostServices.IdentityServer); - _webClient = CreateHttpClient(AppHostServices.Web); - } - [Theory] [InlineData(AppHostServices.MvcAutomaticTokenManagement)] [InlineData(AppHostServices.MvcCode)] @@ -29,7 +21,7 @@ public class IdentityServerTests : PlaywrightTestBase [InlineData(AppHostServices.MvcJarJwt)] [InlineData(AppHostServices.MvcJarUriJwt)] [InlineData(AppHostServices.Web)] - public async Task can_login_use_tokens_and_logout(string clientName) + public async Task clients_can_login_use_tokens_and_logout(string clientName) { await Page.GotoAsync(Fixture.GetUrlTo(clientName).ToString()); await Page.Login(); @@ -38,4 +30,18 @@ public class IdentityServerTests : PlaywrightTestBase await Page.CallApi(); await Page.Logout(); } + + [Theory] + [InlineData(AppHostServices.TemplateIs)] + [InlineData(AppHostServices.TemplateIsEmpty)] + [InlineData(AppHostServices.TemplateIsInMem)] + [InlineData(AppHostServices.TemplateIsAspid)] + // The EF template is disabled because we would need to run the migrations + // [InlineData(AppHostServices.TemplateIsEF)] + public async Task templates_can_serve_discovery(string templateName) + { + var client = CreateHttpClient(templateName); + var response = await client.GetAsync(".well-known/openid-configuration"); + response.IsSuccessStatusCode.ShouldBeTrue(); + } } diff --git a/shared/Xunit.Playwright/AppHostFixture.cs b/shared/Xunit.Playwright/AppHostFixture.cs index 56aa0b77f..8e0b3e0cb 100644 --- a/shared/Xunit.Playwright/AppHostFixture.cs +++ b/shared/Xunit.Playwright/AppHostFixture.cs @@ -148,16 +148,16 @@ public class AppHostFixture(IAppHostServiceRoutes routes) : IAsyncLifetim /// /// This method builds an http client. /// - /// + /// /// - public HttpClient CreateHttpClient(string clientName) + public HttpClient CreateHttpClient(string hostName) { HttpMessageHandler inner; Uri? baseAddress; if (UsingAlreadyRunningInstance) { - var url = GetUrlTo(clientName); + var url = GetUrlTo(hostName); baseAddress = url; inner = new SocketsHttpHandler @@ -182,7 +182,7 @@ public class AppHostFixture(IAppHostServiceRoutes routes) : IAsyncLifetim throw new NotSupportedException("App should not be null"); } - var client = _app.CreateHttpClient(clientName); + var client = _app.CreateHttpClient(hostName); baseAddress = client.BaseAddress; // We can't directly use the HTTP Client, because we need cookie support, but if we @@ -221,11 +221,11 @@ public class AppHostFixture(IAppHostServiceRoutes routes) : IAsyncLifetim }; } - public Uri GetUrlTo(string clientName) + public Uri GetUrlTo(string hostName) { if (UsingAlreadyRunningInstance) { - return routes.UrlTo(clientName); + return routes.UrlTo(hostName); } else { @@ -235,7 +235,7 @@ public class AppHostFixture(IAppHostServiceRoutes routes) : IAsyncLifetim throw new NullReferenceException("App should not be null"); } - return _app.GetEndpoint(clientName); + return _app.GetEndpoint(hostName); #else Skip.If(true, "When running the Host.Tests using NCrunch, you must start the Hosts.AppHost project manually. IE: dotnet run -p bff/samples/Hosts.AppHost. Or start without debugging from the UI. "); return null!; diff --git a/shared/Xunit.Playwright/IAppHostServiceRoutes.cs b/shared/Xunit.Playwright/IAppHostServiceRoutes.cs index a759bbd8a..91757c934 100644 --- a/shared/Xunit.Playwright/IAppHostServiceRoutes.cs +++ b/shared/Xunit.Playwright/IAppHostServiceRoutes.cs @@ -9,5 +9,5 @@ namespace Duende.Xunit.Playwright; public interface IAppHostServiceRoutes { public string[] ServiceNames { get; } - public Uri UrlTo(string clientName); + public Uri UrlTo(string hostName); }