rancher/rancher · error

[Google OAuth] formGoogleOAuthRedirectURLFromMap: no creds f

Error message

[Google OAuth] formGoogleOAuthRedirectURLFromMap: no creds file present

What it means

formGoogleOAuthRedirectURLFromMap requires the request's config map to carry a string 'oauthCredential' entry; this error fires when that key is absent or not a string. It is the first guard before the credential is read from the secret and parsed for a redirect URL. This path runs during testAndApply-style flows that receive the config as a raw map (e.g. from the HTTP request body) rather than a typed CR.

Source

Thrown at pkg/auth/providers/googleoauth/goauthconfig_actions.go:133

	userExtraInfo := g.GetUserExtraAttributes(userPrincipal)
	if err := retry.RetryOnConflict(retry.DefaultRetry, func() error {
		return g.userMGR.UserAttributeCreateOrUpdate(user.Name, userPrincipal.Provider, groupPrincipals, userExtraInfo)
	}); err != nil {
		return httperror.NewAPIError(httperror.ServerError, fmt.Sprintf("Failed to create or update userAttribute: %v", err))
	}

	return g.tokenMGR.CreateTokenAndSetCookie(user.Name, userPrincipal, groupPrincipals, providerInfo, 0, "Token via Google OAuth Configuration", request)

}

func (g *googleOauthProvider) formGoogleOAuthRedirectURL(goauthConfig *apiv3.GoogleOauthConfig) (string, error) {
	return g.getRedirectURL([]byte(goauthConfig.OauthCredential))
}

func (g *googleOauthProvider) formGoogleOAuthRedirectURLFromMap(config map[string]any) (string, error) {
	clientCreds, ok := config[client.GoogleOauthConfigFieldOauthCredential].(string)
	if !ok {
		return "", fmt.Errorf("[Google OAuth] formGoogleOAuthRedirectURLFromMap: no creds file present")
	}
	value, err := common.ReadFromSecret(g.secrets, clientCreds, strings.ToLower(client.GoogleOauthConfigFieldOauthCredential))
	if err != nil {
		return "", err
	}

	return g.getRedirectURL([]byte(value))
}

func (g *googleOauthProvider) getRedirectURL(configFile []byte) (string, error) {
	oauth2Config, err := google.ConfigFromJSON(configFile)
	if err != nil {
		return "", err
	}
	// Removing redirectURL from config because UI will set it
	oauth2Config.RedirectURL = ""
	// access type=offline and prompt=consent (approval force), return a refresh token
	// UI will generate and validate the state

View on GitHub (pinned to 932558d4e6)

Solutions

  1. Include the oauthCredential (secret name/reference) as a string field in the config map of the request body
  2. Validate the payload shape before submitting: config["oauthCredential"] must exist and be a string
  3. If the intent is to reuse stored creds, use the flow/API that reads from the CR instead of the map-based path

Example fix

// before
body := map[string]any{"hostname": "example.com"}
url, err := p.formGoogleOAuthRedirectURLFromMap(body) // -> no creds file present

// after
body := map[string]any{
    "hostname":        "example.com",
    "oauthCredential": "google-oauth-client-secret",
}
url, err := p.formGoogleOAuthRedirectURLFromMap(body)
Defensive patterns

Strategy: validation

Validate before calling

// hasOauthCredential validates the request map before calling the provider.
func hasOauthCredential(config map[string]any) error {
    v, ok := config[client.GoogleOauthConfigFieldOauthCredential]
    if !ok {
        return fmt.Errorf("oauthCredential is required")
    }
    if _, ok := v.(string); !ok {
        return fmt.Errorf("oauthCredential must be a string")
    }
    return nil
}

Try / catch

url, err := g.formGoogleOAuthRedirectURLFromMap(config)
if err != nil {
    if strings.Contains(err.Error(), "no creds file present") {
        return "", httperror.NewAPIError(httperror.InvalidBodyContent, "oauthCredential (string) is required in the request body")
    }
    return "", err
}

Prevention

When it happens

Trigger: POSTing a testAndApply/update request whose spec map omits oauthCredential; sending oauthCredential as a non-string (map or number) in JSON; UI form submitting without the credential file because the field was left blank.

Common situations: Automated API calls that build the request body from a template missing the credential; JSON payloads where the file content was nested under the wrong key; clients assuming an existing stored credential is reused and omitting the field.

Related errors


AI-assisted analysis of rancher/rancher@932558d4e6 (2026-08-16). Data as JSON: /api/errors/191baa5e7940c301. Report an issue: GitHub.