using AspNetCore.Authentication.ApiKey; using Elsa.Extensions; using Elsa.Features.Abstractions; using Elsa.Features.Attributes; using Elsa.Features.Services; using Elsa.Identity.Providers; using Elsa.Requirements; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authorization; using Microsoft.Extensions.DependencyInjection; namespace Elsa.Identity.Features; /// /// Provides an authorization feature that configures the system with JWT bearer and API key authentication. /// [DependsOn(typeof(IdentityFeature))] public class DefaultAuthenticationFeature : FeatureBase { private const string MultiScheme = "Jwt-or-ApiKey"; private Func _configureApiKeyAuthorization = builder => builder.AddApiKeyInAuthorizationHeader(); /// public DefaultAuthenticationFeature(IModule module) : base(module) { } /// /// Gets or sets the . /// public Type ApiKeyProviderType { get; set; } = typeof(DefaultApiKeyProvider); public Action ConfigureAuthorizationOptions { get; set; } = options => options.AddPolicy(IdentityPolicyNames.SecurityRoot, policy => policy.AddRequirements(new LocalHostPermissionRequirement())); /// /// Configures the API key provider type. /// /// The type of the API key provider. /// The current . public DefaultAuthenticationFeature UseApiKeyAuthorization() where T : class, IApiKeyProvider { _configureApiKeyAuthorization = builder => builder.AddApiKeyInAuthorizationHeader(); return this; } /// /// Configures the API key provider type to . /// /// The current . public DefaultAuthenticationFeature UseAdminApiKey() => UseApiKeyAuthorization(); /// /// Disables the local host requirement for the security root policy. /// We are considering removing this requirement by default in the future, in favor of a new "setup mode" paradigm. /// public DefaultAuthenticationFeature DisableLocalHostRequirement() { ConfigureAuthorizationOptions = options => options.AddPolicy(IdentityPolicyNames.SecurityRoot, policy => policy.RequireAuthenticatedUser()); return this; } /// public override void Apply() { Services.ConfigureOptions(); Services.ConfigureOptions(); var authBuilder = Services .AddAuthentication(MultiScheme) .AddPolicyScheme(MultiScheme, MultiScheme, options => { options.ForwardDefaultSelector = context => { return context.Request.Headers.Authorization.Any(x => x!.Contains(ApiKeyDefaults.AuthenticationScheme)) ? ApiKeyDefaults.AuthenticationScheme : JwtBearerDefaults.AuthenticationScheme; }; }) .AddJwtBearer(); _configureApiKeyAuthorization(authBuilder); Services.AddScoped(); Services.AddScoped(); Services.AddScoped(ApiKeyProviderType); Services.AddScoped(sp => (IApiKeyProvider)sp.GetRequiredService(ApiKeyProviderType)); Services.AddAuthorization(ConfigureAuthorizationOptions); } }