< Summary

Information
Class: Elsa.Identity.Features.IdentityFeature
Assembly: Elsa.Identity
File(s): /home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Identity/Features/IdentityFeature.cs
Line coverage
85%
Covered lines: 86
Uncovered lines: 15
Coverable lines: 101
Total lines: 244
Line coverage: 85.1%
Branch coverage
N/A
Covered branches: 0
Total branches: 0
Branch coverage: N/A
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

File(s)

/home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Identity/Features/IdentityFeature.cs

#LineLine coverage
 1using AspNetCore.Authentication.ApiKey;
 2using Elsa.Common.Features;
 3using Elsa.Common.Multitenancy;
 4using Elsa.Extensions;
 5using Elsa.Features.Abstractions;
 6using Elsa.Features.Attributes;
 7using Elsa.Features.Services;
 8using Elsa.Identity.Contracts;
 9using Elsa.Identity.Entities;
 10using Elsa.Identity.Multitenancy;
 11using Elsa.Identity.HostedServices;
 12using Elsa.Identity.Options;
 13using Elsa.Identity.Providers;
 14using Elsa.Identity.Services;
 15using JetBrains.Annotations;
 16using Microsoft.Extensions.DependencyInjection;
 17using Microsoft.Extensions.DependencyInjection.Extensions;
 18
 19namespace Elsa.Identity.Features;
 20
 21/// <summary>
 22/// Provides identity feature to authenticate &amp; authorize API requests.
 23/// </summary>
 24[DependsOn(typeof(SystemClockFeature))]
 25[PublicAPI]
 26public class IdentityFeature : FeatureBase
 27{
 28    /// <inheritdoc />
 529    public IdentityFeature(IModule module) : base(module)
 30    {
 531    }
 32
 33    /// <summary>
 34    /// Gets or sets the <see cref="IdentityTokenOptions"/>.
 35    /// </summary>
 1936    public Action<IdentityTokenOptions> TokenOptions { get; set; } = _ => { };
 37
 38    /// <summary>
 39    /// Gets or sets the <see cref="ApiKeyOptions"/>.
 40    /// </summary>
 1041    public Action<ApiKeyOptions> ApiKeyOptions { get; set; } = options =>
 542    {
 143        options.Realm = "Elsa Workflows";
 144        options.KeyName = "ApiKey";
 645    };
 46
 47    /// <summary>
 48    /// A delegate that configures the <see cref="UsersOptions"/>.
 49    /// </summary>
 1650    public Action<UsersOptions> UsersOptions { get; set; } = _ => { };
 51
 52    /// <summary>
 53    /// A delegate that configures the <see cref="ApplicationsOptions"/>.
 54    /// </summary>
 1655    public Action<ApplicationsOptions> ApplicationsOptions { get; set; } = _ => { };
 56
 57    /// <summary>
 58    /// A delegate that configures the <see cref="RolesOptions"/>.
 59    /// </summary>
 1960    public Action<RolesOptions> RolesOptions { get; set; } = _ => { };
 61
 62    /// <summary>
 63    /// A delegate that creates an instance of an implementation of <see cref="IUserStore"/>.
 64    /// </summary>
 1465    public Func<IServiceProvider, IUserStore> UserStore { get; set; } = sp => sp.GetRequiredService<MemoryUserStore>();
 66
 67    /// <summary>
 68    /// A delegate that creates an instance of an implementation of <see cref="IApplicationStore"/>.
 69    /// </summary>
 1370    public Func<IServiceProvider, IApplicationStore> ApplicationStore { get; set; } = sp => sp.GetRequiredService<Memory
 71
 72    /// <summary>
 73    /// A delegate that creates an instance of an implementation of <see cref="IRoleStore"/>.
 74    /// </summary>
 1475    public Func<IServiceProvider, IRoleStore> RoleStore { get; set; } = sp => sp.GetRequiredService<MemoryRoleStore>();
 76
 77    /// <summary>
 78    /// A delegate that creates an instance of an implementation of <see cref="IUserProvider"/>.
 79    /// </summary>
 1380    public Func<IServiceProvider, IUserProvider> UserProvider { get; set; } = sp => sp.GetRequiredService<StoreBasedUser
 81
 82    /// <summary>
 83    /// A delegate that creates an instance of an implementation of <see cref="IApplicationProvider"/>.
 84    /// </summary>
 1385    public Func<IServiceProvider, IApplicationProvider> ApplicationProvider { get; set; } = sp => sp.GetRequiredService<
 86
 87    /// <summary>
 88    /// A delegate that creates an instance of an implementation of <see cref="IRoleProvider"/>.
 89    /// </summary>
 1490    public Func<IServiceProvider, IRoleProvider> RoleProvider { get; set; } = sp => sp.GetRequiredService<StoreBasedRole
 91
 92    /// <summary>
 93    /// Configures the feature to use <see cref="ConfigurationBasedUserProvider"/>.
 94    /// </summary>
 095    public void UseStoreBasedUserProvider() => UserProvider = sp => sp.GetRequiredService<StoreBasedUserProvider>();
 96
 97    /// <summary>
 98    /// Configures the feature to use <see cref="ConfigurationBasedUserProvider"/>.
 99    /// </summary>
 100    public void UseConfigurationBasedUserProvider(Action<UsersOptions> configure)
 101    {
 6102        UserProvider = sp => sp.GetRequiredService<ConfigurationBasedUserProvider>();
 3103        UsersOptions += configure;
 3104    }
 105
 106    /// <summary>
 107    /// Configures the feature to use <see cref="AdminUserProvider"/>. The provider denies all users unless configured.
 108    /// </summary>
 109    public void UseAdminUserProvider()
 110    {
 0111        UserProvider = sp => sp.GetRequiredService<AdminUserProvider>();
 0112        RoleProvider = sp => sp.GetRequiredService<AdminRoleProvider>();
 0113    }
 114
 115    /// <summary>
 116    /// Configures the feature to use <see cref="AdminUserProvider"/> with an explicit admin user.
 117    /// </summary>
 118    public void UseAdminUserProvider(Action<AdminUserProviderOptions> configure)
 119    {
 0120        UseAdminUserProvider();
 0121        Services.Configure(configure);
 0122    }
 123
 124    /// <summary>
 125    /// Configures the feature to use the development admin user. Do not use in production.
 126    /// </summary>
 0127    public void UseDevelopmentAdminUserProvider() => UseAdminUserProvider(options =>
 0128    {
 0129        options.UserName = "admin";
 0130        options.Password = "password";
 0131    });
 132
 133    /// <summary>
 134    /// Configures the feature to use <see cref="StoreBasedApplicationProvider"/>.
 135    /// </summary>
 0136    public void UseStoreBasedApplicationProvider() => ApplicationProvider = sp => sp.GetRequiredService<StoreBasedApplic
 137
 138    /// <summary>
 139    /// Configures the feature to use <see cref="ConfigurationBasedApplicationProvider"/>.
 140    /// </summary>
 141    public void UseConfigurationBasedApplicationProvider(Action<ApplicationsOptions> configure)
 142    {
 6143        ApplicationProvider = sp => sp.GetRequiredService<ConfigurationBasedApplicationProvider>();
 3144        ApplicationsOptions += configure;
 3145    }
 146
 147    /// <summary>
 148    /// Configures the feature to use <see cref="StoreBasedRoleProvider"/>.
 149    /// </summary>
 0150    public void UseStoreBasedRoleProvider() => RoleProvider = sp => sp.GetRequiredService<StoreBasedRoleProvider>();
 151
 152    /// <summary>
 153    /// Configures the feature to use <see cref="ConfigurationBasedRoleProvider"/>.
 154    /// </summary>
 155    public void UseConfigurationBasedRoleProvider(Action<RolesOptions> configure)
 156    {
 9157        RoleProvider = sp => sp.GetRequiredService<ConfigurationBasedRoleProvider>();
 3158        RolesOptions += configure;
 3159    }
 160
 161    /// <inheritdoc />
 162    public override void Configure()
 163    {
 3164        Module.AddFastEndpointsAssembly(GetType());
 3165    }
 166
 167    /// <inheritdoc />
 168    public override void Apply()
 169    {
 5170        Services.Configure(TokenOptions);
 5171        Services.Configure(ApiKeyDefaults.AuthenticationScheme, ApiKeyOptions);
 5172        Services.Configure<AdminUserProviderOptions>(_ => { });
 5173        Services.Configure(UsersOptions);
 5174        Services.Configure(ApplicationsOptions);
 5175        Services.Configure(RolesOptions);
 176
 177        // The identity stores are tenant-scoped, so a host that never enables multitenancy still needs an
 178        // accessor. TryAdd leaves an existing registration -- notably MultitenancyFeature's -- untouched.
 5179        Services.TryAddSingleton<ITenantAccessor, DefaultTenantAccessor>();
 5180        Services.AddMemoryCache();
 5181        Services.Configure<PermissionStampOptions>(_ => { });
 5182        Services.AddHostedService<StoredPermissionValidator>();
 5183        Services.AddHostedService<IdentityBootstrapDiagnostic>();
 184
 185        // Memory stores.
 5186        Services
 5187            .AddMemoryStore<User, MemoryUserStore>()
 5188            .AddMemoryStore<Application, MemoryApplicationStore>()
 5189            .AddMemoryStore<Role, MemoryRoleStore>();
 190
 191        // User providers.
 5192        Services
 5193            .AddScoped<AdminUserProvider>()
 5194            .AddScoped<StoreBasedUserProvider>()
 5195            .AddScoped<ConfigurationBasedUserProvider>();
 196
 197        // Application providers.
 5198        Services
 5199            .AddScoped<StoreBasedApplicationProvider>()
 5200            .AddScoped<ConfigurationBasedApplicationProvider>();
 201
 202        // Role providers.
 5203        Services
 5204            .AddScoped<AdminRoleProvider>()
 5205            .AddScoped<StoreBasedRoleProvider>()
 5206            .AddScoped<ConfigurationBasedRoleProvider>();
 207
 208        // Tenant resolution strategies.
 5209        Services
 5210            .AddScoped<ITenantResolver, ClaimsTenantResolver>()
 5211            .AddScoped<ITenantResolver, CurrentUserTenantResolver>();
 212
 213        // Services.
 5214        Services
 5215            .AddScoped(UserStore)
 5216            .AddScoped(ApplicationStore)
 5217            .AddScoped(RoleStore)
 5218            .AddScoped(UserProvider)
 5219            .AddScoped(ApplicationProvider)
 5220            .AddScoped(RoleProvider)
 5221            .AddScoped<IUserManager, UserManager>()
 5222            .AddScoped<IRoleManager, RoleManager>()
 5223            .AddScoped<IRoleAuthorizationService, RoleAuthorizationService>()
 5224            .AddScoped<RoleSecurityNotifier>()
 5225            .AddScoped<IPermissionStampCalculator, PermissionStampCalculator>()
 5226            .AddScoped<PermissionStampValidator>()
 5227            .AddScoped<IRoleDeletionCoordinator, RoleDeletionCoordinator>()
 5228            .AddScoped<IUserDeletionCoordinator, UserDeletionCoordinator>()
 5229            .AddScoped<ISecretHasher, DefaultSecretHasher>()
 5230            .AddScoped<IElsaTokenService, DefaultElsaTokenService>()
 4231            .AddScoped<IAccessTokenIssuer>(sp => ActivatorUtilities.CreateInstance<DefaultAccessTokenIssuer>(sp))
 5232            .AddScoped<IIdentityRefreshTokenService, DefaultIdentityRefreshTokenService>()
 5233            .AddScoped<IUserCredentialsValidator, DefaultUserCredentialsValidator>()
 5234            .AddScoped<IApplicationCredentialsValidator, DefaultApplicationCredentialsValidator>()
 3235            .AddScoped<IApiKeyGenerator>(sp => sp.GetRequiredService<DefaultApiKeyGeneratorAndParser>())
 0236            .AddScoped<IApiKeyParser>(sp => sp.GetRequiredService<DefaultApiKeyGeneratorAndParser>())
 5237            .AddScoped<IClientIdGenerator, DefaultClientIdGenerator>()
 5238            .AddScoped<ISecretGenerator, DefaultSecretGenerator>()
 5239            .AddScoped<IRandomStringGenerator, DefaultRandomStringGenerator>()
 5240            .AddScoped<DefaultApiKeyGeneratorAndParser>()
 5241            .AddHttpContextAccessor()
 5242            ;
 5243    }
 244}