public async Task TestOidcAuth()
        {
            var clientId         = "CLIENT_ID";
            var clientSecret     = "CLIENT_SECRET";
            var idpIssuerUrl     = "https://idp.issuer.url";
            var unexpiredIdToken = "eyJhbGciOiJIUzI1NiJ9.eyJpYXQiOjAsImV4cCI6MjAwMDAwMDAwMH0.8Ata5uKlrqYfeIaMwS91xVgVFHu7ntHx1sGN95i2Zho";
            var expiredIdToken   = "eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjB9.f37LFpIw_XIS5TZt3wdtEjjyCNshYy03lOWpyDViRM0";
            var refreshToken     = "REFRESH_TOKEN";

            // use unexpired id token as bearer, do not attempt to refresh
            var auth   = new OidcTokenProvider(clientId, clientSecret, idpIssuerUrl, unexpiredIdToken, refreshToken);
            var result = await auth.GetAuthenticationHeaderAsync(CancellationToken.None).ConfigureAwait(false);

            result.Scheme.Should().Be("Bearer");
            result.Parameter.Should().Be(unexpiredIdToken);

            try
            {
                // attempt to refresh id token when expired
                auth   = new OidcTokenProvider(clientId, clientSecret, idpIssuerUrl, expiredIdToken, refreshToken);
                result = await auth.GetAuthenticationHeaderAsync(CancellationToken.None).ConfigureAwait(false);

                result.Scheme.Should().Be("Bearer");
                result.Parameter.Should().Be(expiredIdToken);
                Assert.True(false, "should not be here");
            }
            catch (KubernetesClientException e)
            {
                Assert.StartsWith("Unable to refresh OIDC token.", e.Message);
            }

            try
            {
                // attempt to refresh id token when null
                auth   = new OidcTokenProvider(clientId, clientSecret, idpIssuerUrl, null, refreshToken);
                result = await auth.GetAuthenticationHeaderAsync(CancellationToken.None).ConfigureAwait(false);

                result.Scheme.Should().Be("Bearer");
                result.Parameter.Should().Be(expiredIdToken);
                Assert.True(false, "should not be here");
            }
            catch (KubernetesClientException e)
            {
                Assert.StartsWith("Unable to refresh OIDC token.", e.Message);
            }
        }
        private void SetUserDetails(K8SConfiguration k8SConfig, Context activeContext)
        {
            if (string.IsNullOrWhiteSpace(activeContext.ContextDetails.User))
            {
                return;
            }

            var userDetails = k8SConfig.Users.FirstOrDefault(c => c.Name.Equals(
                                                                 activeContext.ContextDetails.User,
                                                                 StringComparison.OrdinalIgnoreCase));

            if (userDetails == null)
            {
                throw new KubeConfigException($"User not found for context {activeContext.Name} in kubeconfig");
            }

            if (userDetails.UserCredentials == null)
            {
                throw new KubeConfigException($"User credentials not found for user: {userDetails.Name} in kubeconfig");
            }

            var userCredentialsFound = false;

            // Basic and bearer tokens are mutually exclusive
            if (!string.IsNullOrWhiteSpace(userDetails.UserCredentials.Token))
            {
                AccessToken          = userDetails.UserCredentials.Token;
                userCredentialsFound = true;
            }
            else if (!string.IsNullOrWhiteSpace(userDetails.UserCredentials.UserName) &&
                     !string.IsNullOrWhiteSpace(userDetails.UserCredentials.Password))
            {
                Username             = userDetails.UserCredentials.UserName;
                Password             = userDetails.UserCredentials.Password;
                userCredentialsFound = true;
            }

            // Token and cert based auth can co-exist
            if (!string.IsNullOrWhiteSpace(userDetails.UserCredentials.ClientCertificateData) &&
                !string.IsNullOrWhiteSpace(userDetails.UserCredentials.ClientKeyData))
            {
                ClientCertificateData    = userDetails.UserCredentials.ClientCertificateData;
                ClientCertificateKeyData = userDetails.UserCredentials.ClientKeyData;
                userCredentialsFound     = true;
            }

            if (!string.IsNullOrWhiteSpace(userDetails.UserCredentials.ClientCertificate) &&
                !string.IsNullOrWhiteSpace(userDetails.UserCredentials.ClientKey))
            {
                ClientCertificateFilePath = GetFullPath(k8SConfig, userDetails.UserCredentials.ClientCertificate);
                ClientKeyFilePath         = GetFullPath(k8SConfig, userDetails.UserCredentials.ClientKey);
                userCredentialsFound      = true;
            }

            if (userDetails.UserCredentials.AuthProvider != null)
            {
                if (userDetails.UserCredentials.AuthProvider.Config != null &&
                    (userDetails.UserCredentials.AuthProvider.Config.ContainsKey("access-token") ||
                     userDetails.UserCredentials.AuthProvider.Config.ContainsKey("id-token")))
                {
                    switch (userDetails.UserCredentials.AuthProvider.Name)
                    {
                    case "azure":
                    {
                        var config = userDetails.UserCredentials.AuthProvider.Config;
                        if (config.ContainsKey("expires-on"))
                        {
                            var            expiresOn = int.Parse(config["expires-on"]);
                            DateTimeOffset expires;
                            expires = DateTimeOffset.FromUnixTimeSeconds(expiresOn);

                            if (DateTimeOffset.Compare(
                                    expires,
                                    DateTimeOffset.Now)
                                <= 0)
                            {
                                var tenantId    = config["tenant-id"];
                                var clientId    = config["client-id"];
                                var apiServerId = config["apiserver-id"];
                                var refresh     = config["refresh-token"];
                                var newToken    = RenewAzureToken(
                                    tenantId,
                                    clientId,
                                    apiServerId,
                                    refresh);
                                config["access-token"] = newToken;
                            }
                        }

                        AccessToken          = config["access-token"];
                        userCredentialsFound = true;
                        break;
                    }

                    case "gcp":
                    {
                        // config
                        var config = userDetails.UserCredentials.AuthProvider.Config;
                        TokenProvider        = new GcpTokenProvider(config["cmd-path"]);
                        userCredentialsFound = true;
                        break;
                    }

                    case "oidc":
                    {
                        var config = userDetails.UserCredentials.AuthProvider.Config;
                        AccessToken = config["id-token"];
                        if (config.ContainsKey("client-id") &&
                            config.ContainsKey("idp-issuer-url") &&
                            config.ContainsKey("id-token") &&
                            config.ContainsKey("refresh-token"))
                        {
                            string clientId     = config["client-id"];
                            string clientSecret = config.ContainsKey("client-secret") ? config["client-secret"] : null;
                            string idpIssuerUrl = config["idp-issuer-url"];
                            string idToken      = config["id-token"];
                            string refreshToken = config["refresh-token"];

                            TokenProvider = new OidcTokenProvider(clientId, clientSecret, idpIssuerUrl, idToken, refreshToken);

                            userCredentialsFound = true;
                        }

                        break;
                    }
                    }
                }
            }

            if (userDetails.UserCredentials.ExternalExecution != null)
            {
                if (string.IsNullOrWhiteSpace(userDetails.UserCredentials.ExternalExecution.Command))
                {
                    throw new KubeConfigException(
                              "External command execution to receive user credentials must include a command to execute");
                }

                if (string.IsNullOrWhiteSpace(userDetails.UserCredentials.ExternalExecution.ApiVersion))
                {
                    throw new KubeConfigException("External command execution missing ApiVersion key");
                }

                var(accessToken, clientCertificateData, clientCertificateKeyData) = ExecuteExternalCommand(userDetails.UserCredentials.ExternalExecution);
                AccessToken = accessToken;
                // When reading ClientCertificateData from a config file it will be base64 encoded, and code later in the system (see CertUtils.GeneratePfx)
                // expects ClientCertificateData and ClientCertificateKeyData to be base64 encoded because of this. However the string returned by external
                // auth providers is the raw certificate and key PEM text, so we need to take that and base64 encoded it here so it can be decoded later.
                ClientCertificateData    = clientCertificateData == null ? null : Convert.ToBase64String(System.Text.Encoding.ASCII.GetBytes(clientCertificateData));
                ClientCertificateKeyData = clientCertificateKeyData == null ? null : Convert.ToBase64String(System.Text.Encoding.ASCII.GetBytes(clientCertificateKeyData));

                userCredentialsFound = true;
            }

            if (!userCredentialsFound)
            {
                throw new KubeConfigException(
                          $"User: {userDetails.Name} does not have appropriate auth credentials in kubeconfig");
            }
        }