// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { // *** CHANGE THIS FOR PRODUCTION USE *** // Here, we're generating a random key to sign tokens - obviously this means // that each time the app is started the key will change, and multiple servers // all have different keys. This should be changed to load a key from a file // securely delivered to your application, controlled by configuration. // // See the RSAKeyUtils.GetKeyParameters method for an examle of loading from // a JSON file. RSAParameters keyParams = RsaKeyService.GetRandomKey(); // Create the key, and a set of token options to record signing credentials // using that key, along with the other parameters we will need in the // token controlller. key = new Microsoft.IdentityModel.Tokens.RsaSecurityKey(keyParams); tokenOptions = new TokenOptionsModel() { Audience = TokenAudience, Issuer = TokenIssuer, SigningCredentials = new Microsoft.IdentityModel.Tokens.SigningCredentials(key, Microsoft.IdentityModel.Tokens.SecurityAlgorithms.RsaSha256Signature) }; // Save the token options into an instance so they're accessible to the // controller. services.AddSingleton <TokenOptionsModel>(tokenOptions); // Enable the use of an [Authorize("Bearer")] attribute on methods and classes to protect. services.AddAuthorization(auth => { // inline policies //https://leastprivilege.com/2015/10/12/the-state-of-security-in-asp-net-5-and-mvc-6-authorization/ auth.AddPolicy("Admin", new AuthorizationPolicyBuilder() .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme) .RequireAuthenticatedUser().RequireClaim("Admin").Build()); // inline policies //https://leastprivilege.com/2015/10/12/the-state-of-security-in-asp-net-5-and-mvc-6-authorization/ auth.AddPolicy("Manager", new AuthorizationPolicyBuilder() .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme) .RequireAuthenticatedUser().RequireClaim("Manager").Build()); //https://github.com/mrsheepuk/ASPNETSelfCreatedTokenAuthExample auth.DefaultPolicy = new AuthorizationPolicyBuilder() .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme) .RequireAuthenticatedUser().Build(); }); // CORS works but hosting can make things confusing // http://stackoverflow.com/questions/34212765/how-do-i-get-the-kestrel-web-server-to-listen-to-non-localhost-requests services.AddCors(o => o.AddPolicy("AnyOrigin", builder => { builder.AllowAnyOrigin() .AllowAnyMethod() .AllowAnyHeader(); })); // Add framework services. services.AddMvc(); }
static string GenerateJWT(RSA rsa) { //var securityKey = new Microsoft.IdentityModel.Tokens.X509SecurityKey(GetByThumbprint("YOUR-CERT-THUMBPRINT-HERE")); //var securityKey = new Microsoft.IdentityModel.Tokens.X509SecurityKey(new X509Certificate2(Convert.FromBase64String("MIIDBTCCAe2gAwIBAgIQbiJkXaenk61AKixVocnLRTANBgkqhkiG9w0BAQsFADAtMSswKQYDVQQDEyJhY2NvdW50cy5hY2Nlc3Njb250cm9sLndpbmRvd3MubmV0MB4XDTE5MTAwNTAwMDAwMFoXDTI0MTAwNDAwMDAwMFowLTErMCkGA1UEAxMiYWNjb3VudHMuYWNjZXNzY29udHJvbC53aW5kb3dzLm5ldDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJ2H9Y6Z+3BXUCtlbmXr6H5owYy15XTl3vdpOZLUkk4OV9LMsB1phjNp+wgl28eAgrNNfu4BTVlHdR9x6NTrSiIapsYjzzEz4mOmRh1Bw5tJxit0VEGn00/ZENniTjgeEFYgDHYwjrfZQ6dERBFiw1OQb2IG5f3KLtx92lUXeIZ7ZvTaPkUpc4Qd6wQZmWgzPqWFocRsJATGyZzXiiXQUrc9cVqm1bws3P0lFBcqNtv+AKDYKT5IRYLsyCkueQC9R6LUCsZVD7bVIkeQuA3iehJKIEAlk/e3j5E4VaCRs642ajb/z9kByTl2xL2k0AeZGc8/Rcy7SQn0LBcJNZGp/SMCAwEAAaMhMB8wHQYDVR0OBBYEFOLhl3BDPLNVYDe38Dp9JbUmd4kKMA0GCSqGSIb3DQEBCwUAA4IBAQAN4XwyqYfVdMl0xEbBMa/OzSfIbuI4pQWWpl3isKRAyhXezAX1t/0532LsIcYkwubLifnjHHqo4x1jnVqkvkFjcPZ12kjs/q5d1L0LxlQST/Uqwm/9/AeTzRZXtUKNBWBOWy9gmw9DEH593sNYytGAEerbWhCR3agUxsnQSYTTwg4K9cSqLWzHX5Kcz0NLCGwLx015/Jc7HwPJnp7q5Bo0O0VfhomDiEctIFfzqE5x9T9ZTUSWUDn3J7DYzs2L1pDrOQaNs/YEkXsKDP1j4tOFyxic6OvjQ10Yugjo5jg1uWoxeU8pI0BxY6sj2GZt3Ynzev2bZqmj68y0I9Z+NTZo"))); var securityKey = new Microsoft.IdentityModel.Tokens.RsaSecurityKey(rsa); var mod = rsa.ExportParameters(includePrivateParameters: false).Modulus; // The "key ID" used for RSA key in GPG/PGP is the last 8 hex digits (4 bytes) of the modulus of the key. securityKey.KeyId = Base64UrlEncode(mod, mod.Length - 4, 4); var credentials = new Microsoft.IdentityModel.Tokens.SigningCredentials(securityKey, "RS256"); var header = new JwtHeader(credentials); var payload = new JwtPayload { { "aud", "https://management.core.windows.net/" }, { "iss", "https://sts.windows.net/72f988bf-86f1-41af-91ab-2d7cd011db47/" }, { "exp", (Int32)(new DateTime(2019, 12, 9, 0, 0, 0, DateTimeKind.Utc).Subtract(new DateTime(1970, 1, 1))).TotalSeconds }, { "iat", (Int32)(new DateTime(2019, 12, 7, 0, 0, 0, DateTimeKind.Utc).Subtract(new DateTime(1970, 1, 1))).TotalSeconds } }; var token = new JwtSecurityToken(header, payload); var input = string.Join(".", new[] { token.EncodedHeader, token.EncodedPayload }); var signature = SignRS256(input, rsa); return(string.Join(".", new[] { input, Base64UrlEncoder.Encode(signature) })); }
/// <summary> /// Converts a ITfoxtec JWK to a SecurityKey. /// </summary> public static MSTokens.SecurityKey ToSecurityKey(this JsonWebKey jwk) { var key = new MSTokens.RsaSecurityKey(jwk.ToRsaParameters(true)); key.KeyId = jwk.Kid; return(key); }
public JwtSecurityToken ReadJWTRSA(string serializedJWT, string publicRSAKeyContents, string algorithm, TokenValidationParameters validationParameters) { var securityHandler = new JwtSecurityTokenHandler(); var rsa = RSA.Create(); Nullable <RSAParameters> rsaParameters = new PEMCryptoService().GetRSAProviderFromRSAKeyContents(publicRSAKeyContents); if (rsaParameters != null) { rsa.ImportParameters(rsaParameters.Value); var securityKey = new Microsoft.IdentityModel.Tokens.RsaSecurityKey(rsaParameters.Value); var credentials = new Microsoft.IdentityModel.Tokens.SigningCredentials(securityKey, algorithm); validationParameters.IssuerSigningKey = credentials.Key; SecurityToken validatedToken; try { securityHandler.ValidateToken(serializedJWT, validationParameters, out validatedToken); if (validatedToken == null) { throw new Exception("Validation of signature failed! Don't trust these data!"); } return(securityHandler.ReadJwtToken(serializedJWT)); } catch (SecurityTokenInvalidSignatureException) { throw new Exception("Validation of signature failed! Don't trust these data!"); } } return(null); }
private JwtSecurityToken BuildDeepLinkPostbackToken(JwtSecurityToken requestToken, out string returnUrl) { Claim linkSettings = requestToken.Claims.Single(x => x.Type == LtiClaims.DeepLinkingSettings); JObject settingValues = JObject.Parse(linkSettings.Value); returnUrl = (string)settingValues["deep_link_return_url"]; string data = (string)settingValues["data"]; // first - read tool's private key RSAParameters rsaParams; using (var tr = new StringReader(this.config.ToolPrivateKey)) { var pemReader = new PemReader(tr); var keyPair = pemReader.ReadObject() as AsymmetricCipherKeyPair; if (keyPair == null) { throw new Exception("Could not read RSA private key"); } var privateRsaParams = keyPair.Private as RsaPrivateCrtKeyParameters; rsaParams = DotNetUtilities.ToRSAParameters(privateRsaParams); } // create security key using private key above var securityKey = new Microsoft.IdentityModel.Tokens.RsaSecurityKey(rsaParams); // note that securityKey length should be >256b so you have to make sure that your private key has a proper length var signingCredentials = new Microsoft.IdentityModel.Tokens.SigningCredentials(securityKey, Microsoft.IdentityModel.Tokens.SecurityAlgorithms.RsaSha256); // create a Token var clientAsssertionJwtTokenHeader = new JwtHeader(signingCredentials); // Some PayLoad that contain information about the caller (tool) // expected payload for access token request.. confirm with IMS guys var now = DateTime.UtcNow; var clientAsssertionJwtTokenPayload = new JwtPayload { { "iss", this.config.ClientId }, //{ "aud", this.config.PlatformTokenEndpoint }, { "aud", requestToken.Issuer }, { "exp", now.AddMinutes(5).Ticks }, // give the user 5 minutes to post the deep link? { "iat", now.Ticks }, { "jti", $"{this.config.ClientId}-{now.Ticks}" }, { "nonce", "377fdbf8cbc2f7b0799b" } }; Claim[] deepLinkResponseClaims = this.BuildResponseClaims(data); clientAsssertionJwtTokenPayload.AddClaims(deepLinkResponseClaims); var clientAsssertionJwtToken = new JwtSecurityToken(clientAsssertionJwtTokenHeader, clientAsssertionJwtTokenPayload); return(clientAsssertionJwtToken); }
public static string JwtToken(this System.Security.Cryptography.RSACryptoServiceProvider rsaProvider, string issuer, Uri scope, IEnumerable <Claim> claims, DateTime issued, TimeSpan duration) { var securityKey = new Microsoft.IdentityModel.Tokens.RsaSecurityKey(rsaProvider); var signature = new Microsoft.IdentityModel.Tokens.SigningCredentials( securityKey, Microsoft.IdentityModel.Tokens.SecurityAlgorithms.RsaSha256Signature); var expires = (issued + duration); var token = new JwtSecurityToken(issuer, scope.AbsoluteUri, claims, issued, expires, signature); var handler = new JwtSecurityTokenHandler(); var jwt = handler.WriteToken(token); return(jwt); }
public JwtSecurityToken GenerateJWTFromRSA(JwtPayload payload, string privateRSAKeyContents, string algorithm) { var rsa = RSA.Create(); Nullable <RSAParameters> rsaParameters = new PEMCryptoService().GetRSAProviderFromRSAKeyContents(privateRSAKeyContents); if (rsaParameters != null) { rsa.ImportParameters(rsaParameters.Value); var securityKey = new Microsoft.IdentityModel.Tokens.RsaSecurityKey(rsaParameters.Value); var credentials = new Microsoft.IdentityModel.Tokens.SigningCredentials(securityKey, algorithm); var JWTHeader = new JwtHeader(credentials); var token = new JwtSecurityToken(JWTHeader, payload); return(token); } return(null); }
/// <summary> /// Convert RSA security key into json web key. /// </summary> /// <param name="key">RSA security key</param> /// <returns>json web key</returns> public static JsonWebKey ConvertFromRSASecurityKey(RsaSecurityKey key) { var jsonWebKey = new JsonWebKey(); var parameters = new RSAParameters(); jsonWebKey.Kty = JsonWebAlgorithmsKeyTypes.RSA; jsonWebKey.Kid = key.KeyId; // get Parameters if (key.Rsa != null) { parameters = key.Rsa.ExportParameters(true); } else { parameters = key.Parameters; } jsonWebKey.N = parameters.Modulus != null?Base64UrlEncoder.Encode(parameters.Modulus) : null; jsonWebKey.E = parameters.Exponent != null?Base64UrlEncoder.Encode(parameters.Exponent) : null; jsonWebKey.D = parameters.D != null?Base64UrlEncoder.Encode(parameters.D) : null; jsonWebKey.P = parameters.P != null?Base64UrlEncoder.Encode(parameters.P) : null; jsonWebKey.Q = parameters.Q != null?Base64UrlEncoder.Encode(parameters.Q) : null; jsonWebKey.DP = parameters.DP != null?Base64UrlEncoder.Encode(parameters.DP) : null; jsonWebKey.DQ = parameters.DQ != null?Base64UrlEncoder.Encode(parameters.DQ) : null; jsonWebKey.QI = parameters.InverseQ != null?Base64UrlEncoder.Encode(parameters.InverseQ) : null; return(jsonWebKey); }
public static string JwtToken(this System.Security.Cryptography.RSACryptoServiceProvider rsaProvider, string issuer, Uri scope, IEnumerable <Claim> claims, DateTime issued, TimeSpan duration, string algorithm, IEnumerable <KeyValuePair <string, string> > tokenHeaders = default) { var securityKey = new Microsoft.IdentityModel.Tokens.RsaSecurityKey(rsaProvider); var signature = new Microsoft.IdentityModel.Tokens.SigningCredentials( securityKey, algorithm); var expires = (issued + duration); var token = new JwtSecurityToken(issuer, scope.AbsoluteUri, claims, issued, expires, signature); foreach (var kvp in tokenHeaders.NullToEmpty()) { token.Header.Add(kvp.Key, kvp.Value); } var handler = new JwtSecurityTokenHandler(); var jwt = handler.WriteToken(token); return(jwt); }
/// <summary> /// Returns the JsonWebKeys as a <see cref="IList{SecurityKey}"/>. /// </summary> public IList <SecurityKey> GetSigningKeys() { List <SecurityKey> keys = new List <SecurityKey>(); for (int i = 0; i < Keys.Count; i++) { JsonWebKey webKey = Keys[i]; if (!StringComparer.Ordinal.Equals(webKey.Kty, JsonWebAlgorithmsKeyTypes.RSA)) { continue; } if ((string.IsNullOrWhiteSpace(webKey.Use) || (StringComparer.Ordinal.Equals(webKey.Use, JsonWebKeyUseNames.Sig)))) { if (webKey.X5c != null) { foreach (var certString in webKey.X5c) { try { // Add chaining SecurityKey key = new X509SecurityKey(new X509Certificate2(Convert.FromBase64String(certString))); key.KeyId = webKey.Kid; keys.Add(key); } catch (CryptographicException ex) { throw LogHelper.LogExceptionMessage(new InvalidOperationException(LogHelper.FormatInvariant(LogMessages.IDX10802, webKey.X5c[0]), ex)); } catch (FormatException fex) { throw LogHelper.LogExceptionMessage(new InvalidOperationException(LogHelper.FormatInvariant(LogMessages.IDX10802, webKey.X5c[0]), fex)); } } } if (!string.IsNullOrWhiteSpace(webKey.E) && !string.IsNullOrWhiteSpace(webKey.N)) { try { SecurityKey key = new RsaSecurityKey ( new RSAParameters { Exponent = Base64UrlEncoder.DecodeBytes(webKey.E), Modulus = Base64UrlEncoder.DecodeBytes(webKey.N), } ); key.KeyId = webKey.Kid; keys.Add(key); } catch (CryptographicException ex) { throw LogHelper.LogExceptionMessage(new InvalidOperationException(LogHelper.FormatInvariant(LogMessages.IDX10801, webKey.E, webKey.N), ex)); } catch (FormatException ex) { throw LogHelper.LogExceptionMessage(new InvalidOperationException(LogHelper.FormatInvariant(LogMessages.IDX10801, webKey.E, webKey.N), ex)); } } } } return(keys); }
private void ResolveAsymmetricAlgorithm(SecurityKey key, string algorithm, bool willCreateSignatures) { if (key == null) { throw LogHelper.LogArgumentNullException("key"); } if (string.IsNullOrWhiteSpace(algorithm)) { throw LogHelper.LogArgumentNullException("algorithm"); } _hashAlgorithm = GetHashAlgorithmString(algorithm); RsaSecurityKey rsaKey = key as RsaSecurityKey; if (rsaKey != null) { if (rsaKey.Rsa != null) { _rsaCryptoServiceProvider = rsaKey.Rsa as RSACryptoServiceProvider; } if (_rsaCryptoServiceProvider == null) { _rsaCryptoServiceProvider = new RSACryptoServiceProvider(); (_rsaCryptoServiceProvider as RSA).ImportParameters(rsaKey.Parameters); _disposeRsa = true; } return; } X509SecurityKey x509Key = key as X509SecurityKey; if (x509Key != null) { if (willCreateSignatures) { _rsaCryptoServiceProviderProxy = new RSACryptoServiceProviderProxy(x509Key.PrivateKey as RSACryptoServiceProvider); } else { _rsaCryptoServiceProviderProxy = new RSACryptoServiceProviderProxy(x509Key.PublicKey as RSACryptoServiceProvider); } return; } ECDsaSecurityKey ecdsaKey = key as ECDsaSecurityKey; if (ecdsaKey != null) { if (ecdsaKey.ECDsa != null) { _ecdsa = ecdsaKey.ECDsa as ECDsaCng; _ecdsa.HashAlgorithm = new CngAlgorithm(_hashAlgorithm); return; } } JsonWebKey webKey = key as JsonWebKey; if (webKey.Kty == JsonWebAlgorithmsKeyTypes.RSA) { RSAParameters parameters = CreateRsaParametersFromJsonWebKey(webKey, willCreateSignatures); _rsaCryptoServiceProvider = new RSACryptoServiceProvider(); (_rsaCryptoServiceProvider as RSA).ImportParameters(parameters); return; } else if (webKey.Kty == JsonWebAlgorithmsKeyTypes.EllipticCurve) { CreateECDsaFromJsonWebKey(webKey, willCreateSignatures); return; } throw LogHelper.LogExceptionMessage(new ArgumentOutOfRangeException(nameof(key), String.Format(CultureInfo.InvariantCulture, LogMessages.IDX10641, key))); }
public void ValidateJsonWebToken(string tokenString, SsoSettings settings, IList <string> audiences) { try { TokenString = tokenString; SecurityKey securityKey; IssuerSigningKeyResolver issuerSigningKeyResolver; log.DebugFormat("Jwt Validation securityAlgorithm={0}, audience[0]={1}, audience[1]={2}", settings.ValidationType, audiences[0], audiences[1]); switch (settings.ValidationType) { case ValidationTypes.RSA_SHA256: RSACryptoServiceProvider publicOnly = new RSACryptoServiceProvider(); //"<RSAKeyValue><Modulus>zeyPa4SwRb0IO+KMq20760ZmaUvy/qzecdOkRUNdNpdUe1E72Xt1WkAcWNu24/UeS3pETu08rVTqHJUMfhHcSKgL7LAk/MMj2inGFxop1LipGZSnqZhnjsfj1ERJL5eXs1O9hqyAcXvY4A2wo67qqv/lbHLKTW59W+YQkbIOVR4nQlbh1lK1TIY+oqK0J/5Ileb4QfERn0Rv/J/K0fy6VzLmVt+kg9MRNxYwnVsC3m5/kIu1fw3OpZxcaCC68SRqLLb/UXmaJM8NXYKkAkHKxT4DQqSk6KbFSQG6qi49Q34akohekzxjxmmGeoO5tsFCuMJofKAsBKKtOkLPaJD2rQ==</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>" publicOnly.FromXmlString(settings.PublicKey); securityKey = new Microsoft.IdentityModel.Tokens.RsaSecurityKey(publicOnly); issuerSigningKeyResolver = (token, securityToken, kid, validationParameters) => new List <Microsoft.IdentityModel.Tokens.RsaSecurityKey> { new Microsoft.IdentityModel.Tokens.RsaSecurityKey(publicOnly) }; break; case ValidationTypes.HMAC_SHA256: //var key = "zeyPa4SwRb0IO+KMq20760ZmaUvy/qzecdOkRUNdNpdUe1E72Xu24/UeS3pETu"; securityKey = new Microsoft.IdentityModel.Tokens.SymmetricSecurityKey(GetBytes(settings.PublicKey)); issuerSigningKeyResolver = (token, securityToken, kid, validationParameters) => new List <Microsoft.IdentityModel.Tokens.SymmetricSecurityKey> { new Microsoft.IdentityModel.Tokens.SymmetricSecurityKey(GetBytes(settings.PublicKey)) }; break; case ValidationTypes.X509: var certificate = new Certificate(); certificate.LoadCertificate(settings.PublicKey); securityKey = new X509SecurityKey(certificate.Cert); issuerSigningKeyResolver = (token, securityToken, kid, validationParameters) => new List <X509SecurityKey> { new X509SecurityKey(certificate.Cert) }; break; default: log.ErrorFormat("ValidationType has wrong value: {0}", settings.ValidationType); throw new ArgumentException("ValidationType has wrong value"); } TokenValidationParameters validationParams = new TokenValidationParameters { ValidIssuer = settings.Issuer, ValidAudiences = audiences, ValidateIssuer = true, ValidateIssuerSigningKey = true, ValidateAudience = true, ValidateActor = true, IssuerSigningKey = securityKey, IssuerSigningKeyResolver = issuerSigningKeyResolver }; JwtSecurityTokenHandler recipientTokenHandler = new JwtSecurityTokenHandler { TokenLifetimeInMinutes = MaxClockSkew }; SecurityToken validatedToken; ClaimsPrincipalReceived = recipientTokenHandler.ValidateToken(TokenString, validationParams, out validatedToken); JwtSecurityToken = validatedToken; } catch (Exception e) { log.ErrorFormat("Jwt Validation error. {0}", e); } }
/// <summary> /// Add Signing credential by file /// </summary> /// <param name="builder">IIdentityServerBuilder</param> /// <param name="appSettings">AppSettings</param> /// <returns>IIdentityServerBuilder</returns> public static IIdentityServerBuilder AddSigningCredentialsByFile( this IIdentityServerBuilder builder, AppSettings appSettings) { // Variables const int DEFAULT_EXPIRY_YEAR = 1; const string DIR_NAME_KEYS = "Keys"; const string FILE_NAME_WORKING_SC = "SigningCredential.rsa"; const string FILE_NAME_DEPRECATED_SC = "DeprecatedSigningCredentials.rsa"; var rootDir = Path.Combine(AppContext.BaseDirectory, DIR_NAME_KEYS); var workingScDir = Path.Combine(rootDir, FILE_NAME_WORKING_SC); var deprecatedScDir = Path.Combine(rootDir, FILE_NAME_DEPRECATED_SC); var utcNow = DateTimeOffset.UtcNow; // RSA key object Microsoft.IdentityModel.Tokens.RsaSecurityKey key = null; // The Key for Idsrv // Signing credetial object SigningCredential credential = null; // The Signing credential stored in file List <SigningCredential> deprecatedCredentials = null; // The Deprecated Signing credentials stored in file #region Add exist or new Signing Credentials var strWorkingSc = FileUtils.ReadFileAsync(workingScDir).Result; var strDeprecatedScs = FileUtils.ReadFileAsync(deprecatedScDir).Result; if (!string.IsNullOrEmpty(strWorkingSc)) { // Use the RSA key pair stored in file credential = JsonConvert.DeserializeObject <SigningCredential>(strWorkingSc); key = CryptoHelper.CreateRsaSecurityKey(credential.Parameters, credential.KeyId); // Warning if key expires if (credential.ExpireOn < utcNow) { logger.Warn($"Auth Server's Signing Credential (ID: {credential.KeyId}) is expired at {credential.ExpireOn.ToLocalTime()}!"); } } else { // Create new RSA key pair 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 fiile FileUtils.SaveFileAsync(workingScDir, JsonConvert.SerializeObject(credential)).Wait(); } // Add the key as the Signing credential for Idsrv builder.AddSigningCredential(key, IdentityServerConstants.RsaSigningAlgorithm.RS256); #endregion #region Add Deprecated Signing Credentials for clients' old tokens deprecatedCredentials = string.IsNullOrEmpty(strDeprecatedScs) ? new List <SigningCredential>() : JsonConvert.DeserializeObject <List <SigningCredential> >(strDeprecatedScs); 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()); #endregion return(builder); }
/// <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); }
private void ResolveAsymmetricAlgorithm(SecurityKey key, string algorithm, bool willCreateSignatures) { if (key == null) { throw LogHelper.LogArgumentNullException("key"); } if (string.IsNullOrWhiteSpace(algorithm)) { throw LogHelper.LogArgumentNullException("algorithm"); } _hashAlgorithm = GetHashAlgorithmName(algorithm); RsaSecurityKey rsaKey = key as RsaSecurityKey; if (rsaKey != null) { if (rsaKey.Rsa != null) { _rsa = rsaKey.Rsa; return; } _rsa = RSA.Create(); if (_rsa != null) { _rsa.ImportParameters(rsaKey.Parameters); _disposeRsa = true; return; } } X509SecurityKey x509Key = key as X509SecurityKey; if (x509Key != null) { if (willCreateSignatures) { RSACryptoServiceProvider rsaCsp = x509Key.PrivateKey as RSACryptoServiceProvider; if (rsaCsp != null) { _rsaCryptoServiceProviderProxy = new RSACryptoServiceProviderProxy(rsaCsp); } else { _rsa = x509Key.PrivateKey as RSA; } } else { _rsa = x509Key.PublicKey as RSA; } return; } ECDsaSecurityKey ecdsaKey = key as ECDsaSecurityKey; if (ecdsaKey != null) { if (ecdsaKey.ECDsa != null) { _ecdsa = ecdsaKey.ECDsa; return; } } JsonWebKey webKey = key as JsonWebKey; if (webKey.Kty == JsonWebAlgorithmsKeyTypes.RSA) { RSAParameters parameters = CreateRsaParametersFromJsonWebKey(webKey, willCreateSignatures); _rsa = RSA.Create(); if (_rsa != null) { _rsa.ImportParameters(parameters); _disposeRsa = true; return; } } else if (webKey.Kty == JsonWebAlgorithmsKeyTypes.EllipticCurve) { if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { throw new PlatformNotSupportedException(); } CreateECDsaFromJsonWebKey(webKey, willCreateSignatures); return; } throw LogHelper.LogArgumentException <ArgumentOutOfRangeException>(nameof(key), LogMessages.IDX10641, key); }