< Summary

Information
Class: ProjectTemplate.Web.Authentication.Options.ApplicationAuthenticationOptionsValidator
Assembly: ProjectTemplate.Web
File(s): /home/runner/work/NetCoreApplicationTemplate/NetCoreApplicationTemplate/src/ProjectTemplate.Web/Authentication/Options/ApplicationAuthenticationOptionsValidator.cs
Line coverage
100%
Covered lines: 82
Uncovered lines: 0
Coverable lines: 82
Total lines: 162
Line coverage: 100%
Branch coverage
93%
Covered branches: 15
Total branches: 16
Branch coverage: 93.7%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
Validate(...)100%22100%
ValidateApplicationAuthentication(...)83.33%66100%
ValidateOpenIdConnectProvider(...)100%22100%
ValidateSaml2Provider(...)100%22100%
ValidateExternalProvider(...)100%22100%
RequireProviderValue(...)100%11100%
Require(...)100%22100%

File(s)

/home/runner/work/NetCoreApplicationTemplate/NetCoreApplicationTemplate/src/ProjectTemplate.Web/Authentication/Options/ApplicationAuthenticationOptionsValidator.cs

#LineLine coverage
 1using Microsoft.Extensions.Options;
 2using ProjectTemplate.Web.Authentication.Providers.OpenIdConnect;
 3using ProjectTemplate.Web.Authentication.Providers.Saml2;
 4
 5namespace ProjectTemplate.Web.Authentication.Options;
 6
 7/// <summary>
 8/// Validates application authentication configuration during application startup.
 9/// </summary>
 19410public sealed class ApplicationAuthenticationOptionsValidator(IHostEnvironment? environment)
 11    : IValidateOptions<ApplicationAuthenticationOptions>
 12{
 19413    private readonly IHostEnvironment? _environment = environment;
 14
 15    /// <inheritdoc />
 16    public ValidateOptionsResult Validate(string? name, ApplicationAuthenticationOptions options)
 17    {
 32418        ArgumentNullException.ThrowIfNull(options);
 19
 32420        List<string> failures = [];
 21
 32422        ValidateApplicationAuthentication(options, failures);
 32423        ValidateOpenIdConnectProvider(options.Providers.OpenIdConnect, failures);
 32424        ValidateSaml2Provider(options.Providers.Saml2, failures);
 32425        ValidateExternalProvider("Microsoft", options.Providers.Microsoft, failures);
 32426        ValidateExternalProvider("Google", options.Providers.Google, failures);
 32427        ValidateExternalProvider("GitHub", options.Providers.GitHub, failures);
 28
 32429        return failures.Count == 0
 32430            ? ValidateOptionsResult.Success
 32431            : ValidateOptionsResult.Fail(failures);
 32    }
 33
 34    private void ValidateApplicationAuthentication(
 35        ApplicationAuthenticationOptions options,
 36        ICollection<string> failures)
 37    {
 32438        Require(
 32439            !string.IsNullOrWhiteSpace(options.DefaultScheme),
 32440            "ProjectTemplate:Authentication:DefaultScheme is required.",
 32441            failures);
 42
 32443        Require(
 32444            !string.IsNullOrWhiteSpace(options.DefaultChallengeScheme),
 32445            "ProjectTemplate:Authentication:DefaultChallengeScheme is required.",
 32446            failures);
 47
 32448        Require(
 32449            !string.IsNullOrWhiteSpace(options.DefaultSignInScheme),
 32450            "ProjectTemplate:Authentication:DefaultSignInScheme is required.",
 32451            failures);
 52
 32453        Require(
 32454            !options.Cookie.AllowInsecureHttp || _environment?.IsDevelopment() == true,
 32455            "ProjectTemplate:Authentication:Cookie:AllowInsecureHttp may only be enabled in the Development environment.
 32456            failures);
 57
 32458        if (!options.Enabled)
 59        {
 1460            return;
 61        }
 62
 31063        Require(
 31064            options.Cookie.Enabled,
 31065            "ProjectTemplate:Authentication:Cookie:Enabled must be true when application authentication is enabled.",
 31066            failures);
 67
 31068        Require(
 31069            !string.IsNullOrWhiteSpace(options.Cookie.Scheme),
 31070            "ProjectTemplate:Authentication:Cookie:Scheme is required when application authentication is enabled.",
 31071            failures);
 72
 31073        Require(
 31074            options.Cookie.ExpireMinutes > 0,
 31075            "ProjectTemplate:Authentication:Cookie:ExpireMinutes must be greater than zero when application authenticati
 31076            failures);
 31077    }
 78
 79    private static void ValidateOpenIdConnectProvider(
 80        OpenIdConnectAuthenticationOptions options,
 81        ICollection<string> failures)
 82    {
 32483        if (!options.Enabled)
 84        {
 31485            return;
 86        }
 87
 88        const string prefix = "ProjectTemplate:Authentication:Providers:OpenIdConnect";
 89
 1090        RequireProviderValue(prefix, nameof(options.Scheme), options.Scheme, failures);
 1091        RequireProviderValue(prefix, nameof(options.DisplayName), options.DisplayName, failures);
 1092        RequireProviderValue(prefix, nameof(options.Authority), options.Authority, failures);
 1093        RequireProviderValue(prefix, nameof(options.ClientId), options.ClientId, failures);
 1094        RequireProviderValue(prefix, nameof(options.CallbackPath), options.CallbackPath, failures);
 1095        RequireProviderValue(prefix, nameof(options.ResponseType), options.ResponseType, failures);
 96
 1097        Require(
 1098            options.Scopes.Any(scope => !string.IsNullOrWhiteSpace(scope)),
 1099            $"{prefix}:Scopes must contain at least one non-empty value when the OpenID Connect provider is enabled.",
 10100            failures);
 10101    }
 102
 103    private static void ValidateSaml2Provider(
 104        Saml2AuthenticationOptions options,
 105        ICollection<string> failures)
 106    {
 324107        if (!options.Enabled)
 108        {
 314109            return;
 110        }
 111
 112        const string prefix = "ProjectTemplate:Authentication:Providers:Saml2";
 113
 10114        RequireProviderValue(prefix, nameof(options.Scheme), options.Scheme, failures);
 10115        RequireProviderValue(prefix, nameof(options.DisplayName), options.DisplayName, failures);
 10116        RequireProviderValue(prefix, nameof(options.EntityId), options.EntityId, failures);
 10117        RequireProviderValue(prefix, nameof(options.MetadataUrl), options.MetadataUrl, failures);
 10118        RequireProviderValue(prefix, nameof(options.ModulePath), options.ModulePath, failures);
 10119    }
 120
 121    private static void ValidateExternalProvider(
 122        string providerName,
 123        ApplicationExternalAuthenticationProviderOptions options,
 124        ICollection<string> failures)
 125    {
 972126        if (!options.Enabled)
 127        {
 938128            return;
 129        }
 130
 34131        string prefix = $"ProjectTemplate:Authentication:Providers:{providerName}";
 132
 34133        RequireProviderValue(prefix, nameof(options.Scheme), options.Scheme, failures);
 34134        RequireProviderValue(prefix, nameof(options.DisplayName), options.DisplayName, failures);
 34135        RequireProviderValue(prefix, nameof(options.ClientId), options.ClientId, failures);
 34136        RequireProviderValue(prefix, nameof(options.ClientSecret), options.ClientSecret, failures);
 34137        RequireProviderValue(prefix, nameof(options.CallbackPath), options.CallbackPath, failures);
 34138    }
 139
 140    private static void RequireProviderValue(
 141        string prefix,
 142        string key,
 143        string? value,
 144        ICollection<string> failures)
 145    {
 280146        Require(
 280147            !string.IsNullOrWhiteSpace(value),
 280148            $"{prefix}:{key} is required when the provider is enabled.",
 280149            failures);
 280150    }
 151
 152    private static void Require(
 153        bool condition,
 154        string failureMessage,
 155        ICollection<string> failures)
 156    {
 2516157        if (!condition)
 158        {
 16159            failures.Add(failureMessage);
 160        }
 2516161    }
 162}