Allows token authentication handler to request additional scopes
When an auth request provides the "from" query parameter, the token handler will add a "pull" scope for the provided repository, refreshing the token if the overall scope has increased Signed-off-by: Brian Bland <brian.bland@docker.com>
This commit is contained in:
parent
41e30f626b
commit
44d95e5841
1 changed files with 25 additions and 3 deletions
|
@ -108,6 +108,8 @@ type tokenHandler struct {
|
|||
tokenLock sync.Mutex
|
||||
tokenCache string
|
||||
tokenExpiration time.Time
|
||||
|
||||
additionalScopes map[string]struct{}
|
||||
}
|
||||
|
||||
// tokenScope represents the scope at which a token will be requested.
|
||||
|
@ -145,6 +147,7 @@ func newTokenHandler(transport http.RoundTripper, creds CredentialStore, c clock
|
|||
Scope: scope,
|
||||
Actions: actions,
|
||||
},
|
||||
additionalScopes: map[string]struct{}{},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -160,7 +163,15 @@ func (th *tokenHandler) Scheme() string {
|
|||
}
|
||||
|
||||
func (th *tokenHandler) AuthorizeRequest(req *http.Request, params map[string]string) error {
|
||||
if err := th.refreshToken(params); err != nil {
|
||||
var additionalScopes []string
|
||||
if fromParam := req.URL.Query().Get("from"); fromParam != "" {
|
||||
additionalScopes = append(additionalScopes, tokenScope{
|
||||
Resource: "repository",
|
||||
Scope: fromParam,
|
||||
Actions: []string{"pull"},
|
||||
}.String())
|
||||
}
|
||||
if err := th.refreshToken(params, additionalScopes...); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -169,11 +180,18 @@ func (th *tokenHandler) AuthorizeRequest(req *http.Request, params map[string]st
|
|||
return nil
|
||||
}
|
||||
|
||||
func (th *tokenHandler) refreshToken(params map[string]string) error {
|
||||
func (th *tokenHandler) refreshToken(params map[string]string, additionalScopes ...string) error {
|
||||
th.tokenLock.Lock()
|
||||
defer th.tokenLock.Unlock()
|
||||
var addedScopes bool
|
||||
for _, scope := range additionalScopes {
|
||||
if _, ok := th.additionalScopes[scope]; !ok {
|
||||
th.additionalScopes[scope] = struct{}{}
|
||||
addedScopes = true
|
||||
}
|
||||
}
|
||||
now := th.clock.Now()
|
||||
if now.After(th.tokenExpiration) {
|
||||
if now.After(th.tokenExpiration) || addedScopes {
|
||||
tr, err := th.fetchToken(params)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -223,6 +241,10 @@ func (th *tokenHandler) fetchToken(params map[string]string) (token *tokenRespon
|
|||
reqParams.Add("scope", scopeField)
|
||||
}
|
||||
|
||||
for scope := range th.additionalScopes {
|
||||
reqParams.Add("scope", scope)
|
||||
}
|
||||
|
||||
if th.creds != nil {
|
||||
username, password := th.creds.Basic(realmURL)
|
||||
if username != "" && password != "" {
|
||||
|
|
Loading…
Reference in a new issue