< Summary - Kestrun — Combined Coverage

Information
Class: Kestrun.Authentication.ApiKeyAuthenticationOptions
Assembly: Kestrun
File(s): /home/runner/work/Kestrun/Kestrun/src/CSharp/Kestrun/Authentication/ApiKeyAuthenticationOptions.cs
Tag: Kestrun/Kestrun@0d738bf294e6281b936d031e1979d928007495ff
Line coverage
97%
Covered lines: 41
Uncovered lines: 1
Coverable lines: 42
Total lines: 163
Line coverage: 97.6%
Branch coverage
100%
Covered branches: 6
Total branches: 6
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Coverage history

Coverage history 0 25 50 75 100 08/26/2025 - 14:53:17 Line coverage: 100% (14/14) Branch coverage: 100% (2/2) Total lines: 108 Tag: Kestrun/Kestrun@78d1e497d8ba989d121b57aa39aa3c6b22de743112/12/2025 - 17:27:19 Line coverage: 97.6% (41/42) Branch coverage: 100% (6/6) Total lines: 163 Tag: Kestrun/Kestrun@826bf9dcf9db118c5de4c78a3259bce9549f0dcd 08/26/2025 - 14:53:17 Line coverage: 100% (14/14) Branch coverage: 100% (2/2) Total lines: 108 Tag: Kestrun/Kestrun@78d1e497d8ba989d121b57aa39aa3c6b22de743112/12/2025 - 17:27:19 Line coverage: 97.6% (41/42) Branch coverage: 100% (6/6) Total lines: 163 Tag: Kestrun/Kestrun@826bf9dcf9db118c5de4c78a3259bce9549f0dcd

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor()100%11100%
get_DisplayName()100%210%
get_GlobalScheme()100%11100%
get_Description()100%11100%
get_DocumentationId()100%11100%
get_Host()100%11100%
get_Logger()100%44100%
get_ApiKeyName()100%11100%
get_In()100%11100%
get_AdditionalHeaderNames()100%11100%
get_AllowQueryStringFallback()100%11100%
get_StaticApiKey()100%11100%
get_StaticApiKeyAsBytes()100%22100%
get_AllowInsecureHttp()100%11100%
get_EmitChallengeHeader()100%11100%
get_ChallengeHeaderFormat()100%11100%
get_ValidateKeyAsync()100%11100%
get_ValidateCodeSettings()100%11100%
get_IssueClaims()100%11100%
get_IssueClaimsCodeSettings()100%11100%
get_ClaimPolicyConfig()100%11100%
ApplyTo(...)100%11100%

File(s)

/home/runner/work/Kestrun/Kestrun/src/CSharp/Kestrun/Authentication/ApiKeyAuthenticationOptions.cs

