golang.org/x/oauth2@v0.18.0/google/externalaccount/urlcredsource.go (about) 1 // Copyright 2020 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package externalaccount 6 7 import ( 8 "context" 9 "encoding/json" 10 "errors" 11 "fmt" 12 "io" 13 "io/ioutil" 14 "net/http" 15 16 "golang.org/x/oauth2" 17 ) 18 19 type urlCredentialSource struct { 20 URL string 21 Headers map[string]string 22 Format Format 23 ctx context.Context 24 } 25 26 func (cs urlCredentialSource) credentialSourceType() string { 27 return "url" 28 } 29 30 func (cs urlCredentialSource) subjectToken() (string, error) { 31 client := oauth2.NewClient(cs.ctx, nil) 32 req, err := http.NewRequest("GET", cs.URL, nil) 33 if err != nil { 34 return "", fmt.Errorf("oauth2/google/externalaccount: HTTP request for URL-sourced credential failed: %v", err) 35 } 36 req = req.WithContext(cs.ctx) 37 38 for key, val := range cs.Headers { 39 req.Header.Add(key, val) 40 } 41 resp, err := client.Do(req) 42 if err != nil { 43 return "", fmt.Errorf("oauth2/google/externalaccount: invalid response when retrieving subject token: %v", err) 44 } 45 defer resp.Body.Close() 46 47 respBody, err := ioutil.ReadAll(io.LimitReader(resp.Body, 1<<20)) 48 if err != nil { 49 return "", fmt.Errorf("oauth2/google/externalaccount: invalid body in subject token URL query: %v", err) 50 } 51 if c := resp.StatusCode; c < 200 || c > 299 { 52 return "", fmt.Errorf("oauth2/google/externalaccount: status code %d: %s", c, respBody) 53 } 54 55 switch cs.Format.Type { 56 case "json": 57 jsonData := make(map[string]interface{}) 58 err = json.Unmarshal(respBody, &jsonData) 59 if err != nil { 60 return "", fmt.Errorf("oauth2/google/externalaccount: failed to unmarshal subject token file: %v", err) 61 } 62 val, ok := jsonData[cs.Format.SubjectTokenFieldName] 63 if !ok { 64 return "", errors.New("oauth2/google/externalaccount: provided subject_token_field_name not found in credentials") 65 } 66 token, ok := val.(string) 67 if !ok { 68 return "", errors.New("oauth2/google/externalaccount: improperly formatted subject token") 69 } 70 return token, nil 71 case "text": 72 return string(respBody), nil 73 case "": 74 return string(respBody), nil 75 default: 76 return "", errors.New("oauth2/google/externalaccount: invalid credential_source file format type") 77 } 78 79 }