/// <summary>
        /// Given a JWT, decode it and return the JSON payload.
        /// </summary>
        /// <remarks>Based on https://github.com/johnsheehan/jwt and https://github.com/NuGet/OpsDashboard/blob/master/NuGetGallery.Dashboard/Infrastructure/JWT.cs </remarks>
        /// <param name="jsonWebToken">The JWT.</param>
        /// <param name="key">The key that was used to sign the JWT.</param>
        /// <param name="verify">Whether to verify the signature (default is true).</param>
        /// <returns>A string containing the JSON payload.</returns>
        /// <exception cref="SignatureVerificationException">Thrown if the verify parameter was true and the signature was NOT valid or if the JWT was signed with an unsupported algorithm.</exception>
        private static IDTokenPayload DecodeAndVerifyIDTokenPayload(string jsonWebToken, List <RSACryptoServiceProvider> rsaCryptoProvider, bool verify)
        {
            JavaScriptSerializer jsonSerializer = new JavaScriptSerializer();

            string[] parts   = jsonWebToken.Split('.');
            string   header  = parts[0];
            string   payload = parts[1];

            byte[] crypto = ConversionUtility.Base64UrlDecode(parts[2]);

            string headerJson = Encoding.UTF8.GetString(ConversionUtility.Base64UrlDecode(header));
            Dictionary <string, object> headerData = jsonSerializer.Deserialize <Dictionary <string, object> >(headerJson);
            string algorithm   = headerData["alg"] as string;
            string payloadJson = Encoding.UTF8.GetString(ConversionUtility.Base64UrlDecode(payload));

            byte[] bytesToSign = Encoding.UTF8.GetBytes(String.Concat(header, ".", payload));

            if (!JwtHashAlgorithm.Equals(algorithm))
            {
                throw new HashAlgorithmNotSupportedException(algorithm);
            }
            if (verify && !VerifyRSAHash(bytesToSign, crypto, rsaCryptoProvider))
            {
                throw new SignatureVerificationException();
            }

            return(ConversionUtility.DeSerializerObject <IDTokenPayload>(payloadJson));
        }
        /// <summary>
        /// Converts the JWKs to a list of <see cref="RSACryptoServiceProvider"/>.
        /// The JWKs are being downloaded directly from the link provided in
        /// the OIDC Discovery Document.
        /// </summary>
        /// <returns>List of RSACryptoServiceProviders</returns>
        private static List <RSACryptoServiceProvider> GetRSACryptoServiceProvider()
        {
            JsonWebKeyIndex jsonWebKeyIndex           = WebClientUtility.GetJsonWebKeyIndex();
            List <RSACryptoServiceProvider> providers = new List <RSACryptoServiceProvider>();

            jsonWebKeyIndex.Keys.ForEach(jsonWebToken =>
            {
                RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
                provider.ImportParameters(new RSAParameters
                {
                    Exponent = ConversionUtility.Base64UrlDecode(jsonWebToken.Exponent),
                    Modulus  = ConversionUtility.Base64UrlDecode(jsonWebToken.Modulus)
                });
                providers.Add(provider);
            });

            return(providers);
        }