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
5df21570a7
commit
3a35a2d953
1 changed files with 25 additions and 3 deletions
|
@ -108,6 +108,8 @@ type tokenHandler struct {
|
||||||
tokenLock sync.Mutex
|
tokenLock sync.Mutex
|
||||||
tokenCache string
|
tokenCache string
|
||||||
tokenExpiration time.Time
|
tokenExpiration time.Time
|
||||||
|
|
||||||
|
additionalScopes map[string]struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// tokenScope represents the scope at which a token will be requested.
|
// 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,
|
Scope: scope,
|
||||||
Actions: actions,
|
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 {
|
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
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,11 +180,18 @@ func (th *tokenHandler) AuthorizeRequest(req *http.Request, params map[string]st
|
||||||
return nil
|
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()
|
th.tokenLock.Lock()
|
||||||
defer th.tokenLock.Unlock()
|
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()
|
now := th.clock.Now()
|
||||||
if now.After(th.tokenExpiration) {
|
if now.After(th.tokenExpiration) || addedScopes {
|
||||||
tr, err := th.fetchToken(params)
|
tr, err := th.fetchToken(params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -223,6 +241,10 @@ func (th *tokenHandler) fetchToken(params map[string]string) (token *tokenRespon
|
||||||
reqParams.Add("scope", scopeField)
|
reqParams.Add("scope", scopeField)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for scope := range th.additionalScopes {
|
||||||
|
reqParams.Add("scope", scope)
|
||||||
|
}
|
||||||
|
|
||||||
if th.creds != nil {
|
if th.creds != nil {
|
||||||
username, password := th.creds.Basic(realmURL)
|
username, password := th.creds.Basic(realmURL)
|
||||||
if username != "" && password != "" {
|
if username != "" && password != "" {
|
||||||
|
|
Loading…
Reference in a new issue