< Summary

Information
Class: ProjectTemplate.Web.Authentication.ExternalAuthenticationProviderSchemes
Assembly: ProjectTemplate.Web
File(s): /home/runner/work/NetCoreApplicationTemplate/NetCoreApplicationTemplate/src/ProjectTemplate.Web/Authentication/ExternalAuthenticationProviderSchemes.cs
Line coverage
96%
Covered lines: 27
Uncovered lines: 1
Coverable lines: 28
Total lines: 90
Line coverage: 96.4%
Branch coverage
80%
Covered branches: 8
Total branches: 10
Branch coverage: 80%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
GetSelectableSchemesAsync()100%11100%
FindSelectableSchemeAsync()83.33%6688.88%
IsSelectable(...)100%22100%
GetReservedSchemeNamesAsync()100%11100%
AddSchemeName(...)50%22100%

File(s)

/home/runner/work/NetCoreApplicationTemplate/NetCoreApplicationTemplate/src/ProjectTemplate.Web/Authentication/ExternalAuthenticationProviderSchemes.cs

#LineLine coverage
 1using Microsoft.AspNetCore.Authentication;
 2using Microsoft.AspNetCore.Authentication.Cookies;
 3
 4namespace ProjectTemplate.Web.Authentication;
 5
 6/// <summary>
 7/// Determines which registered authentication schemes a user may choose as an external sign-in provider.
 8/// </summary>
 9/// <remarks>
 10/// The login page and the external challenge endpoint use the same rule, so a scheme can be challenged through
 11/// <c>/External/Challenge</c> only when it is also offered on the login page. A scheme is selectable when it has a
 12/// non-empty display name and is not a reserved local scheme: the cookie session scheme or the default authenticate,
 13/// sign-in, or sign-out scheme. Register a display name only for schemes users are meant to choose; schemes registered
 14/// without one, such as bearer-token or test schemes, cannot be challenged through the external endpoint.
 15/// </remarks>
 16internal static class ExternalAuthenticationProviderSchemes
 17{
 18    /// <summary>
 19    /// Gets the registered schemes that users may choose as external sign-in providers.
 20    /// </summary>
 21    /// <param name="schemeProvider">The authentication scheme provider.</param>
 22    /// <returns>The selectable external provider schemes.</returns>
 23    internal static async Task<IReadOnlyList<AuthenticationScheme>> GetSelectableSchemesAsync(
 24        IAuthenticationSchemeProvider schemeProvider)
 25    {
 426        ArgumentNullException.ThrowIfNull(schemeProvider);
 27
 428        HashSet<string> reservedSchemeNames = await GetReservedSchemeNamesAsync(schemeProvider).ConfigureAwait(false);
 429        IEnumerable<AuthenticationScheme> schemes = await schemeProvider.GetAllSchemesAsync().ConfigureAwait(false);
 30
 431        return [.. schemes.Where(scheme => IsSelectable(scheme, reservedSchemeNames))];
 432    }
 33
 34    /// <summary>
 35    /// Finds a selectable external provider scheme by name.
 36    /// </summary>
 37    /// <param name="schemeProvider">The authentication scheme provider.</param>
 38    /// <param name="schemeName">The scheme name supplied by the request.</param>
 39    /// <returns>The scheme when it exists and is selectable; otherwise <see langword="null"/>.</returns>
 40    internal static async Task<AuthenticationScheme?> FindSelectableSchemeAsync(
 41        IAuthenticationSchemeProvider schemeProvider,
 42        string? schemeName)
 43    {
 644        ArgumentNullException.ThrowIfNull(schemeProvider);
 45
 646        if (string.IsNullOrWhiteSpace(schemeName))
 47        {
 048            return null;
 49        }
 50
 651        AuthenticationScheme? scheme = await schemeProvider.GetSchemeAsync(schemeName).ConfigureAwait(false);
 52
 653        if (scheme is null)
 54        {
 255            return null;
 56        }
 57
 458        HashSet<string> reservedSchemeNames = await GetReservedSchemeNamesAsync(schemeProvider).ConfigureAwait(false);
 59
 460        return IsSelectable(scheme, reservedSchemeNames) ? scheme : null;
 661    }
 62
 63    private static bool IsSelectable(AuthenticationScheme scheme, HashSet<string> reservedSchemeNames)
 64    {
 1265        return !string.IsNullOrWhiteSpace(scheme.DisplayName) &&
 1266            !reservedSchemeNames.Contains(scheme.Name);
 67    }
 68
 69    private static async Task<HashSet<string>> GetReservedSchemeNamesAsync(IAuthenticationSchemeProvider schemeProvider)
 70    {
 871        HashSet<string> reservedSchemeNames = new(StringComparer.Ordinal)
 872        {
 873            CookieAuthenticationDefaults.AuthenticationScheme
 874        };
 75
 876        AddSchemeName(reservedSchemeNames, await schemeProvider.GetDefaultAuthenticateSchemeAsync().ConfigureAwait(false
 877        AddSchemeName(reservedSchemeNames, await schemeProvider.GetDefaultSignInSchemeAsync().ConfigureAwait(false));
 878        AddSchemeName(reservedSchemeNames, await schemeProvider.GetDefaultSignOutSchemeAsync().ConfigureAwait(false));
 79
 880        return reservedSchemeNames;
 881    }
 82
 83    private static void AddSchemeName(HashSet<string> schemeNames, AuthenticationScheme? scheme)
 84    {
 2485        if (scheme is not null)
 86        {
 2487            _ = schemeNames.Add(scheme.Name);
 88        }
 2489    }
 90}