/// <summary> /// Add Signing credential by Redis /// </summary> /// <param name="builder">IIdentityServerBuilder</param> /// <param name="appSettings">AppSettings</param> /// <returns>IIdentityServerBuilder</returns> public static IIdentityServerBuilder AddSigningCredentialByRedis( this IIdentityServerBuilder builder, AppSettings appSettings) { // Variables const int DEFAULT_EXPIRY_YEAR = 1; var utcNow = DateTimeOffset.UtcNow; var redisKeyWorkingSk = CacheKeyFactory.SigningCredential(); var redisKeyDeprecatedSk = CacheKeyFactory.SigningCredential(isDeprecated: true); // RSA key object Microsoft.IdentityModel.Tokens.RsaSecurityKey key = null; // The Key for Idsrv // Signing credetial object from Redis SigningCredential credential = null; // The Signing credential stored in Redis List <SigningCredential> deprecatedCredentials = null; // The Deprecated Signing credentials stored in Redis using (ICacheService redis = new RedisService(appSettings)) { bool isSigningCredentialExists = redis.GetCache(redisKeyWorkingSk, out credential); if (isSigningCredentialExists && credential.ExpireOn >= utcNow) { // Use the RSA key pair stored in redis key = CryptoHelper.CreateRsaSecurityKey(credential.Parameters, credential.KeyId); } else if (isSigningCredentialExists && credential.ExpireOn < utcNow) { #region Move the expired Signing credential to Redis's Decprecated-Signing-Credential key _ = redis.GetCache(redisKeyDeprecatedSk, out deprecatedCredentials); if (deprecatedCredentials == null) { deprecatedCredentials = new List <SigningCredential>(); } deprecatedCredentials.Add(credential); redis.SaveCache(redisKeyDeprecatedSk, deprecatedCredentials); #endregion #region Clear the expired Signing credential from Redis's Signing-Credential key redis.ClearCache(redisKeyWorkingSk); #endregion // Set flag as False isSigningCredentialExists = false; } #region If no available Signing credial, create a new one if (!isSigningCredentialExists) { key = CryptoHelper.CreateRsaSecurityKey(); RSAParameters parameters = key.Rsa == null ? parameters = key.Parameters : key.Rsa.ExportParameters(includePrivateParameters: true); var expireOn = appSettings.Global?.SigningCredential?.DefaultExpiry == null? utcNow.AddYears(DEFAULT_EXPIRY_YEAR) : appSettings.Global.SigningCredential.DefaultExpiry.GetExpireOn(); credential = new SigningCredential { Parameters = parameters, KeyId = key.KeyId, ExpireOn = expireOn }; // Save to Redis redis.SaveCache(redisKeyWorkingSk, credential); } #endregion // Add the key as the Signing credential for Idsrv builder.AddSigningCredential(key, IdentityServerConstants.RsaSigningAlgorithm.RS256); // Also add the expired key for clients' old tokens if (redis.GetCache(redisKeyDeprecatedSk, out deprecatedCredentials)) { IList <SecurityKeyInfo> deprecatedKeyInfos = new List <SecurityKeyInfo>(); deprecatedCredentials.ForEach(dc => { var deprecatedKeyInfo = new SecurityKeyInfo { Key = CryptoHelper.CreateRsaSecurityKey(dc.Parameters, dc.KeyId), SigningAlgorithm = SecurityAlgorithms.RsaSha256 }; deprecatedKeyInfos.Add(deprecatedKeyInfo); // builder.AddValidationKey(deprecatedKey, IdentityServerConstants.RsaSigningAlgorithm.RS256)); }); builder.AddValidationKey(deprecatedKeyInfos.ToArray()); } } return(builder); }