using Elsa.Permissions; using Elsa.Authorization; using Elsa.Common; using Elsa.ExternalAuthentication.Contracts; using Elsa.ExternalAuthentication.Models; using Elsa.ExternalAuthentication.Options; using Elsa.ExternalAuthentication.OpenIdConnect.Services; using Elsa.ExternalAuthentication.Permissions; using Elsa.ExternalAuthentication.Providers; using Elsa.ExternalAuthentication.Services; using Elsa.ExternalAuthentication.Stores.InMemory; using Elsa.Identity.Contracts; using Microsoft.AspNetCore.RateLimiting; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; namespace Elsa.ExternalAuthentication.UnitTests.Foundational; public class ExternalAuthenticationServiceCollectionTests { [Fact] public void AddsTheConfigurationFirstBrokerFoundation() { var services = new ServiceCollection(); services.AddSingleton(new TestSystemClock(new DateTimeOffset(2026, 7, 24, 12, 0, 0, TimeSpan.Zero))); services.AddExternalAuthenticationServices(options => { options.AllowedUnlinkedIdentityPolicyTypes.Clear(); options.AllowedPermissionGrantSourceTypes.Clear(); }); using var serviceProvider = services.BuildServiceProvider(new ServiceProviderOptions { ValidateScopes = true }); Assert.NotNull(serviceProvider.GetRequiredService>().Value); var connectionSources = serviceProvider.GetRequiredService>().ToArray(); Assert.Contains(connectionSources, source => source is ConfigurationIdentityProviderConnectionSource); Assert.Contains(connectionSources, source => source is DatabaseIdentityProviderConnectionSource); Assert.IsType(serviceProvider.GetRequiredService()); Assert.IsType(serviceProvider.GetRequiredService()); Assert.IsType(serviceProvider.GetRequiredService()); Assert.IsType(serviceProvider.GetRequiredService()); Assert.IsType(serviceProvider.GetRequiredService()); Assert.IsType(serviceProvider.GetRequiredService()); Assert.IsType(serviceProvider.GetRequiredService()); var descriptors = serviceProvider.GetServices().SelectMany(x => x.GetDescriptors()).ToArray(); Assert.Contains(descriptors, x => x.Resource == ExternalAuthenticationResourcePermissions.Connections && x.Supports(CoreVerbs.View)); Assert.Contains(descriptors, x => x.Resource == ExternalAuthenticationResourcePermissions.PolicyDefaultRoles && x.Supports(CoreVerbs.Update)); Assert.NotNull(serviceProvider.GetRequiredService>().Value); Assert.Contains(serviceProvider.GetServices>(), x => x.GetType().Name == "ConfigureExternalAuthenticationRateLimiterOptions"); } [Fact] public void OpenIdConnectRegistrationUsesTheHardenedProviderClient() { var services = new ServiceCollection(); services.AddExternalAuthenticationServices(options => { options.AllowedUnlinkedIdentityPolicyTypes.Clear(); options.AllowedPermissionGrantSourceTypes.Clear(); }); services.AddOpenIdConnectExternalAuthentication(); Assert.Contains(services, descriptor => descriptor.ServiceType == typeof(IProviderHttpClient) && descriptor.ImplementationFactory is not null); Assert.Contains(services, descriptor => descriptor.ServiceType == typeof(OpenIdConnectExternalAuthenticationAdapter)); } [Fact] public void RoleDeletionContributorResolvesWhenIdentityIsNotRegistered() { var services = new ServiceCollection(); services.AddSingleton(new TestSystemClock(DateTimeOffset.UnixEpoch)); services.AddExternalAuthenticationServices(options => { options.AllowedUnlinkedIdentityPolicyTypes.Clear(); options.AllowedPermissionGrantSourceTypes.Clear(); }); using var serviceProvider = services.BuildServiceProvider(new ServiceProviderOptions { ValidateScopes = true }); using var scope = serviceProvider.CreateScope(); var contributor = Assert.Single(scope.ServiceProvider.GetServices()); Assert.IsType(contributor); Assert.Empty(scope.ServiceProvider.GetServices()); } }