< Summary

Information
Class: ProjectTemplate.Web.Authentication.Extensions.AuthenticationServiceExtensions
Assembly: ProjectTemplate.Web
File(s): /home/runner/work/NetCoreApplicationTemplate/NetCoreApplicationTemplate/src/ProjectTemplate.Web/Authentication/Extensions/AuthenticationServiceExtensions.cs
Line coverage
100%
Covered lines: 82
Uncovered lines: 0
Coverable lines: 82
Total lines: 156
Line coverage: 100%
Branch coverage
100%
Covered branches: 4
Total branches: 4
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
AddApplicationAuthentication(...)100%11100%
AddApplicationAuthentication(...)100%22100%
UseApplicationAuthentication(...)100%22100%

File(s)

/home/runner/work/NetCoreApplicationTemplate/NetCoreApplicationTemplate/src/ProjectTemplate.Web/Authentication/Extensions/AuthenticationServiceExtensions.cs

#LineLine coverage
 1using Microsoft.AspNetCore.Authentication;
 2using Microsoft.AspNetCore.Authentication.Cookies;
 3using Microsoft.Extensions.Options;
 4using ProjectTemplate.Web.Authentication.Claims;
 5using ProjectTemplate.Web.Authentication.Options;
 6using ProjectTemplate.Web.Authentication.Providers.GitHub;
 7using ProjectTemplate.Web.Authentication.Providers.Google;
 8using ProjectTemplate.Web.Authentication.Providers.Microsoft;
 9using ProjectTemplate.Web.Authentication.Providers.OpenIdConnect;
 10using ProjectTemplate.Web.Authentication.Providers.Saml2;
 11
 12namespace ProjectTemplate.Web.Authentication.Extensions;
 13
 14/// <summary>
 15/// Provides extension methods for registering and applying application authentication services.
 16/// </summary>
 17public static class AuthenticationServiceExtensions
 18{
 19    /// <summary>
 20    /// The authentication cookie name used when the cookie is always sent with the <c>Secure</c> attribute.
 21    /// </summary>
 22    public const string HostPrefixedAuthenticationCookieName = "__Host-ProjectTemplate.Web.Authentication";
 23
 24    /// <summary>
 25    /// The authentication cookie name used when the Development-only insecure HTTP override is active.
 26    /// </summary>
 27    public const string AuthenticationCookieName = ".ProjectTemplate.Web.Authentication";
 28
 29    /// <summary>
 30    /// Adds application authentication services based on configuration using the secure cookie policy without an
 31    /// environment-specific plain HTTP override.
 32    /// </summary>
 33    /// <param name="services">The service collection to add authentication services to.</param>
 34    /// <param name="configuration">The application configuration source.</param>
 35    /// <returns>The same <see cref="IServiceCollection"/> instance for chaining.</returns>
 36    public static IServiceCollection AddApplicationAuthentication(
 37        this IServiceCollection services,
 38        IConfiguration configuration)
 39    {
 1440        return AddApplicationAuthentication(services, configuration, environment: null);
 41    }
 42
 43    /// <summary>
 44    /// Adds application authentication services based on configuration and the current hosting environment.
 45    /// </summary>
 46    /// <param name="services">The service collection to add authentication services to.</param>
 47    /// <param name="configuration">The application configuration source.</param>
 48    /// <param name="environment">The current hosting environment.</param>
 49    /// <returns>The same <see cref="IServiceCollection"/> instance for chaining.</returns>
 50    public static IServiceCollection AddApplicationAuthentication(
 51        this IServiceCollection services,
 52        IConfiguration configuration,
 53        IHostEnvironment? environment)
 54    {
 12955        ArgumentNullException.ThrowIfNull(services);
 12956        ArgumentNullException.ThrowIfNull(configuration);
 57
 12958        services.AddTransient<IClaimsTransformation, ApplicationClaimsTransformation>();
 12959        services.AddSingleton<IValidateOptions<ApplicationAuthenticationOptions>>(
 12960            new ApplicationAuthenticationOptionsValidator(environment));
 61
 12962        services
 12963            .AddOptions<ApplicationAuthenticationOptions>()
 12964            .Bind(configuration.GetSection(ApplicationAuthenticationOptions.SectionName))
 12965            .ValidateOnStart();
 66
 12967        AuthenticationBuilder authenticationBuilder = services.AddAuthentication(options =>
 12968        {
 12969            options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
 12970            options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
 12971            options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
 12972            options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
 12973        });
 12974        services
 12975            .AddOptions<AuthenticationOptions>()
 12976            .Configure<IOptions<ApplicationAuthenticationOptions>>((options, applicationAuthenticationOptionsAccessor) =
 12977            {
 12978                ApplicationAuthenticationOptions applicationAuthenticationOptions =
 12979                    applicationAuthenticationOptionsAccessor.Value;
 12980
 12981                if (!applicationAuthenticationOptions.Enabled)
 12982                {
 12983                    return;
 12984                }
 12985
 12986                options.DefaultScheme = applicationAuthenticationOptions.DefaultScheme;
 12987                options.DefaultAuthenticateScheme = applicationAuthenticationOptions.DefaultScheme;
 12988                options.DefaultChallengeScheme = applicationAuthenticationOptions.DefaultChallengeScheme;
 12989                options.DefaultSignInScheme = applicationAuthenticationOptions.DefaultSignInScheme;
 12990            });
 91
 12992        authenticationBuilder.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme);
 93
 12994        services
 12995            .AddOptions<CookieAuthenticationOptions>(CookieAuthenticationDefaults.AuthenticationScheme)
 12996            .Configure<IOptions<ApplicationAuthenticationOptions>>((options, applicationAuthenticationOptionsAccessor) =
 12997            {
 12998                ApplicationAuthenticationOptions applicationAuthenticationOptions =
 12999                    applicationAuthenticationOptionsAccessor.Value;
 129100
 129101                options.LoginPath = applicationAuthenticationOptions.Cookie.LoginPath;
 129102                options.LogoutPath = applicationAuthenticationOptions.Cookie.LogoutPath;
 129103                options.AccessDeniedPath = applicationAuthenticationOptions.Cookie.AccessDeniedPath;
 129104                options.ExpireTimeSpan = TimeSpan.FromMinutes(applicationAuthenticationOptions.Cookie.ExpireMinutes);
 129105                options.SlidingExpiration = applicationAuthenticationOptions.Cookie.SlidingExpiration;
 129106
 129107                options.Cookie.HttpOnly = true;
 129108                options.Cookie.SameSite = SameSiteMode.Lax;
 129109                options.Cookie.SecurePolicy = applicationAuthenticationOptions.Cookie.AllowInsecureHttp &&
 129110                    environment?.IsDevelopment() == true
 129111                        ? CookieSecurePolicy.SameAsRequest
 129112                        : CookieSecurePolicy.Always;
 129113
 129114                // Browsers accept a __Host- cookie only when it is Secure, has Path=/, and has no Domain, which binds
 129115                // the session cookie to this exact host. The prefix is used only when the cookie is always Secure, so
 129116                // the Development-only insecure HTTP override keeps working with an unprefixed name.
 129117                bool useHostPrefix = options.Cookie.SecurePolicy == CookieSecurePolicy.Always;
 129118                options.Cookie.Name = useHostPrefix
 129119                    ? HostPrefixedAuthenticationCookieName
 129120                    : AuthenticationCookieName;
 129121                if (useHostPrefix)
 129122                {
 129123                    options.Cookie.Path = "/";
 129124                }
 129125            });
 126
 129127        ApplicationAuthenticationOptions applicationAuthenticationOptions = configuration
 129128            .GetSection(ApplicationAuthenticationOptions.SectionName)
 129129            .Get<ApplicationAuthenticationOptions>() ?? new ApplicationAuthenticationOptions();
 130
 129131        authenticationBuilder
 129132            .AddOpenIdConnectAuthentication(applicationAuthenticationOptions.Providers.OpenIdConnect)
 129133            .AddSaml2Authentication(applicationAuthenticationOptions.Providers.Saml2)
 129134            .AddMicrosoftAuthentication(applicationAuthenticationOptions.Providers.Microsoft)
 129135            .AddGoogleAuthentication(applicationAuthenticationOptions.Providers.Google)
 129136            .AddGitHubAuthentication(applicationAuthenticationOptions.Providers.GitHub);
 137
 129138        return services;
 139    }
 140
 141    /// <summary>
 142    /// Applies application authentication middleware when authentication is enabled.
 143    /// </summary>
 144    /// <param name="app">The application builder.</param>
 145    /// <returns>The same <see cref="IApplicationBuilder"/> instance for chaining.</returns>
 146    public static IApplicationBuilder UseApplicationAuthentication(this IApplicationBuilder app)
 147    {
 107148        ArgumentNullException.ThrowIfNull(app);
 149
 107150        ApplicationAuthenticationOptions options = app.ApplicationServices
 107151            .GetRequiredService<IOptions<ApplicationAuthenticationOptions>>()
 107152            .Value;
 153
 100154        return !options.Enabled ? app : app.UseAuthentication();
 155    }
 156}