< Summary

Information
Class: Elsa.ExternalAuthentication.Options.RedirectValidationOptions
Assembly: Elsa.ExternalAuthentication
File(s): /home/runner/work/elsa-core/elsa-core/src/modules/Elsa.ExternalAuthentication/Options/ExternalAuthenticationOptions.cs
Line coverage
100%
Covered lines: 4
Uncovered lines: 0
Coverable lines: 4
Total lines: 257
Line coverage: 100%
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

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
get_ExternalCallbackBaseUri()100%11100%
get_RequirePkceS256()100%11100%
get_AllowDevelopmentLoopbackCallbacks()100%11100%
get_MaximumReturnPathLength()100%11100%

File(s)

/home/runner/work/elsa-core/elsa-core/src/modules/Elsa.ExternalAuthentication/Options/ExternalAuthenticationOptions.cs

#LineLine coverage
 1using Elsa.ExternalAuthentication.Models;
 2using Elsa.ExternalAuthentication.Permissions;
 3using Microsoft.Extensions.Configuration;
 4
 5namespace Elsa.ExternalAuthentication.Options;
 6
 7/// <summary>
 8/// Configures deployment-owned External Authentication behavior.
 9/// </summary>
 10public class ExternalAuthenticationOptions
 11{
 12    /// <summary>Deployment-owned broker clients. Configuration key: <c>AuthenticationClients</c>.</summary>
 13    [ConfigurationKeyName("AuthenticationClients")]
 14    public ICollection<AuthenticationClient> Clients { get; set; } = new List<AuthenticationClient>();
 15
 16    /// <summary>Controls brokered Elsa username/password login as a normal login method.</summary>
 17    public LocalLoginMethodOptions LocalLogin { get; set; } = new();
 18
 19    /// <summary>Immutable configuration-owned connections. Configuration key: <c>Connections</c>.</summary>
 20    [ConfigurationKeyName("Connections")]
 21    public ICollection<IdentityProviderConnection> ConfigurationConnections { get; set; } = new List<IdentityProviderCon
 22
 23    /// <summary>Enables the optional database connection source and persisted management surface.</summary>
 24    public bool EnableDatabaseConnections { get; set; } = true;
 25
 26    /// <summary>Allows a database-owned host connection to explicitly supersede a configuration-owned connection with t
 27    public bool AllowConfigurationConnectionOverrides { get; set; }
 28
 29    /// <summary>Adapter types permitted by this deployment. An empty collection permits every installed adapter.</summa
 30    public ICollection<string> AllowedAdapterTypes { get; set; } = new List<string>();
 31
 32    /// <summary>Unlinked identity policy types permitted by this deployment.</summary>
 33    public ICollection<string> AllowedUnlinkedIdentityPolicyTypes { get; set; } = ["reject", "create-user"];
 34
 35    /// <summary>External user matcher types permitted by this deployment.</summary>
 36    public ICollection<string> AllowedExternalUserMatcherTypes { get; set; } = new List<string>();
 37
 38    /// <summary>Permission grant source types permitted by this deployment.</summary>
 39    public ICollection<string> AllowedPermissionGrantSourceTypes { get; set; } = ["elsa-roles", "claim-mapping", "group-
 40
 41    /// <summary>Controls the deployment default and database override boundary for unlinked identities.</summary>
 42    public UnlinkedIdentityPolicyOptions UnlinkedIdentityPolicy { get; set; } = new();
 43
 44    /// <summary>Defines deployment-wide Elsa permission allow and deny boundaries.</summary>
 45    public PermissionGrantOptions PermissionGrants { get; set; } = new();
 46
 47    /// <summary>Configures transaction, code, preview, and session lifetimes.</summary>
 48    public ExternalAuthenticationLifetimesOptions Lifetimes { get; set; } = new();
 49
 50    /// <summary>Defines default projected-claim size limits.</summary>
 51    public ExternalAuthenticationClaimsOptions Claims { get; set; } = new();
 52
 53    /// <summary>Configures anonymous broker endpoint rate limits.</summary>
 54    public ExternalAuthenticationRateLimitOptions RateLimits { get; set; } = new();
 55
 56    /// <summary>Controls provider HTTP destinations, redirects, timeouts, and response limits.</summary>
 57    public ProviderEgressOptions ProviderEgress { get; set; } = new();
 58
 59    /// <summary>Controls callback, return-path, and broker-client PKCE validation.</summary>
 60    public RedirectValidationOptions Redirects { get; set; } = new();
 61
 62    /// <summary>Reserved broker-side description of WebAssembly persistence; Studio enforces its host-local setting.</s
 63    public WebAssemblyCredentialPersistenceOptions WebAssemblyPersistence { get; set; } = new();
 64
 65    /// <summary>Defines the deployment default for upstream provider logout.</summary>
 66    public ExternalAuthenticationLogoutOptions Logout { get; set; } = new();
 67
 68    /// <summary>Prevents management changes from removing the last normal login path without recovery.</summary>
 69    public FinalLoginPathGuardOptions FinalLoginPathGuard { get; set; } = new();
 70
 71    /// <summary>Configures optional operational surfaces.</summary>
 72    public ExternalAuthenticationOperationsOptions Operations { get; set; } = new();
 73
 74    /// <summary>Configures stable keyed hashing for persisted opaque handles and external subjects.</summary>
 75    public ExternalAuthenticationHandleHashingOptions HandleHashing { get; set; } = new();
 76}
 77
 78/// <summary>Deployment-owned availability and presentation settings for broker-local credential sign-in.</summary>
 79public class LocalLoginMethodOptions
 80{
 81    /// <summary>Whether brokered local credentials appear as a normal login method.</summary>
 82    public bool IsEnabled { get; set; } = true;
 83    /// <summary>Text shown by login method discovery.</summary>
 84    public string DisplayName { get; set; } = "Elsa account";
 85    /// <summary>Trusted server-hosted icon identifier.</summary>
 86    public string IconId { get; set; } = "elsa";
 87    /// <summary>Deterministic chooser order.</summary>
 88    public int DisplayOrder { get; set; }
 89    /// <summary>Whether local login is the preferred sign-in method for its scope; this never causes automatic redirect
 90    public bool IsPreferred { get; set; }
 91}
 92
 93/// <summary>Configures the deployment-owned default unlinked identity policy.</summary>
 94public class UnlinkedIdentityPolicyOptions
 95{
 96    /// <summary>Default registered policy type. The safe default rejects unlinked identities.</summary>
 97    public string DefaultType { get; set; } = "reject";
 98    /// <summary>Whether a database-owned connection may select another deployment-allowed policy.</summary>
 99    public bool AllowDatabaseConnectionOverride { get; set; }
 100}
 101
 102/// <summary>Defines deployment-level boundaries applied after grant sources resolve candidate permissions.</summary>
 103public class PermissionGrantOptions
 104{
 105    /// <summary>When empty, all syntactically valid permission names are eligible unless denied.</summary>
 106    public ICollection<string> AllowedPermissions { get; set; } = new List<string>();
 107    /// <summary>Exact permission names denied regardless of grant source.</summary>
 108    public ICollection<string> DeniedPermissions { get; set; } = new List<string>();
 109}
 110
 111/// <summary>Configures bounded authentication flow and session lifetimes.</summary>
 112public class ExternalAuthenticationLifetimesOptions
 113{
 114    /// <summary>Maximum age of a broker or provider correlation transaction.</summary>
 115    public TimeSpan BrokerTransactionLifetime { get; set; } = TimeSpan.FromMinutes(10);
 116    /// <summary>Maximum age of a single-use broker completion code.</summary>
 117    public TimeSpan CompletionCodeLifetime { get; set; } = TimeSpan.FromMinutes(1);
 118    /// <summary>Maximum age of preview state and its one-time result.</summary>
 119    public TimeSpan PreviewLifetime { get; set; } = TimeSpan.FromMinutes(10);
 120    /// <summary>Absolute maximum external authentication session age.</summary>
 121    public TimeSpan MaximumSessionAge { get; set; } = TimeSpan.FromHours(8);
 122}
 123
 124/// <summary>Defines default bounds for normalized projected external claims.</summary>
 125public class ExternalAuthenticationClaimsOptions
 126{
 127    /// <summary>Maximum number of projected claims.</summary>
 128    public int MaximumClaimCount { get; set; } = 64;
 129    /// <summary>Maximum length of one projected string value.</summary>
 130    public int MaximumValueLength { get; set; } = 1_024;
 131    /// <summary>Maximum aggregate UTF-8 size of projected claims.</summary>
 132    public int MaximumTotalBytes { get; set; } = 16 * 1_024;
 133}
 134
 135public class ExternalAuthenticationRateLimitOptions
 136{
 137    /// <summary>
 138    /// Selects the partition key used by the broker's named rate-limit policies.
 139    /// Remote IP is the secure default because it cannot be bypassed by a caller-supplied client identifier.
 140    /// </summary>
 141    public ExternalAuthenticationRateLimitPartitionStrategy PartitionStrategy { get; set; } = ExternalAuthenticationRate
 142    /// <summary>Login method discovery rate limit.</summary>
 143    public RateLimitRule Discovery { get; set; } = new(60, TimeSpan.FromMinutes(1));
 144    /// <summary>External provider initiation rate limit.</summary>
 145    public RateLimitRule ExternalInitiation { get; set; } = new(20, TimeSpan.FromMinutes(1));
 146    /// <summary>Broker-local credential initiation rate limit.</summary>
 147    public RateLimitRule LocalInitiation { get; set; } = new(10, TimeSpan.FromMinutes(1));
 148    /// <summary>Provider callback rate limit.</summary>
 149    public RateLimitRule ProviderCallback { get; set; } = new(60, TimeSpan.FromMinutes(1));
 150    /// <summary>Authorization-code and refresh-token exchange rate limit.</summary>
 151    public RateLimitRule TokenExchange { get; set; } = new(30, TimeSpan.FromMinutes(1));
 152}
 153
 154/// <summary>Selects the server-derived value used to partition anonymous broker rate limits.</summary>
 155public enum ExternalAuthenticationRateLimitPartitionStrategy
 156{
 157    /// <summary>Partition by remote IP address.</summary>
 158    RemoteIp,
 159    /// <summary>Partition by registered client identifier and remote IP address.</summary>
 160    ClientIdAndRemoteIp
 161}
 162
 163/// <summary>A fixed-window permit limit.</summary>
 164public sealed record RateLimitRule(int PermitLimit, TimeSpan Window);
 165
 166/// <summary>Controls outbound traffic to identity providers.</summary>
 167public class ProviderEgressOptions
 168{
 169    /// <summary>Reject non-HTTPS provider endpoints.</summary>
 170    public bool RequireHttps { get; set; } = true;
 171    /// <summary>Allow resolved private, loopback, link-local, or otherwise non-public destinations.</summary>
 172    public bool AllowPrivateNetworkDestinations { get; set; }
 173    /// <summary>Maximum redirects followed after validating every destination.</summary>
 174    public int MaximumRedirects { get; set; } = 3;
 175    /// <summary>Maximum outbound connection establishment time.</summary>
 176    public TimeSpan ConnectTimeout { get; set; } = TimeSpan.FromSeconds(10);
 177    /// <summary>Maximum complete provider request time.</summary>
 178    public TimeSpan RequestTimeout { get; set; } = TimeSpan.FromSeconds(10);
 179    /// <summary>Maximum discovery document size.</summary>
 180    public long MaximumDiscoveryResponseBytes { get; set; } = 1 * 1_024 * 1_024;
 181    /// <summary>Maximum token endpoint response size.</summary>
 182    public long MaximumTokenResponseBytes { get; set; } = 256 * 1_024;
 183    /// <summary>Maximum UserInfo response size.</summary>
 184    public long MaximumUserInfoResponseBytes { get; set; } = 256 * 1_024;
 185    /// <summary>Optional exact host allowlist. An empty collection does not add a host restriction.</summary>
 186    public ICollection<string> AllowedHosts { get; set; } = new List<string>();
 187    /// <summary>Optional deployment-approved HTTP(S) proxy without embedded credentials.</summary>
 188    public Uri? ProxyUri { get; set; }
 189}
 190
 191/// <summary>Controls broker-client callback and return-path validation.</summary>
 192public class RedirectValidationOptions
 193{
 194    /// <summary>Deployment-owned public base URI used to derive upstream provider callbacks.</summary>
 147195    public Uri? ExternalCallbackBaseUri { get; set; }
 196    /// <summary>Reserved compatibility preference; the broker currently always requires S256 PKCE.</summary>
 180197    public bool RequirePkceS256 { get; set; } = true;
 198    /// <summary>Allow explicit HTTP loopback callback registrations for development.</summary>
 15199    public bool AllowDevelopmentLoopbackCallbacks { get; set; }
 200    /// <summary>Reserved configurable limit; the current validator enforces a fixed 2,048-character maximum.</summary>
 179201    public int MaximumReturnPathLength { get; set; } = 2_048;
 202}
 203
 204/// <summary>Describes a broker-side WebAssembly persistence preference; the Studio host owns enforcement.</summary>
 205public class WebAssemblyCredentialPersistenceOptions
 206{
 207    /// <summary>Selected credential persistence mode.</summary>
 208    public BrowserCredentialPersistence Persistence { get; set; } = BrowserCredentialPersistence.Memory;
 209    /// <summary>Require a deployment-visible warning for persistent browser storage.</summary>
 210    public bool RequireExplicitPersistentStorageWarning { get; set; } = true;
 211}
 212
 213/// <summary>Configures the default upstream sign-out behavior.</summary>
 214public class ExternalAuthenticationLogoutOptions
 215{
 216    /// <summary>Reserved deployment preference; current connections default directly to <see cref="UpstreamLogoutMode.D
 217    public UpstreamLogoutMode DefaultUpstreamLogoutMode { get; set; } = UpstreamLogoutMode.Disabled;
 218}
 219
 220/// <summary>Protects deployment access when a connection mutation removes a normal login method.</summary>
 221public class FinalLoginPathGuardOptions
 222{
 223    /// <summary>Enables the guard.</summary>
 224    public bool IsEnabled { get; set; } = true;
 225    /// <summary>Require another normal method, local login, break glass, or privileged confirmation.</summary>
 226    public bool RequireRecoveryMethod { get; set; } = true;
 227    /// <summary>Permission required for a confirmed final-login-path override.</summary>
 228    public string PrivilegedOverridePermission { get; set; } = ExternalAuthenticationPermissions.ProviderTrustUnsafe;
 229    /// <summary>Set by deployment configuration when a separately hosted break-glass method remains available.</summary
 230    public bool HasBreakGlassAuthentication { get; set; }
 231}
 232
 233/// <summary>Enables optional operational surfaces without making them readiness dependencies.</summary>
 234public class ExternalAuthenticationOperationsOptions
 235{
 236    /// <summary>Expose permission-guarded external session list and revoke endpoints.</summary>
 237    public bool EnableSessionAdministration { get; set; } = true;
 238    /// <summary>Reserved host preference; register the check explicitly with <c>AddExternalAuthenticationHealthCheck</c
 239    public bool EnableHealthCheck { get; set; }
 240    /// <summary>Reserved preferred check name for host integration.</summary>
 241    public string HealthCheckName { get; set; } = "external-authentication";
 242    /// <summary>Reserved preferred check tags for host integration.</summary>
 243    public ICollection<string> HealthCheckTags { get; set; } = ["external-authentication", "optional"];
 244}
 245
 246/// <summary>
 247/// Configures the keyed hashes used for opaque broker handles, external subjects, and secret generations.
 248/// </summary>
 249public class ExternalAuthenticationHandleHashingOptions
 250{
 251    /// <summary>
 252    /// A base64-encoded key containing at least 256 bits of entropy. All nodes that share External
 253    /// Authentication persistence must use the same value. When omitted, a process-local key is
 254    /// generated for single-node development.
 255    /// </summary>
 256    public string? SharedKeyBase64 { get; set; }
 257}