< Summary

Information
Class: Elsa.Identity.Options.IdentityTokenOptions
Assembly: Elsa.Identity
File(s): /home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Identity/Options/IdentityTokenOptions.cs
Line coverage
96%
Covered lines: 32
Uncovered lines: 1
Coverable lines: 33
Total lines: 93
Line coverage: 96.9%
Branch coverage
50%
Covered branches: 3
Total branches: 6
Branch coverage: 50%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
get_SigningKey()100%11100%
get_Issuer()100%11100%
get_Audience()100%11100%
get_AccessTokenLifetime()100%11100%
get_RefreshTokenLifetime()100%11100%
get_TenantIdClaimsType()100%11100%
CreateSecurityKey()100%11100%
ConfigureJwtBearerOptions(...)100%210%
ConfigureJwtBearerOptions(...)50%22100%
ValidateLifetime(...)50%44100%

File(s)

/home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Identity/Options/IdentityTokenOptions.cs

#LineLine coverage
 1using System.IdentityModel.Tokens.Jwt;
 2using System.Text;
 3using Elsa.Identity.Constants;
 4using Microsoft.AspNetCore.Authentication.JwtBearer;
 5using Microsoft.IdentityModel.Tokens;
 6
 7namespace Elsa.Identity.Options;
 8
 9/// <summary>
 10/// Represents options about token validation and generation.
 11/// </summary>
 12public class IdentityTokenOptions
 13{
 14    /// <summary>
 15    /// The key to use when signing tokens
 16    /// </summary>
 13617    public string SigningKey { get; set; } = null!;
 18
 19    /// <summary>
 20    /// The issuer to use when creating and validating tokens
 21    /// </summary>
 6922    public string Issuer { get; set; } = "http://elsa.api";
 23
 24    /// <summary>
 25    /// The audience to use when creating and validating tokens
 26    /// </summary>
 6927    public string Audience { get; set; } = "http://elsa.api";
 28
 29    /// <summary>
 30    /// The lifetime of access tokens
 31    /// </summary>
 4832    public TimeSpan AccessTokenLifetime { get; set; } = TimeSpan.FromHours(1);
 33
 34    /// <summary>
 35    /// The lifetime of refresh tokens
 36    /// </summary>
 4837    public TimeSpan RefreshTokenLifetime { get; set; } = TimeSpan.FromHours(2);
 38
 39    /// <summary>
 40    /// Gets or sets the claim type that hold the tenant ID in the user's claims.
 41    /// If not set, <see cref="CustomClaimTypes.TenantId" /> will be used
 42    /// </summary>
 5143    public string TenantIdClaimsType { get; set; } = CustomClaimTypes.TenantId;
 44
 45    /// <summary>
 46    /// Creates a new <see cref="SecurityKey"/> from the <see cref="SigningKey"/>.
 47    /// </summary>
 48    /// <returns></returns>
 1849    public SecurityKey CreateSecurityKey() => new SymmetricSecurityKey(Encoding.ASCII.GetBytes(SigningKey));
 50
 51    /// <summary>
 52    /// Configures the <see cref="JwtBearerOptions"/> with the values from this instance.
 53    /// </summary>
 54    /// <param name="options">The options to configure.</param>
 055    public void ConfigureJwtBearerOptions(JwtBearerOptions options) => ConfigureJwtBearerOptions(options, TokenUse.Acces
 56
 57    /// <summary>
 58    /// Configures the <see cref="JwtBearerOptions"/> with the values from this instance.
 59    /// </summary>
 60    /// <param name="options">The options to configure.</param>
 61    /// <param name="requiredTokenUse">The required token usage claim value.</param>
 62    public void ConfigureJwtBearerOptions(JwtBearerOptions options, string requiredTokenUse)
 63    {
 964        options.TokenValidationParameters = new TokenValidationParameters
 965        {
 966            IssuerSigningKey = CreateSecurityKey(),
 967            ValidAudience = Audience,
 968            ValidIssuer = Issuer,
 969            ValidateLifetime = true,
 970            LifetimeValidator = ValidateLifetime,
 971            NameClaimType = JwtRegisteredClaimNames.Name
 972        };
 973        options.Events ??= new JwtBearerEvents();
 974        var previousOnTokenValidated = options.Events.OnTokenValidated;
 975        options.Events.OnTokenValidated = async context =>
 976        {
 977            await previousOnTokenValidated(context);
 978
 979            if (context.Result?.Failure != null || context.Result?.None == true)
 180                return;
 981
 882            var tokenUse = context.Principal?.FindFirst(TokenUse.ClaimType)?.Value;
 983
 884            if (!string.Equals(tokenUse, requiredTokenUse, StringComparison.Ordinal))
 685                context.Fail($"The token is not a valid {requiredTokenUse} token.");
 1886        };
 987    }
 88
 89    private static bool ValidateLifetime(DateTime? notBefore, DateTime? expires, SecurityToken securityToken, TokenValid
 90    {
 991        return expires != null && expires > DateTime.UtcNow;
 92    }
 93}