diff --git a/src/Tgstation.Server.Host/Security/ITokenFactory.cs b/src/Tgstation.Server.Host/Security/ITokenFactory.cs
index bf9a70fab1..0dbb4a959d 100644
--- a/src/Tgstation.Server.Host/Security/ITokenFactory.cs
+++ b/src/Tgstation.Server.Host/Security/ITokenFactory.cs
@@ -1,4 +1,6 @@
-using Microsoft.IdentityModel.Tokens;
+using System;
+
+using Microsoft.IdentityModel.Tokens;
using Tgstation.Server.Api.Models.Response;
@@ -9,6 +11,11 @@ namespace Tgstation.Server.Host.Security
///
public interface ITokenFactory
{
+ ///
+ /// Gets or sets the 's signing key.
+ ///
+ ReadOnlySpan SigningKey { get; set; }
+
///
/// The for the .
///
diff --git a/src/Tgstation.Server.Host/Security/TokenFactory.cs b/src/Tgstation.Server.Host/Security/TokenFactory.cs
index fcc5990c2f..b579c20faa 100644
--- a/src/Tgstation.Server.Host/Security/TokenFactory.cs
+++ b/src/Tgstation.Server.Host/Security/TokenFactory.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
@@ -19,7 +20,23 @@ namespace Tgstation.Server.Host.Security
sealed class TokenFactory : ITokenFactory
{
///
- public TokenValidationParameters ValidationParameters { get; }
+ public TokenValidationParameters ValidationParameters { get; private set; }
+
+ ///
+ public ReadOnlySpan SigningKey
+ {
+ get => signingKey;
+ set
+ {
+ signingKey = value.ToArray();
+ SetValidationParameters();
+ }
+ }
+
+ ///
+ /// The for the .
+ ///
+ readonly IAssemblyInformationProvider assemblyInformationProvider;
///
/// The for the .
@@ -36,11 +53,16 @@ namespace Tgstation.Server.Host.Security
///
readonly JwtSecurityTokenHandler tokenHandler;
+ ///
+ /// Backing field for .
+ ///
+ byte[] signingKey;
+
///
/// Initializes a new instance of the class.
///
/// The used for generating the .
- /// The used to generate the issuer name.
+ /// The value of .
/// The containing the value of .
public TokenFactory(
ICryptographySuite cryptographySuite,
@@ -48,32 +70,15 @@ namespace Tgstation.Server.Host.Security
IOptions securityConfigurationOptions)
{
ArgumentNullException.ThrowIfNull(cryptographySuite);
- ArgumentNullException.ThrowIfNull(assemblyInformationProvider);
+ this.assemblyInformationProvider = assemblyInformationProvider ?? throw new ArgumentNullException(nameof(assemblyInformationProvider));
securityConfiguration = securityConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(securityConfigurationOptions));
- var signingKeyBytes = String.IsNullOrWhiteSpace(securityConfiguration.CustomTokenSigningKeyBase64)
+ signingKey = String.IsNullOrWhiteSpace(securityConfiguration.CustomTokenSigningKeyBase64)
? cryptographySuite.GetSecureBytes(securityConfiguration.TokenSigningKeyByteCount)
: Convert.FromBase64String(securityConfiguration.CustomTokenSigningKeyBase64);
- ValidationParameters = new TokenValidationParameters
- {
- ValidateIssuerSigningKey = true,
- IssuerSigningKey = new SymmetricSecurityKey(signingKeyBytes),
-
- ValidateIssuer = true,
- ValidIssuer = assemblyInformationProvider.AssemblyName.Name,
-
- ValidateLifetime = true,
- ValidateAudience = true,
- ValidAudience = typeof(TokenResponse).Assembly.GetName().Name,
-
- ClockSkew = TimeSpan.FromMinutes(securityConfiguration.TokenClockSkewMinutes),
-
- RequireSignedTokens = true,
-
- RequireExpirationTime = true,
- };
+ SetValidationParameters();
tokenHeader = new JwtHeader(
new SigningCredentials(
@@ -128,5 +133,29 @@ namespace Tgstation.Server.Host.Security
return tokenResponse;
}
+
+ ///
+ /// Initializes based on fields.
+ ///
+ [MemberNotNull(nameof(ValidationParameters))]
+ void SetValidationParameters()
+ => ValidationParameters = new TokenValidationParameters
+ {
+ ValidateIssuerSigningKey = true,
+ IssuerSigningKey = new SymmetricSecurityKey(signingKey),
+
+ ValidateIssuer = true,
+ ValidIssuer = assemblyInformationProvider.AssemblyName.Name,
+
+ ValidateLifetime = true,
+ ValidateAudience = true,
+ ValidAudience = typeof(TokenResponse).Assembly.GetName().Name,
+
+ ClockSkew = TimeSpan.FromMinutes(securityConfiguration.TokenClockSkewMinutes),
+
+ RequireSignedTokens = true,
+
+ RequireExpirationTime = true,
+ };
}
}