googleapis / googleapis/google-cloud-go

Intermittent "Error getting an UberMint" error when downscoping token for use in GCS

Open
#14,482 0 comments 0 reactions 1 assignee Claimed by @cpriti-os View on GitHub
api: storage triage me
Dominant language
Go
Stars
4.5k
Forks
1.6k
Avg merge
1d 13h
Merged PRs (30d)
109

Description

## Client

* GCS
* cloud.google.com/go/storage
* OAuth
* golang.org/x/oauth2
* golang.org/x/oauth2/google
* golang.org/x/oauth2/google/downscope

## Environment

Go version: 1.24.7
Package versions:
* cloud.google.com/go/storage@v1.50.0
* golang.org/x/oauth2@v0.30.0

## Code and Dependencies

```go

import (
"context"
"fmt"

"golang.org/x/oauth2"
"golang.org/x/oauth2/google"
"golang.org/x/oauth2/google/downscope"
)

// createDownscopedToken would be run on the token broker in order to generate
// a downscoped access token that only grants access to objects whose name begins with prefix.
// The token broker would then pass the newly created token to the requesting token consumer for use.
func createDownscopedToken(bucketName string, prefix string) error {
// bucketName := "foo"
// prefix := "profile-picture-"

ctx := context.Background()
// A condition can optionally be provided to further restrict access permissions.
condition := downscope.AvailabilityCondition{
Expression: "resource.name.startsWith('projects/_/buckets/" + bucketName + "/objects/" + prefix + "')",
Title: prefix + " Only",
Description: "Restricts a token to only be able to access objects that start with `" + prefix + "`",
}
// Initializes an accessBoundary with one Rule which restricts the downscoped
// token to only be able to access the bucket "bucketName" and only grants it the
// permission "storage.objectViewer".
accessBoundary := []downscope.AccessBoundaryRule{
{
AvailableResource: "//storage.googleapis.com/projects/_/buckets/" + bucketName,
AvailablePermissions: []string{"inRole:roles/storage.objectViewer"},
Condition: &condition, // Optional
},
}

// This Source can be initialized in multiple ways; the following example uses
// Application Default Credentials.
var rootSource oauth2.TokenSource

// You must provide the "https://www.googleapis.com/auth/cloud-platform" scope.
rootSource, err := google.DefaultTokenSource(ctx, "https://www.googleapis.com/auth/cloud-platform")
if err != nil {
return fmt.Errorf("failed to generate rootSource: %w", err)
}

// downscope.NewTokenSource constructs the token source with the configuration provided.
dts, err := downscope.NewTokenSource(ctx, downscope.DownscopingConfig{RootSource: rootSource, Rules: accessBoundary})
if err != nil {
return fmt.Errorf("failed to generate downscoped token source: %w", err)
}
// Token() uses the previously declared TokenSource to generate a downscoped token.
tok, err := dts.Token()
if err != nil {
// <-- HERE returns error:
// "failed to generate token: downscope: unable to exchange token; 400. Server responded: {\"error\":\"invalid_grant\",\"error_description\":\"Error getting an UberMint\"}"
return fmt.Errorf("failed to generate token: %w", err)
}
// Pass this token back to the token consumer.
_ = tok
return nil
}
```

## Expected behavior

Description indicating whether the error is server or client-side.

The error message refers to an internal service error but the status code is 4xx, indicating a client-side error.

What is "UberMint"?
Can the request be retried?
What's the corrective action here?

## Actual behavior

An opaque internal error message is returned.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.