Example #1
0
        // 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();
        }
Example #2
0
        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);
        }
Example #4
0
        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);
        }
Example #5
0
        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);
        }
Example #6
0
        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);
        }
Example #7
0
        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);
        }
Example #9
0
        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);
        }
Example #11
0
        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)));
        }
Example #12
0
        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);
        }