#LineLine coverage
 1using System.Security.Claims;
 2using System.Text;
 3using Kestrun.Claims;
 4using Kestrun.Hosting;
 5using Microsoft.AspNetCore.Authentication;
 6using Microsoft.OpenApi;
 7
 8namespace Kestrun.Authentication;
 9
 10/// <summary>
 11/// Options for API key authentication, including header names, validation, and claims issuance.
 12/// </summary>
 3913public class ApiKeyAuthenticationOptions() : AuthenticationSchemeOptions, IAuthenticationCommonOptions, IAuthenticationH
 14{
 15    /// <inheritdoc/>
 016    public string? DisplayName { get; set; }
 17    /// <inheritdoc/>
 2018    public bool GlobalScheme { get; set; }
 19
 20    /// <inheritdoc/>
 2021    public string? Description { get; set; }
 22
 23    /// <inheritdoc/>
 7724    public string[] DocumentationId { get; set; } = [];
 25
 26    /// <inheritdoc/>
 13627    public KestrunHost Host { get; set; } = default!;
 28
 29    private Serilog.ILogger? _logger;
 30    /// <inheritdoc/>
 31    public Serilog.ILogger Logger
 32    {
 5033        get => _logger ?? (Host is null ? Serilog.Log.Logger : Host.Logger); set => _logger = value;
 34    }
 35    /// <summary>
 36    /// Name of to look for the API key.
 37    /// </summary>
 9538    public string ApiKeyName { get; set; } = "X-Api-Key";
 39
 40    /// <summary>
 41    /// Location to look for the API key.
 42    /// </summary>
 6543    public ParameterLocation In { get; set; } = ParameterLocation.Header;
 44
 45    /// <summary>
 46    /// Other headers to try if the primary one is missing.
 47    /// <para>Defaults to empty.</para>
 48    /// <para>Use this to support multiple header names for the API key.</para>
 49    /// </summary>
 6950    public string[] AdditionalHeaderNames { get; set; } = [];
 51
 52    /// <summary>
 53    /// If true, also look for the key in the query string.
 54    /// <para>Defaults to false.</para>
 55    /// <para>Note: this is less secure, as query strings can be logged.</para>
 56    /// <para>Use with caution.</para>
 57    /// </summary>
 3158    public bool AllowQueryStringFallback { get; set; }
 59
 60    /// <summary>
 61    /// Single expected API key (used if ValidateKey is not set).
 62    /// <para>Defaults to null.</para>
 63    /// <para>Use this for simple scenarios where you have a known key.</para>
 64    /// </summary>
 6965    public string? StaticApiKey { get; set; }
 66
 67    /// <summary>
 68    /// Gets the expected API key as a UTF-8 byte array, or null if <see cref="StaticApiKey"/> is not set.
 69    /// </summary>
 2070    public byte[]? StaticApiKeyAsBytes => StaticApiKey is not null ? Encoding.UTF8.GetBytes(StaticApiKey) : null;
 71
 72    /// <summary>
 73    /// If true, allows API key authentication over insecure HTTP connections.
 74    /// </summary>
 4075    public bool AllowInsecureHttp { get; set; }
 76
 77    /// <summary>
 78    /// If true, includes the <c>WWW-Authenticate</c> header in 401 responses.
 79    /// <para>Default: <c>true</c>.</para>
 80    /// <para>Set to <c>false</c> to suppress automatic hints to clients.</para>
 81    /// </summary>
 6882    public bool EmitChallengeHeader { get; set; } = true;
 83
 84    /// <summary>
 85    /// Format for the <c>WWW-Authenticate</c> header in 401 responses.
 86    /// <para>
 87    /// If set to <c>ApiKeyHeader</c>, emits <c>ApiKey header="X-Api-Key"</c>.
 88    /// If set to <c>HeaderOnly</c>, emits just the header name.
 89    /// </para>
 90    /// </summary>
 2291    public ApiKeyChallengeFormat ChallengeHeaderFormat { get; set; } = ApiKeyChallengeFormat.ApiKeyHeader;
 92
 93    /// <summary>
 94    /// Called to validate the raw key string. Return true if valid.
 95    /// <para>This is called for every request, so it should be fast.</para>
 96    /// </summary>
 6497    public Func<HttpContext, string, byte[], Task<bool>> ValidateKeyAsync { get; set; } = (_, _, _) => Task.FromResult(f
 98
 99    /// <summary>
 100    /// Settings for the authentication code, if using a script.
 101    /// </summary>
 102    /// <remarks>
 103    /// This allows you to specify the language, code, and additional imports/refs.
 104    /// </remarks>
 63105    public AuthenticationCodeSettings ValidateCodeSettings { get; set; } = new();
 106
 107    /// <summary>
 108    /// After credentials are valid, this is called to add extra Claims.
 109    /// Parameters: HttpContext, username → IEnumerable of extra claims.
 110    /// </summary>
 28111    public Func<HttpContext, string, Task<IEnumerable<Claim>>>? IssueClaims { get; set; }
 112
 113    /// <summary>
 114    /// Settings for the claims issuing code, if using a script.
 115    /// </summary>
 116    /// <remarks>
 117    /// This allows you to specify the language, code, and additional imports/refs for claims issuance.
 118    /// </remarks>
 63119    public AuthenticationCodeSettings IssueClaimsCodeSettings { get; set; } = new();
 120
 121    /// <summary>
 122    /// Gets or sets the claim policy configuration.
 123    /// </summary>
 124    /// <remarks>
 125    /// This allows you to define multiple authorization policies based on claims.
 126    /// Each policy can specify a claim type and allowed values.
 127    /// </remarks>
 21128    public ClaimPolicyConfig? ClaimPolicyConfig { get; set; }
 129
 130    /// <summary>
 131    /// Helper to copy values from a user-supplied ApiKeyAuthenticationOptions instance to the instance
 132    /// created by the framework inside AddApiKey(). Reassigning the local variable (opts = source) would
 133    /// not work because only the local reference changes – the framework keeps the original instance
 134    /// </summary>
 135    /// <param name="target">The target instance to which values will be copied. </param>
 136    public void ApplyTo(ApiKeyAuthenticationOptions target)
 137    {
 138        // Copy base AuthenticationSchemeOptions properties
 7139        target.ClaimsIssuer = ClaimsIssuer;
 7140        target.EventsType = EventsType;
 7141        target.Events = Events;
 7142        target.ApiKeyName = ApiKeyName;
 7143        target.In = In;
 7144        target.AdditionalHeaderNames = AdditionalHeaderNames;
 7145        target.AllowQueryStringFallback = AllowQueryStringFallback;
 7146        target.StaticApiKey = StaticApiKey;
 7147        target.AllowInsecureHttp = AllowInsecureHttp;
 7148        target.EmitChallengeHeader = EmitChallengeHeader;
 7149        target.ChallengeHeaderFormat = ChallengeHeaderFormat;
 7150        target.ValidateKeyAsync = ValidateKeyAsync;
 7151        target.ValidateCodeSettings = ValidateCodeSettings;
 7152        target.IssueClaims = IssueClaims;
 7153        target.IssueClaimsCodeSettings = IssueClaimsCodeSettings;
 7154        target.ClaimPolicyConfig = ClaimPolicyConfig;
 155
 156        // Copy IAuthenticationHostOptions properties
 7157        target.Host = Host;
 158        // OpenAPI / documentation properties(IOpenApiAuthenticationOptions)
 7159        target.GlobalScheme = GlobalScheme;
 7160        target.Description = Description;
 7161        target.DocumentationId = DocumentationId;
 7162    }
 163}