github.com/tompao/docker@v1.9.1/registry/token.go (about) 1 package registry 2 3 import ( 4 "encoding/json" 5 "errors" 6 "fmt" 7 "net/http" 8 "net/url" 9 "strings" 10 ) 11 12 type tokenResponse struct { 13 Token string `json:"token"` 14 } 15 16 func getToken(username, password string, params map[string]string, registryEndpoint *Endpoint) (string, error) { 17 realm, ok := params["realm"] 18 if !ok { 19 return "", errors.New("no realm specified for token auth challenge") 20 } 21 22 realmURL, err := url.Parse(realm) 23 if err != nil { 24 return "", fmt.Errorf("invalid token auth challenge realm: %s", err) 25 } 26 27 if realmURL.Scheme == "" { 28 if registryEndpoint.IsSecure { 29 realmURL.Scheme = "https" 30 } else { 31 realmURL.Scheme = "http" 32 } 33 } 34 35 req, err := http.NewRequest("GET", realmURL.String(), nil) 36 if err != nil { 37 return "", err 38 } 39 40 reqParams := req.URL.Query() 41 service := params["service"] 42 scope := params["scope"] 43 44 if service != "" { 45 reqParams.Add("service", service) 46 } 47 48 for _, scopeField := range strings.Fields(scope) { 49 reqParams.Add("scope", scopeField) 50 } 51 52 if username != "" { 53 reqParams.Add("account", username) 54 req.SetBasicAuth(username, password) 55 } 56 57 req.URL.RawQuery = reqParams.Encode() 58 59 resp, err := registryEndpoint.client.Do(req) 60 if err != nil { 61 return "", err 62 } 63 defer resp.Body.Close() 64 65 if resp.StatusCode != http.StatusOK { 66 return "", fmt.Errorf("token auth attempt for registry %s: %s request failed with status: %d %s", registryEndpoint, req.URL, resp.StatusCode, http.StatusText(resp.StatusCode)) 67 } 68 69 decoder := json.NewDecoder(resp.Body) 70 71 tr := new(tokenResponse) 72 if err = decoder.Decode(tr); err != nil { 73 return "", fmt.Errorf("unable to decode token response: %s", err) 74 } 75 76 if tr.Token == "" { 77 return "", errors.New("authorization server did not include a token in the response") 78 } 79 80 return tr.Token, nil 81 }