static TokenCredential CreateClientCertificateCredential(ConfidentialClientCredentialOptions config)
        {
            if (null == config)
            {
                throw new ArgumentNullException(nameof(config));
            }
            if (null == config.TenantId)
            {
                throw new Exception("TenantId not specified.");
            }
            if (null == config.ClientId)
            {
                throw new Exception("ClientId not specified.");
            }
            if (null == config.ClientCertificate)
            {
                throw new Exception("ClientCertificate (thumbprint) not specified.");
            }

            var clientCertificate = LoadX509Certificate(config.ClientCertificate, StoreName.My, StoreLocation.CurrentUser);
            var authorityHostUri  = GetAuthorityHostUri(config.AuthorityHost);
            var options           = new TokenCredentialOptions()
            {
                AuthorityHost = authorityHostUri
            };

            return(new ClientCertificateCredential(config.TenantId, config.ClientId, clientCertificate, options));
        }
        static TokenCredential CreateClientSecretCredentials(ConfidentialClientCredentialOptions config)
        {
            if (null == config)
            {
                throw new ArgumentNullException(nameof(config));
            }
            if (null == config.TenantId)
            {
                throw new Exception("TenantId not specified.");
            }
            if (null == config.ClientId)
            {
                throw new Exception("ClientId not specified.");
            }
            if (null == config.ClientSecret)
            {
                throw new Exception("ClientSecret not specified.");
            }

            var authorityHostUri = GetAuthorityHostUri(config.AuthorityHost);
            var options          = new TokenCredentialOptions()
            {
                AuthorityHost = authorityHostUri
            };

            return(new ClientSecretCredential(config.TenantId, config.ClientId, config.ClientSecret, options));
        }
        bool IConfidentialClientCredentialProvider.IsDefined(string credentialName)
        {
            if (null == credentialName)
            {
                throw new ArgumentNullException(nameof(credentialName));
            }

            // This provider maps credentialName to configSectionName. Check if section exists.
            return(ConfidentialClientCredentialOptions.IsDefined(this.Configuration, credentialName));
        }
        static TokenCredential CreateManagedIdentityCredential(ConfidentialClientCredentialOptions config)
        {
            if (null == config)
            {
                throw new ArgumentNullException(nameof(config));
            }

            var authorityHostUri = GetAuthorityHostUri(config.AuthorityHost);
            var options          = new TokenCredentialOptions()
            {
                AuthorityHost = authorityHostUri
            };

            // ClientId can be null;
            // ClientId is required only for user-assigned-managed-identity
            return(new ManagedIdentityCredential(config.ClientId, options));
        }
        // Performance: 1,000,000 iterations Avg: 2.755 µSec
        TokenCredential IConfidentialClientCredentialProvider.GetTokenCredential(string credentialName)
        {
            if (null == credentialName)
            {
                throw new ArgumentNullException(nameof(credentialName));
            }

            // Read the configuration, which could have changed.
            // Reading config costs ~2 µSec, but helps avoid restarting app if config changes.
            // Using IOptionMonitor is an option, not warranted for this use-case.
            var config = ConfidentialClientCredentialOptions.ReadFromConfig(this.Configuration, credentialName);

            // Compose an unique cache key that represents the name and values. (Cost: ~150 nanoSec)
            var cacheKey = $"{credentialName}#{config.GetHashCode()}";

            // Create once, cache and serve.
            return(CredentialCache.GetOrAdd(cacheKey, (x) => CreateTokenCredentialOnce(config)));
        }
        static TokenCredential CreateTokenCredentialOnce(ConfidentialClientCredentialOptions config)
        {
            if (null == config)
            {
                throw new ArgumentNullException(nameof(config));
            }

            try
            {
                return
                    (config.UseManagedIdentity ? CreateManagedIdentityCredential(config) :
                     !string.IsNullOrWhiteSpace(config.ClientCertificate) ? CreateClientCertificateCredential(config) :
                     !string.IsNullOrWhiteSpace(config.ClientSecret) ? CreateClientSecretCredentials(config) :
                     throw new Exception($"Invalid config section. Expecting either 'UseManagedIdentity' or 'ClientCertificate' or 'ClientSecret'."));
            }
            catch (Exception err)
            {
                var errMsg = $"Error creating TokenCredentials using config section: '{config.Name}'";
                throw new Exception(errMsg, err);
            }
        }