< 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>
 12910public sealed class ApplicationAuthenticationOptionsValidator(IHostEnvironment? environment)
 11    : IValidateOptions<ApplicationAuthenticationOptions>
 12{
 12913    private readonly IHostEnvironment? _environment = environment;
 14
 15    /// <inheritdoc />
 16    public ValidateOptionsResult Validate(string? name, ApplicationAuthenticationOptions options)
 17    {
 22418        ArgumentNullException.ThrowIfNull(options);
 19
 22420        List<string> failures = [];
 21
 22422        ValidateApplicationAuthentication(options, failures);
 22423        ValidateOpenIdConnectProvider(options.Providers.OpenIdConnect, failures);
 22424        ValidateSaml2Provider(options.Providers.Saml2, failures);
 22425        ValidateExternalProvider("Microsoft", options.Providers.Microsoft, failures);
 22426        ValidateExternalProvider("Google", options.Providers.Google, failures);
 22427        ValidateExternalProvider("GitHub", options.Providers.GitHub, failures);
 28
 22429        return failures.Count == 0
 22430            ? ValidateOptionsResult.Success
 22431            : ValidateOptionsResult.Fail(failures);
 32    }
 33
 34    private void ValidateApplicationAuthentication(
 35        ApplicationAuthenticationOptions options,
 36        ICollection<string> failures)
 37    {
 22438        Require(
 22439            !string.IsNullOrWhiteSpace(options.DefaultScheme),
 22440            "ProjectTemplate:Authentication:DefaultScheme is required.",
 22441            failures);
 42
 22443        Require(
 22444            !string.IsNullOrWhiteSpace(options.DefaultChallengeScheme),
 22445            "ProjectTemplate:Authentication:DefaultChallengeScheme is required.",
 22446            failures);
 47
 22448        Require(
 22449            !string.IsNullOrWhiteSpace(options.DefaultSignInScheme),
 22450            "ProjectTemplate:Authentication:DefaultSignInScheme is required.",
 22451            failures);
 52
 22453        Require(
 22454            !options.Cookie.AllowInsecureHttp || _environment?.IsDevelopment() == true,
 22455            "ProjectTemplate:Authentication:Cookie:AllowInsecureHttp may only be enabled in the Development environment.
 22456            failures);
 57
 22458        if (!options.Enabled)
 59        {
 960            return;
 61        }
 62
 21563        Require(
 21564            options.Cookie.Enabled,
 21565            "ProjectTemplate:Authentication:Cookie:Enabled must be true when application authentication is enabled.",
 21566            failures);
 67
 21568        Require(
 21569            !string.IsNullOrWhiteSpace(options.Cookie.Scheme),
 21570            "ProjectTemplate:Authentication:Cookie:Scheme is required when application authentication is enabled.",
 21571            failures);
 72
 21573        Require(
 21574            options.Cookie.ExpireMinutes > 0,
 21575            "ProjectTemplate:Authentication:Cookie:ExpireMinutes must be greater than zero when application authenticati
 21576            failures);
 21577    }
 78
 79    private static void ValidateOpenIdConnectProvider(
 80        OpenIdConnectAuthenticationOptions options,
 81        ICollection<string> failures)
 82    {
 22483        if (!options.Enabled)
 84        {
 21985            return;
 86        }
 87
 88        const string prefix = "ProjectTemplate:Authentication:Providers:OpenIdConnect";
 89
 590        RequireProviderValue(prefix, nameof(options.Scheme), options.Scheme, failures);
 591        RequireProviderValue(prefix, nameof(options.DisplayName), options.DisplayName, failures);
 592        RequireProviderValue(prefix, nameof(options.Authority), options.Authority, failures);
 593        RequireProviderValue(prefix, nameof(options.ClientId), options.ClientId, failures);
 594        RequireProviderValue(prefix, nameof(options.CallbackPath), options.CallbackPath, failures);
 595        RequireProviderValue(prefix, nameof(options.ResponseType), options.ResponseType, failures);
 96
 597        Require(
 598            options.Scopes.Any(scope => !string.IsNullOrWhiteSpace(scope)),
 599            $"{prefix}:Scopes must contain at least one non-empty value when the OpenID Connect provider is enabled.",
 5100            failures);
 5101    }
 102
 103    private static void ValidateSaml2Provider(
 104        Saml2AuthenticationOptions options,
 105        ICollection<string> failures)
 106    {
 224107        if (!options.Enabled)
 108        {
 219109            return;
 110        }
 111
 112        const string prefix = "ProjectTemplate:Authentication:Providers:Saml2";
 113
 5114        RequireProviderValue(prefix, nameof(options.Scheme), options.Scheme, failures);
 5115        RequireProviderValue(prefix, nameof(options.DisplayName), options.DisplayName, failures);
 5116        RequireProviderValue(prefix, nameof(options.EntityId), options.EntityId, failures);
 5117        RequireProviderValue(prefix, nameof(options.MetadataUrl), options.MetadataUrl, failures);
 5118        RequireProviderValue(prefix, nameof(options.ModulePath), options.ModulePath, failures);
 5119    }
 120
 121    private static void ValidateExternalProvider(
 122        string providerName,
 123        ApplicationExternalAuthenticationProviderOptions options,
 124        ICollection<string> failures)
 125    {
 672126        if (!options.Enabled)
 127        {
 655128            return;
 129        }
 130
 17131        string prefix = $"ProjectTemplate:Authentication:Providers:{providerName}";
 132
 17133        RequireProviderValue(prefix, nameof(options.Scheme), options.Scheme, failures);
 17134        RequireProviderValue(prefix, nameof(options.DisplayName), options.DisplayName, failures);
 17135        RequireProviderValue(prefix, nameof(options.ClientId), options.ClientId, failures);
 17136        RequireProviderValue(prefix, nameof(options.ClientSecret), options.ClientSecret, failures);
 17137        RequireProviderValue(prefix, nameof(options.CallbackPath), options.CallbackPath, failures);
 17138    }
 139
 140    private static void RequireProviderValue(
 141        string prefix,
 142        string key,
 143        string? value,
 144        ICollection<string> failures)
 145    {
 140146        Require(
 140147            !string.IsNullOrWhiteSpace(value),
 140148            $"{prefix}:{key} is required when the provider is enabled.",
 140149            failures);
 140150    }
 151
 152    private static void Require(
 153        bool condition,
 154        string failureMessage,
 155        ICollection<string> failures)
 156    {
 1686157        if (!condition)
 158        {
 8159            failures.Add(failureMessage);
 160        }
 1686161    }
 162}