fix(storage): don't assume auth from a client option (#4982)

* fix(storage): don't assume auth from a client option

There are cases where a user might not auth with ADC or a client
option such as passing in their own client. In these cases we
should not error, but instead just not make use of the internal
cred lookup.

Fixes: #4980

* switch ordering of some lines

* add some docs
diff --git a/storage/bucket.go b/storage/bucket.go
index d8747e5..ec7dcb5 100644
--- a/storage/bucket.go
+++ b/storage/bucket.go
@@ -239,6 +239,9 @@
 // This method only requires the Method and Expires fields in the specified
 // SignedURLOptions opts to be non-nil. If not provided, it attempts to fill the
 // GoogleAccessID and PrivateKey from the GOOGLE_APPLICATION_CREDENTIALS environment variable.
+// If you are authenticating with a custom HTTP client, Service Account based
+// auto-detection will be hindered.
+//
 // If no private key is found, it attempts to use the GoogleAccessID to sign the URL.
 // This requires the IAM Service Account Credentials API to be enabled
 // (https://console.developers.google.com/apis/api/iamcredentials.googleapis.com/overview)
@@ -260,7 +263,7 @@
 		newopts.GoogleAccessID = id
 	}
 	if newopts.SignBytes == nil && len(newopts.PrivateKey) == 0 {
-		if len(b.c.creds.JSON) > 0 {
+		if b.c.creds != nil && len(b.c.creds.JSON) > 0 {
 			var sa struct {
 				PrivateKey string `json:"private_key"`
 			}
@@ -285,7 +288,7 @@
 func (b *BucketHandle) detectDefaultGoogleAccessID() (string, error) {
 	returnErr := errors.New("no credentials found on client and not on GCE (Google Compute Engine)")
 
-	if len(b.c.creds.JSON) > 0 {
+	if b.c.creds != nil && len(b.c.creds.JSON) > 0 {
 		var sa struct {
 			ClientEmail string `json:"client_email"`
 		}
diff --git a/storage/storage.go b/storage/storage.go
index 98a0389..81ff43c 100644
--- a/storage/storage.go
+++ b/storage/storage.go
@@ -100,7 +100,8 @@
 	scheme string
 	// ReadHost is the default host used on the reader.
 	readHost string
-	creds    *google.Credentials
+	// May be nil.
+	creds *google.Credentials
 
 	// gc is an optional gRPC-based, GAPIC client.
 	//
@@ -131,14 +132,13 @@
 		opts = append(opts, internaloption.WithDefaultEndpoint("https://storage.googleapis.com/storage/v1/"))
 		opts = append(opts, internaloption.WithDefaultMTLSEndpoint("https://storage.mtls.googleapis.com/storage/v1/"))
 
+		// Don't error out here. The user may have passed in their own HTTP
+		// client which does not auth with ADC or other common conventions.
 		c, err := transport.Creds(ctx, opts...)
-		if err != nil {
-			return nil, err
+		if err == nil {
+			creds = c
+			opts = append(opts, internaloption.WithCredentials(creds))
 		}
-		creds = c
-
-		opts = append(opts, internaloption.WithCredentials(creds))
-
 	} else {
 		var hostURL *url.URL