< Summary

Information
Class: Elsa.Extensions.ValidateIdentityTokenOptions
Assembly: Elsa.Identity
File(s): /home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Identity/OptionConfigurators/ValidateIdentityTokenOptions.cs
Line coverage
100%
Covered lines: 26
Uncovered lines: 0
Coverable lines: 26
Total lines: 73
Line coverage: 100%
Branch coverage
94%
Covered branches: 17
Total branches: 18
Branch coverage: 94.4%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.cctor()100%11100%
.ctor()100%11100%
.ctor(...)100%11100%
Validate(...)100%1212100%
IsDemoOrDevelopment()100%44100%
IsPrintableAscii(...)50%22100%

File(s)

/home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Identity/OptionConfigurators/ValidateIdentityTokenOptions.cs

#LineLine coverage
 1using Elsa.Identity.Options;
 2using Microsoft.Extensions.Hosting;
 3using Microsoft.Extensions.Options;
 4
 5// ReSharper disable once CheckNamespace
 6namespace Elsa.Extensions;
 7
 8/// <summary>
 9/// Validates the <see cref="IdentityTokenOptions"/>.
 10/// </summary>
 11public class ValidateIdentityTokenOptions : IValidateOptions<IdentityTokenOptions>
 12{
 13    private const int MinimumSigningKeyByteLength = 32;
 14    private const string DemoEnvironmentName = "Demo";
 15
 216    private static readonly HashSet<string> KnownDefaultSigningKeys = new(StringComparer.OrdinalIgnoreCase)
 217    {
 218        "sufficiently-large-secret-signing-key",
 219        "CHANGE_ME_TO_A_SECURE_RANDOM_KEY"
 220    };
 21
 22    private readonly IHostEnvironment? _environment;
 23
 24    /// <summary>
 25    /// Initializes a new instance of the <see cref="ValidateIdentityTokenOptions"/> class.
 26    /// </summary>
 1727    public ValidateIdentityTokenOptions()
 28    {
 1729    }
 30
 31    /// <summary>
 32    /// Initializes a new instance of the <see cref="ValidateIdentityTokenOptions"/> class.
 33    /// </summary>
 934    public ValidateIdentityTokenOptions(IHostEnvironment environment)
 35    {
 936        _environment = environment;
 937    }
 38
 39    /// <inheritdoc />
 40    public ValidateOptionsResult Validate(string? name, IdentityTokenOptions options)
 41    {
 2642        if (string.IsNullOrWhiteSpace(options.SigningKey))
 443            return ValidateOptionsResult.Fail("SigningKey is required. Configure a secure random JWT signing key through
 44
 2245        var signingKey = options.SigningKey.Trim();
 46
 2247        if (!string.Equals(signingKey, options.SigningKey, StringComparison.Ordinal))
 448            return ValidateOptionsResult.Fail("SigningKey must not contain leading or trailing whitespace. Configure the
 49
 1850        if (KnownDefaultSigningKeys.Contains(signingKey))
 51        {
 1052            if (!IsDemoOrDevelopment())
 853                return ValidateOptionsResult.Fail("SigningKey uses a known public default value. Replace it with a secur
 54
 255            return ValidateOptionsResult.Success;
 56        }
 57
 858        if (!IsPrintableAscii(signingKey))
 259            return ValidateOptionsResult.Fail("SigningKey contains non-printable or non-ASCII characters. Configure a se
 60
 661        if (signingKey.Length < MinimumSigningKeyByteLength)
 262            return ValidateOptionsResult.Fail($"SigningKey must be at least {MinimumSigningKeyByteLength} ASCII characte
 63
 464        return ValidateOptionsResult.Success;
 65    }
 66
 67    private bool IsDemoOrDevelopment()
 68    {
 1069        return _environment is not null && (_environment.IsDevelopment() || string.Equals(_environment.EnvironmentName, 
 70    }
 71
 26872    private static bool IsPrintableAscii(string value) => value.All(x => x is >= ' ' and <= '~');
 73}