grpc/grpc-go · error
unable to transfer oauthAccess PerRPCCredentials: %v
Error message
unable to transfer oauthAccess PerRPCCredentials: %v
What it means
Thrown from oauthAccess.GetRequestMetadata (oauth.go:133) when the security-level check fails for credentials created by the deprecated oauth.NewOauthAccess(token). The supplied static OAuth token is a bearer secret, so gRPC will not attach it over an insecure channel. RequireTransportSecurity() returns true.
Source
Thrown at credentials/oauth/oauth.go:133
return true
}
// oauthAccess supplies PerRPCCredentials from a given token.
type oauthAccess struct {
token oauth2.Token
}
// NewOauthAccess constructs the PerRPCCredentials using a given token.
//
// Deprecated: use oauth.TokenSource instead.
func NewOauthAccess(token *oauth2.Token) credentials.PerRPCCredentials {
return oauthAccess{token: *token}
}
func (oa oauthAccess) GetRequestMetadata(ctx context.Context, _ ...string) (map[string]string, error) {
ri, _ := credentials.RequestInfoFromContext(ctx)
if err := credentials.CheckSecurityLevel(ri.AuthInfo, credentials.PrivacyAndIntegrity); err != nil {
return nil, fmt.Errorf("unable to transfer oauthAccess PerRPCCredentials: %v", err)
}
return map[string]string{
"authorization": oa.token.Type() + " " + oa.token.AccessToken,
}, nil
}
func (oa oauthAccess) RequireTransportSecurity() bool {
return true
}
// NewComputeEngine constructs the PerRPCCredentials that fetches access tokens from
// Google Compute Engine (GCE)'s metadata server. It is only valid to use this
// if your program is running on a GCE instance.
// TODO(dsymonds): Deprecate and remove this.
func NewComputeEngine() credentials.PerRPCCredentials {
return TokenSource{google.ComputeTokenSource("")}
}
View on GitHub (pinned to 03255a9237)
Solutions
- Migrate from deprecated NewOauthAccess to oauth.TokenSource{TokenSource: oauth2.StaticTokenSource(token)}.
- Always pair these credentials with TLS transport credentials.
- If plaintext is required, remove the per-RPC credentials entirely.
Example fix
// before
creds := oauth.NewOauthAccess(token)
conn, _ := grpc.NewClient(addr,
grpc.WithTransportCredentials(insecure.NewCredentials()),
grpc.WithPerRPCCredentials(creds),
)
// after
creds := oauth.TokenSource{TokenSource: oauth2.StaticTokenSource(token)}
conn, _ := grpc.NewClient(addr,
grpc.WithTransportCredentials(credentials.NewClientTLSFromCert(caPool, "")),
grpc.WithPerRPCCredentials(creds),
) Defensive patterns
Strategy: validation
Validate before calling
// Migrate off deprecated NewOauthAccess and always use TLS.
creds := oauth.TokenSource{TokenSource: oauth2.StaticTokenSource(token)}
tlsCreds := credentials.NewClientTLSFromCert(caPool, "")
conn, err := grpc.NewClient(addr,
grpc.WithTransportCredentials(tlsCreds),
grpc.WithPerRPCCredentials(creds),
) Try / catch
if st, ok := status.FromError(err); ok && st.Code() == codes.Unavailable {
if strings.Contains(st.Message(), "oauthAccess PerRPCCredentials") {
// channel insecure; reconfigure with TLS
}
} Prevention
- Stop using deprecated oauth.NewOauthAccess; switch to oauth.TokenSource.
- Never attach static OAuth tokens to insecure channels.
- Static tokens rotate via the TokenSource; configure TLS at the same time.
When it happens
Trigger: Using oauth.NewOauthAccess(token) (deprecated) on a channel with insecure.NewCredentials() or no transport credentials.
Common situations: Legacy code that still calls the deprecated NewOauthAccess; examples that predate oauth.TokenSource; mixing a manually obtained oauth2.Token with a plaintext channel.
Related errors
- unable to transfer TokenSource PerRPCCredentials: %v
- unable to transfer jwtAccess PerRPCCredentials: %v
- unable to transfer serviceAccount PerRPCCredentials: %v
- unable to transfer STS PerRPCCredentials: %v
- cannot send secure credentials on an insecure connection: %v
AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07).
Data as JSON: /api/errors/2065fa2ed1460801.
Report an issue: GitHub.