remotes/docker: allow fetching "refresh token" (aka "identity token")

The new AuthorizerOpt `WithFetchRefreshToken` allows fetching "refresh token"
(aka "identity token", "offline token").

For HTTP GET mode (`FetchToken`), `offline_token=true` is set in the request.
https://docs.docker.com/registry/spec/auth/token/#requesting-a-token

For HTTP POST mode (`FetchTokenWithOAuth`), `access_type=offline` is set in the request.
https://docs.docker.com/registry/spec/auth/oauth/#getting-a-token

Signed-off-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
This commit is contained in:
Akihiro Suda
2021-12-24 14:20:04 +09:00
parent 8094f50dd0
commit 97623ab0cd
3 changed files with 220 additions and 25 deletions

View File

@@ -73,6 +73,15 @@ type TokenOptions struct {
Scopes []string
Username string
Secret string
// FetchRefreshToken enables fetching a refresh token (aka "identity token", "offline token") along with the bearer token.
//
// For HTTP GET mode (FetchToken), FetchRefreshToken sets `offline_token=true` in the request.
// https://docs.docker.com/registry/spec/auth/token/#requesting-a-token
//
// For HTTP POST mode (FetchTokenWithOAuth), FetchRefreshToken sets `access_type=offline` in the request.
// https://docs.docker.com/registry/spec/auth/oauth/#getting-a-token
FetchRefreshToken bool
}
// OAuthTokenResponse is response from fetching token with a OAuth POST request
@@ -101,6 +110,9 @@ func FetchTokenWithOAuth(ctx context.Context, client *http.Client, headers http.
form.Set("username", to.Username)
form.Set("password", to.Secret)
}
if to.FetchRefreshToken {
form.Set("access_type", "offline")
}
req, err := http.NewRequest("POST", to.Realm, strings.NewReader(form.Encode()))
if err != nil {
@@ -175,6 +187,10 @@ func FetchToken(ctx context.Context, client *http.Client, headers http.Header, t
req.SetBasicAuth(to.Username, to.Secret)
}
if to.FetchRefreshToken {
reqParams.Add("offline_token", "true")
}
req.URL.RawQuery = reqParams.Encode()
resp, err := ctxhttp.Do(ctx, client, req)