Change:
When I want to use basic-auth, kubectl will display the password I entered: I think it is more sensible to hide the password?
And it seems that kubectl request for username/password twice...
I'll take this. There is a library here: That appears to do the trick, but we need some refactoring so that it can read from an arbitrary reader to fit our usecase.
This was fixed by but I didn't close this issue. Closing it now.

Discussion:
// DEPRECATED will be replace DefaultClientConfig = DirectClientConfig{*clientcmdapi.NewConfig(), "", &ConfigOverrides{ ClusterDefaults: ClusterDefaults, <del> }, nil, NewDefaultClientConfigLoadingRules()} </del> <ins> }, nil, NewDefaultClientConfigLoadingRules(), promptedCredentials{}} </ins> ) // getDefaultServer returns a default setting for DefaultClientConfig

type PersistAuthProviderConfigForUser func(user string) restclient.AuthProviderConfigPersister <ins> type promptedCredentials struct { username string password string } </ins> // DirectClientConfig is a ClientConfig interface that is backed by a clientcmdapi.Config, options overrides, and an optional fallbackReader for auth information type DirectClientConfig struct { config         clientcmdapi.Config

overrides      *ConfigOverrides fallbackReader io.Reader configAccess   ConfigAccess <ins> // promptedCredentials store the credentials input by the user promptedCredentials promptedCredentials </ins> } // NewDefaultClientConfig creates a DirectClientConfig using the config.CurrentContext as the context name func NewDefaultClientConfig(config clientcmdapi.Config, overrides *ConfigOverrides) ClientConfig { <del> return &DirectClientConfig{config, config.CurrentContext, overrides, nil, NewDefaultClientConfigLoadingRules()} </del> <ins> return &DirectClientConfig{config, config.CurrentContext, overrides, nil, NewDefaultClientConfigLoadingRules(), promptedCredentials{}} </ins> } // NewNonInteractiveClientConfig creates a DirectClientConfig using the passed context name and does not have a fallback reader for auth information func NewNonInteractiveClientConfig(config clientcmdapi.Config, contextName string, overrides *ConfigOverrides, configAccess ConfigAccess) ClientConfig { <del> return &DirectClientConfig{config, contextName, overrides, nil, configAccess} </del> <ins> return &DirectClientConfig{config, contextName, overrides, nil, configAccess, promptedCredentials{}} </ins> } // NewInteractiveClientConfig creates a DirectClientConfig using the passed context name and a reader in case auth information is not provided via files or flags func NewInteractiveClientConfig(config clientcmdapi.Config, contextName string, overrides *ConfigOverrides, fallbackReader io.Reader, configAccess ConfigAccess) ClientConfig { <del> return &DirectClientConfig{config, contextName, overrides, fallbackReader, configAccess} </del> <ins> return &DirectClientConfig{config, contextName, overrides, fallbackReader, configAccess, promptedCredentials{}} </ins> } func (config *DirectClientConfig) RawConfig() (clientcmdapi.Config, error) {

authInfoName, _ := config.getAuthInfoName() persister = PersisterForUser(config.configAccess, authInfoName) } <del> userAuthPartialConfig, err := getUserIdentificationPartialConfig(configAuthInfo, config.fallbackReader, persister) </del> <ins> userAuthPartialConfig, err := config.getUserIdentificationPartialConfig(configAuthInfo, config.fallbackReader, persister) </ins> if err != nil { return nil, err }

// 2.  configAuthInfo.auth-path (this file can contain information that conflicts with #1, and we want #1 to win the priority) // 3.  if there is not enough information to idenfity the user, load try the ~/.kubernetes_auth file // 4.  if there is not enough information to identify the user, prompt if possible <del> func getUserIdentificationPartialConfig(configAuthInfo clientcmdapi.AuthInfo, fallbackReader io.Reader, persistAuthConfig restclient.AuthProviderConfigPersister) (*restclient.Config, error) { </del> <ins> func (config *DirectClientConfig) getUserIdentificationPartialConfig(configAuthInfo clientcmdapi.AuthInfo, fallbackReader io.Reader, persistAuthConfig restclient.AuthProviderConfigPersister) (*restclient.Config, error) { </ins> mergedConfig := &restclient.Config{} // blindly overwrite existing values based on precedence

// if there still isn't enough information to authenticate the user, try prompting if !canIdentifyUser(*mergedConfig) && (fallbackReader != nil) { <ins> if len(config.promptedCredentials.username) > 0 && len(config.promptedCredentials.password) > 0 { mergedConfig.Username = config.promptedCredentials.username mergedConfig.Password = config.promptedCredentials.password return mergedConfig, nil } </ins> prompter := NewPromptingAuthLoader(fallbackReader) promptedAuthInfo, err := prompter.Prompt() if err != nil {

mergedConfig = &restclient.Config{} mergo.Merge(mergedConfig, promptedConfig) mergo.Merge(mergedConfig, previouslyMergedConfig) <ins> config.promptedCredentials.username = mergedConfig.Username config.promptedCredentials.password = mergedConfig.Password </ins> } return mergedConfig, nil