< 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@ca54e35c77799b76774b3805b6f075cdbc0c5fbe
Line coverage
100%
Covered lines: 45
Uncovered lines: 0
Coverable lines: 45
Total lines: 168
Line coverage: 100%
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 09/08/2025 - 20:34:03 Line coverage: 100% (14/14) Branch coverage: 100% (2/2) Total lines: 108 Tag: Kestrun/Kestrun@3790ee5884494a7a2a829344a47743e0bf492e7212/12/2025 - 17:27:19 Line coverage: 97.6% (41/42) Branch coverage: 100% (6/6) Total lines: 163 Tag: Kestrun/Kestrun@826bf9dcf9db118c5de4c78a3259bce9549f0dcd12/21/2025 - 06:07:10 Line coverage: 100% (45/45) Branch coverage: 100% (6/6) Total lines: 168 Tag: Kestrun/Kestrun@8cf7f77e55fd1fd046ea4e5413eb9ef96e49fe6a 09/08/2025 - 20:34:03 Line coverage: 100% (14/14) Branch coverage: 100% (2/2) Total lines: 108 Tag: Kestrun/Kestrun@3790ee5884494a7a2a829344a47743e0bf492e7212/12/2025 - 17:27:19 Line coverage: 97.6% (41/42) Branch coverage: 100% (6/6) Total lines: 163 Tag: Kestrun/Kestrun@826bf9dcf9db118c5de4c78a3259bce9549f0dcd12/21/2025 - 06:07:10 Line coverage: 100% (45/45) Branch coverage: 100% (6/6) Total lines: 168 Tag: Kestrun/Kestrun@8cf7f77e55fd1fd046ea4e5413eb9ef96e49fe6a

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor()100%11100%
get_DisplayName()100%11100%
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%
get_Deprecated()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/>
 1416    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    /// <inheritdoc/>
 20131    public bool Deprecated { get; set; }
 132
 133    /// <summary>
 134    /// Helper to copy values from a user-supplied ApiKeyAuthenticationOptions instance to the instance
 135    /// created by the framework inside AddApiKey(). Reassigning the local variable (opts = source) would
 136    /// not work because only the local reference changes – the framework keeps the original instance
 137    /// </summary>
 138    /// <param name="target">The target instance to which values will be copied. </param>
 139    public void ApplyTo(ApiKeyAuthenticationOptions target)
 140    {
 141        // Copy base AuthenticationSchemeOptions properties
 7142        target.ClaimsIssuer = ClaimsIssuer;
 7143        target.EventsType = EventsType;
 7144        target.Events = Events;
 7145        target.ApiKeyName = ApiKeyName;
 7146        target.In = In;
 7147        target.AdditionalHeaderNames = AdditionalHeaderNames;
 7148        target.AllowQueryStringFallback = AllowQueryStringFallback;
 7149        target.StaticApiKey = StaticApiKey;
 7150        target.AllowInsecureHttp = AllowInsecureHttp;
 7151        target.EmitChallengeHeader = EmitChallengeHeader;
 7152        target.ChallengeHeaderFormat = ChallengeHeaderFormat;
 7153        target.ValidateKeyAsync = ValidateKeyAsync;
 7154        target.ValidateCodeSettings = ValidateCodeSettings;
 7155        target.IssueClaims = IssueClaims;
 7156        target.IssueClaimsCodeSettings = IssueClaimsCodeSettings;
 7157        target.ClaimPolicyConfig = ClaimPolicyConfig;
 158
 159        // Copy IAuthenticationHostOptions properties
 7160        target.Host = Host;
 161        // OpenAPI / documentation properties(IOpenApiAuthenticationOptions)
 7162        target.GlobalScheme = GlobalScheme;
 7163        target.Description = Description;
 7164        target.DocumentationId = DocumentationId;
 7165        target.DisplayName = DisplayName;
 7166        target.Deprecated = Deprecated;
 7167    }
 168}