Repository: google/go-containerregistry
Pull request #694 (2020-03-12 12:14:45)

Pass RegistryToken directly
I would like to pass the Bearer Token generated elsewhere directly. This is because I am developing plugins of some container registries such as Harbor and Quay. These plugins receive Bearer Token directly instead of username/password and need to use it for the authentication with the registries.

```
token := "eyJhbGciOiJSUzI1NiI..." //  passed by a container registry
img, err := remote.Image(ref, remote.WithAuth(&authn.Bearer{Token: token}))
if err != nil {
	return err
}
...
```

codecov-io: # [Codecov](https://codecov.io/gh/google/go-containerregistry/pull/694?src=pr&el=h1) Report
> Merging [#694](https://codecov.io/gh/google/go-containerregistry/pull/694?src=pr&el=desc) into [master](https://codecov.io/gh/google/go-containerregistry/commit/4b1985e5ea2104672636879e1694808f735fd214&el=desc) will **increase** coverage by `0.01%`.
> The diff coverage is `100.00%`.

[![Impacted file tree graph](https://codecov.io/gh/google/go-containerregistry/pull/694/graphs/tree.svg?width=650&height=150&src=pr&token=wG7iiDCdZ4)](https://codecov.io/gh/google/go-containerregistry/pull/694?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master     #694      +/-   ##
==========================================
+ Coverage   79.72%   79.73%   +0.01%     
==========================================
  Files         102      102              
  Lines        4532     4535       +3     
==========================================
+ Hits         3613     3616       +3     
  Misses        505      505              
  Partials      414      414              
```


| [Impacted Files](https://codecov.io/gh/google/go-containerregistry/pull/694?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [pkg/v1/remote/transport/bearer.go](https://codecov.io/gh/google/go-containerregistry/pull/694/diff?src=pr&el=tree#diff-cGtnL3YxL3JlbW90ZS90cmFuc3BvcnQvYmVhcmVyLmdv) | `77.06% <100.00%> (+0.64%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/google/go-containerregistry/pull/694?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/google/go-containerregistry/pull/694?src=pr&el=footer). Last update [4b1985e...a55c744](https://codecov.io/gh/google/go-containerregistry/pull/694?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/pkg/v1/remote/transport/bearer.go b/pkg/v1/remote/transport/bearer.go
index c31a609c..f53eb178 100644
--- a/pkg/v1/remote/transport/bearer.go
+++ b/pkg/v1/remote/transport/bearer.go
@@ -92,6 +92,12 @@ func (bt *bearerTransport) refresh() error {
 	if err != nil {
 		return err
 	}
+
+	if auth.RegistryToken != "" {
+		bt.bearer.RegistryToken = auth.RegistryToken
+		return nil
+	}
+
 	var content []byte
 	if auth.IdentityToken != "" {
 		// If the secret being stored is an identity token,


Test patch:
diff --git a/pkg/v1/remote/transport/bearer_test.go b/pkg/v1/remote/transport/bearer_test.go
index 3a3540b2..9a86f160 100644
--- a/pkg/v1/remote/transport/bearer_test.go
+++ b/pkg/v1/remote/transport/bearer_test.go
@@ -171,6 +171,7 @@ func TestBearerTransportTokenRefresh(t *testing.T) {
 		t.Fatalf("Unexpected error during NewRegistry: %v", err)
 	}
 
+	// Pass Username/Password
 	transport := &bearerTransport{
 		inner:    http.DefaultTransport,
 		bearer:   authn.AuthConfig{RegistryToken: initialToken},
@@ -184,6 +185,24 @@ func TestBearerTransportTokenRefresh(t *testing.T) {
 	res, err := client.Get(fmt.Sprintf("http://%s/v2/foo/bar/blobs/blah", u.Host))
 	if err != nil {
 		t.Errorf("Unexpected error during client.Get: %v", err)
+		return
+	}
+	if res.StatusCode != http.StatusOK {
+		t.Errorf("client.Get final StatusCode got %v, want: %v", res.StatusCode, http.StatusOK)
+	}
+	if got, want := transport.bearer.RegistryToken, refreshedToken; got != want {
+		t.Errorf("Expected Bearer token to be refreshed, got %v, want %v", got, want)
+	}
+
+	// Pass RegistryToken directly
+	transport.bearer = authn.AuthConfig{RegistryToken: initialToken}
+	transport.basic = &authn.Bearer{Token: refreshedToken}
+	client = http.Client{Transport: transport}
+
+	res, err = client.Get(fmt.Sprintf("http://%s/v2/foo/bar/blobs/blah", u.Host))
+	if err != nil {
+		t.Errorf("Unexpected error during client.Get: %v", err)
+		return
 	}
 	if res.StatusCode != http.StatusOK {
 		t.Errorf("client.Get final StatusCode got %v, want: %v", res.StatusCode, http.StatusOK)