From 6242940328da417c5a49f34f94cf1f983816df10 Mon Sep 17 00:00:00 2001 From: Vui Lam Date: Thu, 10 Oct 2024 14:23:09 -0700 Subject: [PATCH] Update UAA token refresh logic Ensures a pre-established, intentionally non-secret, string is used in the token exchange request as the client secret to ensure the refresh token obtained is reusable. Signed-off-by: Vui Lam --- pkg/auth/common/login_handler.go | 7 +++++-- pkg/auth/uaa/tanzu.go | 11 +++++++++++ pkg/auth/uaa/uaa.go | 2 +- pkg/command/apitoken.go | 2 +- pkg/command/context.go | 2 +- pkg/constants/env_variables.go | 3 +++ 6 files changed, 22 insertions(+), 5 deletions(-) diff --git a/pkg/auth/common/login_handler.go b/pkg/auth/common/login_handler.go index 2331ac15d..cca563e2a 100644 --- a/pkg/auth/common/login_handler.go +++ b/pkg/auth/common/login_handler.go @@ -123,12 +123,15 @@ func WithCertInfo(tlsSkipVerify bool, caCertData string) LoginOption { } } -// WithClientID specifies a OAuth Client ID to use -func WithClientID(clientID string) LoginOption { +// WithClientIDAndSecret specifies a OAuth Client ID and secret to use +func WithClientIDAndSecret(clientID, clientSecret string) LoginOption { return func(h *TanzuLoginHandler) error { h.clientID = clientID + h.clientSecret = clientSecret if h.oauthConfig != nil { h.oauthConfig.ClientID = clientID + // + h.oauthConfig.ClientSecret = clientSecret } return nil } diff --git a/pkg/auth/uaa/tanzu.go b/pkg/auth/uaa/tanzu.go index f775c7aa0..e23e935b4 100644 --- a/pkg/auth/uaa/tanzu.go +++ b/pkg/auth/uaa/tanzu.go @@ -35,6 +35,17 @@ func getIssuerEndpoints(issuerURL string) common.IssuerEndPoints { } } +func GetClientSecret() string { + // Not really used as a secret, but specified in OAuth client to UAA in order + // to obtain the expected token refresh behavior. + secret := "tanzu_intentionally_not_a_secret" + + if noClientSecret, _ := strconv.ParseBool(os.Getenv(constants.UAANoClientSecret)); noClientSecret { + secret = "" + } + return secret +} + func GetAlternateClientID() string { // Default to use the same client id, even for non-interactive login use cases. clientID := tanzuCLIClientID diff --git a/pkg/auth/uaa/uaa.go b/pkg/auth/uaa/uaa.go index eba4b91e2..d616448bb 100644 --- a/pkg/auth/uaa/uaa.go +++ b/pkg/auth/uaa/uaa.go @@ -15,7 +15,7 @@ func GetTokens(refreshOrAPIToken, _, issuer, tokenType string) (*common.Token, e if tokenType == common.APITokenType { clientID = GetAlternateClientID() } - loginOptions := []common.LoginOption{common.WithRefreshToken(refreshOrAPIToken), common.WithListenerPortFromEnv(constants.TanzuCLIOAuthLocalListenerPort), common.WithClientID(clientID)} + loginOptions := []common.LoginOption{common.WithRefreshToken(refreshOrAPIToken), common.WithListenerPortFromEnv(constants.TanzuCLIOAuthLocalListenerPort), common.WithClientIDAndSecret(clientID, GetClientSecret())} if tokenType == common.APITokenType { loginOptions = append(loginOptions, common.WithSuppressInteractive(true)) } diff --git a/pkg/command/apitoken.go b/pkg/command/apitoken.go index 733bd1bb8..70a6b9520 100644 --- a/pkg/command/apitoken.go +++ b/pkg/command/apitoken.go @@ -75,7 +75,7 @@ func createAPIToken(cmd *cobra.Command, _ []string) (err error) { // Also specify the client ID to use for token generation loginOptions := []commonauth.LoginOption{ commonauth.WithListenerPortFromEnv(constants.TanzuCLIOAuthLocalListenerPort), - commonauth.WithClientID(uaa.GetAlternateClientID()), + commonauth.WithClientIDAndSecret(uaa.GetAlternateClientID(), uaa.GetClientSecret()), } token, err = uaa.TanzuLogin(c.GlobalOpts.Auth.Issuer, loginOptions...) diff --git a/pkg/command/context.go b/pkg/command/context.go index 6bae0224f..ca1fffec6 100644 --- a/pkg/command/context.go +++ b/pkg/command/context.go @@ -736,7 +736,7 @@ func doUAAAPITokenAuthAndUpdateContext(c *configtypes.Context, uaaEndpoint, apiT loginOptions := []commonauth.LoginOption{ commonauth.WithSuppressInteractive(true), // fail instead of falling back to interactive login commonauth.WithRefreshToken(apiTokenValue), - commonauth.WithClientID(uaa.GetAlternateClientID()), + commonauth.WithClientIDAndSecret(uaa.GetAlternateClientID(), uaa.GetClientSecret()), } var endpointCACertData string diff --git a/pkg/constants/env_variables.go b/pkg/constants/env_variables.go index bbba1149e..c67a58153 100644 --- a/pkg/constants/env_variables.go +++ b/pkg/constants/env_variables.go @@ -69,6 +69,9 @@ const ( // UAAUseAlternateClient allows use of an alternate UAA client for non-interactive logins UAAUseAlternateClient = "TANZU_CLI_USE_ALTERNATE_UAA_CLIENT" + // UAANoClientSecret skips setting of OAuth Client Secret + UAANoClientSecret = "TANZU_CLI_NO_UAA_CLIENT_SECRET" //nolint:gosec + // TanzuCLIOAuthLocalListenerPort is the port to be used by local listener for OAuth authorization flow TanzuCLIOAuthLocalListenerPort = "TANZU_CLI_OAUTH_LOCAL_LISTENER_PORT"